• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 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 "vktTestGroupUtil.hpp"
27 #include "vktAmberTestCase.hpp"
28 #include "vktRasterizationTests.hpp"
29 #include "vktRasterizationFragShaderSideEffectsTests.hpp"
30 #ifndef CTS_USES_VULKANSC
31 #include "vktRasterizationProvokingVertexTests.hpp"
32 #endif // CTS_USES_VULKANSC
33 #include "tcuRasterizationVerifier.hpp"
34 #include "tcuSurface.hpp"
35 #include "tcuRenderTarget.hpp"
36 #include "tcuVectorUtil.hpp"
37 #include "tcuStringTemplate.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuResultCollector.hpp"
40 #include "tcuFloatFormat.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "vkImageUtil.hpp"
43 #include "deStringUtil.hpp"
44 #include "deRandom.hpp"
45 #include "vktTestCase.hpp"
46 #include "vktTestCaseUtil.hpp"
47 #include "vkPrograms.hpp"
48 #include "vkMemUtil.hpp"
49 #include "vkRefUtil.hpp"
50 #include "vkQueryUtil.hpp"
51 #include "vkBuilderUtil.hpp"
52 #include "vkTypeUtil.hpp"
53 #include "vkCmdUtil.hpp"
54 #include "vkObjUtil.hpp"
55 #include "vkBufferWithMemory.hpp"
56 #include "vkImageWithMemory.hpp"
57 #include "vkBarrierUtil.hpp"
58 #include "vkBufferWithMemory.hpp"
59 #ifndef CTS_USES_VULKANSC
60 #include "vktRasterizationOrderAttachmentAccessTests.hpp"
61 #include "vktRasterizationDepthBiasControlTests.hpp"
62 #include "vktShaderTileImageTests.hpp"
63 #endif // CTS_USES_VULKANSC
64 
65 #include <vector>
66 #include <sstream>
67 #include <memory>
68 
69 using namespace vk;
70 
71 namespace vkt
72 {
73 namespace rasterization
74 {
75 namespace
76 {
77 
78 using tcu::RasterizationArguments;
79 using tcu::TriangleSceneSpec;
80 using tcu::PointSceneSpec;
81 using tcu::LineSceneSpec;
82 
83 static const char* const s_shaderVertexTemplate =	"#version 310 es\n"
84 													"layout(location = 0) in highp vec4 a_position;\n"
85 													"layout(location = 1) in highp vec4 a_color;\n"
86 													"layout(location = 0) ${INTERPOLATION}out highp vec4 v_color;\n"
87 													"layout (set=0, binding=0) uniform PointSize {\n"
88 													"	highp float u_pointSize;\n"
89 													"};\n"
90 													"void main ()\n"
91 													"{\n"
92 													"	gl_Position = a_position;\n"
93 													"	gl_PointSize = u_pointSize;\n"
94 													"	v_color = a_color;\n"
95 													"}\n";
96 
97 static const char* const s_shaderFragmentTemplate =	"#version 310 es\n"
98 													"layout(location = 0) out highp vec4 fragColor;\n"
99 													"layout(location = 0) ${INTERPOLATION}in highp vec4 v_color;\n"
100 													"void main ()\n"
101 													"{\n"
102 													"	fragColor = v_color;\n"
103 													"}\n";
104 
105 enum InterpolationCaseFlags
106 {
107 	INTERPOLATIONFLAGS_NONE = 0,
108 	INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
109 	INTERPOLATIONFLAGS_FLATSHADE = (1 << 2),
110 };
111 
112 enum ResolutionValues
113 {
114 	RESOLUTION_POT = 256,
115 	RESOLUTION_NPOT = 258
116 };
117 
118 enum PrimitiveWideness
119 {
120 	PRIMITIVEWIDENESS_NARROW = 0,
121 	PRIMITIVEWIDENESS_WIDE,
122 
123 	PRIMITIVEWIDENESS_LAST
124 };
125 
126 enum LineStipple
127 {
128 	LINESTIPPLE_DISABLED = 0,
129 	LINESTIPPLE_STATIC,
130 	LINESTIPPLE_DYNAMIC,
131 	LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY,
132 
133 	LINESTIPPLE_LAST
134 };
135 
136 static const deUint32 lineStippleFactor = 2;
137 static const deUint32 lineStipplePattern = 0x0F0F;
138 
139 enum class LineStippleFactorCase
140 {
141 	DEFAULT	= 0,
142 	ZERO,
143 	LARGE,
144 };
145 
146 enum PrimitiveStrictness
147 {
148 	PRIMITIVESTRICTNESS_STRICT = 0,
149 	PRIMITIVESTRICTNESS_NONSTRICT,
150 	PRIMITIVESTRICTNESS_IGNORE,
151 
152 	PRIMITIVESTRICTNESS_LAST
153 };
154 
155 
156 class BaseRenderingTestCase : public TestCase
157 {
158 public:
159 								BaseRenderingTestCase	(tcu::TestContext& context, const std::string& name, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deBool flatshade = DE_FALSE);
160 	virtual						~BaseRenderingTestCase	(void);
161 
162 	virtual void				initPrograms			(vk::SourceCollections& programCollection) const;
163 
164 protected:
165 	const VkSampleCountFlagBits	m_sampleCount;
166 	const deBool				m_flatshade;
167 };
168 
BaseRenderingTestCase(tcu::TestContext & context,const std::string & name,VkSampleCountFlagBits sampleCount,deBool flatshade)169 BaseRenderingTestCase::BaseRenderingTestCase (tcu::TestContext& context, const std::string& name, VkSampleCountFlagBits sampleCount, deBool flatshade)
170 	: TestCase(context, name)
171 	, m_sampleCount	(sampleCount)
172 	, m_flatshade	(flatshade)
173 {
174 }
175 
initPrograms(vk::SourceCollections & programCollection) const176 void BaseRenderingTestCase::initPrograms (vk::SourceCollections& programCollection) const
177 {
178 	tcu::StringTemplate					vertexSource	(s_shaderVertexTemplate);
179 	tcu::StringTemplate					fragmentSource	(s_shaderFragmentTemplate);
180 	std::map<std::string, std::string>	params;
181 
182 	params["INTERPOLATION"] = (m_flatshade) ? ("flat ") : ("");
183 
184 	programCollection.glslSources.add("vertext_shader") << glu::VertexSource(vertexSource.specialize(params));
185 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fragmentSource.specialize(params));
186 }
187 
~BaseRenderingTestCase(void)188 BaseRenderingTestCase::~BaseRenderingTestCase (void)
189 {
190 }
191 
192 class BaseRenderingTestInstance : public TestInstance
193 {
194 public:
195 													BaseRenderingTestInstance		(Context& context, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT, deUint32 renderSize = RESOLUTION_POT, VkFormat imageFormat = VK_FORMAT_R8G8B8A8_UNORM, deUint32 additionalRenderSize = 0);
196 													~BaseRenderingTestInstance		(void);
197 
198 	const tcu::TextureFormat&						getTextureFormat				(void) const;
199 
200 protected:
201 	void											addImageTransitionBarrier		(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const;
202 	virtual void									drawPrimitives					(tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology);
203 	void											drawPrimitives					(tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, VkPrimitiveTopology primitiveTopology);
204 	void											drawPrimitives					(tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology,
205 																						VkImage image, VkImage resolvedImage, VkFramebuffer frameBuffer, const deUint32 renderSize, VkBuffer resultBuffer, const Allocation& resultBufferMemory);
206 	virtual float									getLineWidth					(void) const;
207 	virtual float									getPointSize					(void) const;
getLineStippleDynamic(void) const208 	virtual bool									getLineStippleDynamic			(void) const { return false; }
isDynamicTopology(void) const209 	virtual bool									isDynamicTopology				(void) const { return false; }
getWrongTopology(void) const210 	virtual VkPrimitiveTopology						getWrongTopology				(void) const { return VK_PRIMITIVE_TOPOLOGY_LAST; }
getRightTopology(void) const211 	virtual VkPrimitiveTopology						getRightTopology				(void) const { return VK_PRIMITIVE_TOPOLOGY_LAST; }
getOffScreenPoints(void) const212 	virtual std::vector<tcu::Vec4>					getOffScreenPoints				(void) const { return std::vector<tcu::Vec4>(); }
213 
214 	virtual
215 	const VkPipelineRasterizationStateCreateInfo*	getRasterizationStateCreateInfo	(void) const;
216 
217 	virtual
218 	VkPipelineRasterizationLineStateCreateInfoEXT	initLineRasterizationStateCreateInfo	(void) const;
219 
220 	virtual
221 	const VkPipelineRasterizationLineStateCreateInfoEXT*	getLineRasterizationStateCreateInfo	(void);
222 
223 	virtual
224 	const VkPipelineColorBlendStateCreateInfo*		getColorBlendStateCreateInfo	(void) const;
225 
226 	const deUint32									m_renderSize;
227 	const VkSampleCountFlagBits						m_sampleCount;
228 	deUint32										m_subpixelBits;
229 	const deBool									m_multisampling;
230 
231 	const VkFormat									m_imageFormat;
232 	const tcu::TextureFormat						m_textureFormat;
233 	Move<VkCommandPool>								m_commandPool;
234 
235 	Move<VkImage>									m_image;
236 	de::MovePtr<Allocation>							m_imageMemory;
237 	Move<VkImageView>								m_imageView;
238 
239 	Move<VkImage>									m_resolvedImage;
240 	de::MovePtr<Allocation>							m_resolvedImageMemory;
241 	Move<VkImageView>								m_resolvedImageView;
242 
243 	Move<VkRenderPass>								m_renderPass;
244 	Move<VkFramebuffer>								m_frameBuffer;
245 
246 	Move<VkDescriptorPool>							m_descriptorPool;
247 	Move<VkDescriptorSet>							m_descriptorSet;
248 	Move<VkDescriptorSetLayout>						m_descriptorSetLayout;
249 
250 	Move<VkBuffer>									m_uniformBuffer;
251 	de::MovePtr<Allocation>							m_uniformBufferMemory;
252 	const VkDeviceSize								m_uniformBufferSize;
253 
254 	Move<VkPipelineLayout>							m_pipelineLayout;
255 
256 	Move<VkShaderModule>							m_vertexShaderModule;
257 	Move<VkShaderModule>							m_fragmentShaderModule;
258 
259 	Move<VkBuffer>									m_resultBuffer;
260 	de::MovePtr<Allocation>							m_resultBufferMemory;
261 	const VkDeviceSize								m_resultBufferSize;
262 
263 	const deUint32									m_additionalRenderSize;
264 	const VkDeviceSize								m_additionalResultBufferSize;
265 
266 	VkPipelineRasterizationLineStateCreateInfoEXT	m_lineRasterizationStateInfo;
267 
268 private:
getIteration(void) const269 	virtual int										getIteration					(void) const { TCU_THROW(InternalError, "Iteration undefined in the base class"); }
270 };
271 
BaseRenderingTestInstance(Context & context,VkSampleCountFlagBits sampleCount,deUint32 renderSize,VkFormat imageFormat,deUint32 additionalRenderSize)272 BaseRenderingTestInstance::BaseRenderingTestInstance (Context& context, VkSampleCountFlagBits sampleCount, deUint32 renderSize, VkFormat imageFormat, deUint32 additionalRenderSize)
273 	: TestInstance			(context)
274 	, m_renderSize			(renderSize)
275 	, m_sampleCount			(sampleCount)
276 	, m_subpixelBits		(context.getDeviceProperties().limits.subPixelPrecisionBits)
277 	, m_multisampling		(m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
278 	, m_imageFormat			(imageFormat)
279 	, m_textureFormat		(vk::mapVkFormat(m_imageFormat))
280 	, m_uniformBufferSize	(sizeof(float))
281 	, m_resultBufferSize	(renderSize * renderSize * m_textureFormat.getPixelSize())
282 	, m_additionalRenderSize(additionalRenderSize)
283 	, m_additionalResultBufferSize(additionalRenderSize * additionalRenderSize * m_textureFormat.getPixelSize())
284 	, m_lineRasterizationStateInfo	()
285 {
286 	const DeviceInterface&						vkd						= m_context.getDeviceInterface();
287 	const VkDevice								vkDevice				= m_context.getDevice();
288 	const deUint32								queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
289 	Allocator&									allocator				= m_context.getDefaultAllocator();
290 	DescriptorPoolBuilder						descriptorPoolBuilder;
291 	DescriptorSetLayoutBuilder					descriptorSetLayoutBuilder;
292 
293 	// Command Pool
294 	m_commandPool = createCommandPool(vkd, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
295 
296 	// Image
297 	{
298 		const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
299 		VkImageFormatProperties	properties;
300 
301 		if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
302 																					 m_imageFormat,
303 																					 VK_IMAGE_TYPE_2D,
304 																					 VK_IMAGE_TILING_OPTIMAL,
305 																					 imageUsage,
306 																					 0,
307 																					 &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
308 		{
309 			TCU_THROW(NotSupportedError, "Format not supported");
310 		}
311 
312 		if ((properties.sampleCounts & m_sampleCount) != m_sampleCount)
313 		{
314 			TCU_THROW(NotSupportedError, "Format not supported");
315 		}
316 
317 		const VkImageCreateInfo					imageCreateInfo			=
318 		{
319 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
320 			DE_NULL,									// const void*				pNext;
321 			0u,											// VkImageCreateFlags		flags;
322 			VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
323 			m_imageFormat,								// VkFormat					format;
324 			{ m_renderSize,	m_renderSize, 1u },			// VkExtent3D				extent;
325 			1u,											// deUint32					mipLevels;
326 			1u,											// deUint32					arrayLayers;
327 			m_sampleCount,								// VkSampleCountFlagBits	samples;
328 			VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
329 			imageUsage,									// VkImageUsageFlags		usage;
330 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
331 			1u,											// deUint32					queueFamilyIndexCount;
332 			&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
333 			VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
334 		};
335 
336 		m_image = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
337 
338 		m_imageMemory	= allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_image), MemoryRequirement::Any);
339 		VK_CHECK(vkd.bindImageMemory(vkDevice, *m_image, m_imageMemory->getMemory(), m_imageMemory->getOffset()));
340 	}
341 
342 	// Image View
343 	{
344 		const VkImageViewCreateInfo				imageViewCreateInfo		=
345 		{
346 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
347 			DE_NULL,									// const void*					pNext;
348 			0u,											// VkImageViewCreateFlags		flags;
349 			*m_image,									// VkImage						image;
350 			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
351 			m_imageFormat,								// VkFormat						format;
352 			makeComponentMappingRGBA(),					// VkComponentMapping			components;
353 			{
354 				VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
355 				0u,											// deUint32						baseMipLevel;
356 				1u,											// deUint32						mipLevels;
357 				0u,											// deUint32						baseArrayLayer;
358 				1u,											// deUint32						arraySize;
359 			},											// VkImageSubresourceRange		subresourceRange;
360 		};
361 
362 		m_imageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
363 	}
364 
365 	if (m_multisampling)
366 	{
367 		{
368 			// Resolved Image
369 			const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
370 			VkImageFormatProperties	properties;
371 
372 			if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
373 																						 m_imageFormat,
374 																						 VK_IMAGE_TYPE_2D,
375 																						 VK_IMAGE_TILING_OPTIMAL,
376 																						 imageUsage,
377 																						 0,
378 																						 &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
379 			{
380 				TCU_THROW(NotSupportedError, "Format not supported");
381 			}
382 
383 			const VkImageCreateInfo					imageCreateInfo			=
384 			{
385 				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
386 				DE_NULL,									// const void*				pNext;
387 				0u,											// VkImageCreateFlags		flags;
388 				VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
389 				m_imageFormat,								// VkFormat					format;
390 				{ m_renderSize,	m_renderSize, 1u },			// VkExtent3D				extent;
391 				1u,											// deUint32					mipLevels;
392 				1u,											// deUint32					arrayLayers;
393 				VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples;
394 				VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
395 				imageUsage,									// VkImageUsageFlags		usage;
396 				VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
397 				1u,											// deUint32					queueFamilyIndexCount;
398 				&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
399 				VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
400 			};
401 
402 			m_resolvedImage			= vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
403 			m_resolvedImageMemory	= allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_resolvedImage), MemoryRequirement::Any);
404 			VK_CHECK(vkd.bindImageMemory(vkDevice, *m_resolvedImage, m_resolvedImageMemory->getMemory(), m_resolvedImageMemory->getOffset()));
405 		}
406 
407 		// Resolved Image View
408 		{
409 			const VkImageViewCreateInfo				imageViewCreateInfo		=
410 			{
411 				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
412 				DE_NULL,									// const void*					pNext;
413 				0u,											// VkImageViewCreateFlags		flags;
414 				*m_resolvedImage,							// VkImage						image;
415 				VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
416 				m_imageFormat,								// VkFormat						format;
417 				makeComponentMappingRGBA(),					// VkComponentMapping			components;
418 				{
419 					VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
420 					0u,											// deUint32						baseMipLevel;
421 					1u,											// deUint32						mipLevels;
422 					0u,											// deUint32						baseArrayLayer;
423 					1u,											// deUint32						arraySize;
424 				},											// VkImageSubresourceRange		subresourceRange;
425 			};
426 
427 			m_resolvedImageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
428 		}
429 
430 	}
431 
432 	// Render Pass
433 	{
434 		const VkImageLayout						imageLayout				= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
435 		const VkAttachmentDescription			attachmentDesc[]		=
436 		{
437 			{
438 				0u,													// VkAttachmentDescriptionFlags		flags;
439 				m_imageFormat,										// VkFormat							format;
440 				m_sampleCount,										// VkSampleCountFlagBits			samples;
441 				VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
442 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
443 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
444 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
445 				imageLayout,										// VkImageLayout					initialLayout;
446 				imageLayout,										// VkImageLayout					finalLayout;
447 			},
448 			{
449 				0u,													// VkAttachmentDescriptionFlags		flags;
450 				m_imageFormat,										// VkFormat							format;
451 				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
452 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				loadOp;
453 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
454 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
455 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
456 				imageLayout,										// VkImageLayout					initialLayout;
457 				imageLayout,										// VkImageLayout					finalLayout;
458 			}
459 		};
460 
461 		const VkAttachmentReference				attachmentRef			=
462 		{
463 			0u,													// deUint32							attachment;
464 			imageLayout,										// VkImageLayout					layout;
465 		};
466 
467 		const VkAttachmentReference				resolveAttachmentRef	=
468 		{
469 			1u,													// deUint32							attachment;
470 			imageLayout,										// VkImageLayout					layout;
471 		};
472 
473 		const VkSubpassDescription				subpassDesc				=
474 		{
475 			0u,													// VkSubpassDescriptionFlags		flags;
476 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
477 			0u,													// deUint32							inputAttachmentCount;
478 			DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
479 			1u,													// deUint32							colorAttachmentCount;
480 			&attachmentRef,										// const VkAttachmentReference*		pColorAttachments;
481 			m_multisampling ? &resolveAttachmentRef : DE_NULL,	// const VkAttachmentReference*		pResolveAttachments;
482 			DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
483 			0u,													// deUint32							preserveAttachmentCount;
484 			DE_NULL,											// const VkAttachmentReference*		pPreserveAttachments;
485 		};
486 
487 		const VkRenderPassCreateInfo			renderPassCreateInfo	=
488 		{
489 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
490 			DE_NULL,											// const void*						pNext;
491 			0u,													// VkRenderPassCreateFlags			flags;
492 			m_multisampling ? 2u : 1u,							// deUint32							attachmentCount;
493 			attachmentDesc,										// const VkAttachmentDescription*	pAttachments;
494 			1u,													// deUint32							subpassCount;
495 			&subpassDesc,										// const VkSubpassDescription*		pSubpasses;
496 			0u,													// deUint32							dependencyCount;
497 			DE_NULL,											// const VkSubpassDependency*		pDependencies;
498 		};
499 
500 		m_renderPass =  createRenderPass(vkd, vkDevice, &renderPassCreateInfo, DE_NULL);
501 	}
502 
503 	// FrameBuffer
504 	{
505 		const VkImageView						attachments[]			=
506 		{
507 			*m_imageView,
508 			*m_resolvedImageView
509 		};
510 
511 		const VkFramebufferCreateInfo			framebufferCreateInfo	=
512 		{
513 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
514 			DE_NULL,									// const void*				pNext;
515 			0u,											// VkFramebufferCreateFlags	flags;
516 			*m_renderPass,								// VkRenderPass				renderPass;
517 			m_multisampling ? 2u : 1u,					// deUint32					attachmentCount;
518 			attachments,								// const VkImageView*		pAttachments;
519 			m_renderSize,								// deUint32					width;
520 			m_renderSize,								// deUint32					height;
521 			1u,											// deUint32					layers;
522 		};
523 
524 		m_frameBuffer = createFramebuffer(vkd, vkDevice, &framebufferCreateInfo, DE_NULL);
525 	}
526 
527 	// Uniform Buffer
528 	{
529 		const VkBufferCreateInfo				bufferCreateInfo		=
530 		{
531 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
532 			DE_NULL,									// const void*			pNext;
533 			0u,											// VkBufferCreateFlags	flags;
534 			m_uniformBufferSize,						// VkDeviceSize			size;
535 			VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,			// VkBufferUsageFlags	usage;
536 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
537 			1u,											// deUint32				queueFamilyIndexCount;
538 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
539 		};
540 
541 		m_uniformBuffer			= createBuffer(vkd, vkDevice, &bufferCreateInfo);
542 		m_uniformBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
543 
544 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset()));
545 	}
546 
547 	// Descriptors
548 	{
549 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
550 		m_descriptorPool = descriptorPoolBuilder.build(vkd, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
551 
552 		descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_ALL);
553 		m_descriptorSetLayout = descriptorSetLayoutBuilder.build(vkd, vkDevice);
554 
555 		const VkDescriptorSetAllocateInfo		descriptorSetParams		=
556 		{
557 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
558 			DE_NULL,
559 			*m_descriptorPool,
560 			1u,
561 			&m_descriptorSetLayout.get(),
562 		};
563 
564 		m_descriptorSet = allocateDescriptorSet(vkd, vkDevice, &descriptorSetParams);
565 
566 		const VkDescriptorBufferInfo			descriptorBufferInfo	=
567 		{
568 			*m_uniformBuffer,							// VkBuffer		buffer;
569 			0u,											// VkDeviceSize	offset;
570 			VK_WHOLE_SIZE								// VkDeviceSize	range;
571 		};
572 
573 		const VkWriteDescriptorSet				writeDescritporSet		=
574 		{
575 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,		// VkStructureType					sType;
576 			DE_NULL,									// const void*						pNext;
577 			*m_descriptorSet,							// VkDescriptorSet					destSet;
578 			0,											// deUint32							destBinding;
579 			0,											// deUint32							destArrayElement;
580 			1u,											// deUint32							count;
581 			VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,			// VkDescriptorType					descriptorType;
582 			DE_NULL,									// const VkDescriptorImageInfo*		pImageInfo;
583 			&descriptorBufferInfo,						// const VkDescriptorBufferInfo*	pBufferInfo;
584 			DE_NULL										// const VkBufferView*				pTexelBufferView;
585 		};
586 
587 		vkd.updateDescriptorSets(vkDevice, 1u, &writeDescritporSet, 0u, DE_NULL);
588 	}
589 
590 	// Pipeline Layout
591 	{
592 		const VkPipelineLayoutCreateInfo		pipelineLayoutCreateInfo	=
593 		{
594 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
595 			DE_NULL,											// const void*					pNext;
596 			0u,													// VkPipelineLayoutCreateFlags	flags;
597 			1u,													// deUint32						descriptorSetCount;
598 			&m_descriptorSetLayout.get(),						// const VkDescriptorSetLayout*	pSetLayouts;
599 			0u,													// deUint32						pushConstantRangeCount;
600 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
601 		};
602 
603 		m_pipelineLayout = createPipelineLayout(vkd, vkDevice, &pipelineLayoutCreateInfo);
604 	}
605 
606 	// Shaders
607 	{
608 		m_vertexShaderModule	= createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("vertext_shader"), 0);
609 		m_fragmentShaderModule	= createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("fragment_shader"), 0);
610 	}
611 
612 	// Result Buffer
613 	{
614 		const VkBufferCreateInfo				bufferCreateInfo		=
615 		{
616 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
617 			DE_NULL,									// const void*			pNext;
618 			0u,											// VkBufferCreateFlags	flags;
619 			m_resultBufferSize,							// VkDeviceSize			size;
620 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
621 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
622 			1u,											// deUint32				queueFamilyIndexCount;
623 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
624 		};
625 
626 		m_resultBuffer			= createBuffer(vkd, vkDevice, &bufferCreateInfo);
627 		m_resultBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
628 
629 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset()));
630 	}
631 
632 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Sample count = " << getSampleCountFlagsStr(m_sampleCount) << tcu::TestLog::EndMessage;
633 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage;
634 }
635 
~BaseRenderingTestInstance(void)636 BaseRenderingTestInstance::~BaseRenderingTestInstance (void)
637 {
638 }
639 
640 
addImageTransitionBarrier(VkCommandBuffer commandBuffer,VkImage image,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkAccessFlags srcAccessMask,VkAccessFlags dstAccessMask,VkImageLayout oldLayout,VkImageLayout newLayout) const641 void BaseRenderingTestInstance::addImageTransitionBarrier(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const
642 {
643 
644 	const DeviceInterface&			vkd					= m_context.getDeviceInterface();
645 
646 	const VkImageSubresourceRange	subResourcerange	=
647 	{
648 		VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
649 		0,								// deUint32				baseMipLevel;
650 		1,								// deUint32				levelCount;
651 		0,								// deUint32				baseArrayLayer;
652 		1								// deUint32				layerCount;
653 	};
654 
655 	const VkImageMemoryBarrier		imageBarrier		=
656 	{
657 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
658 		DE_NULL,									// const void*				pNext;
659 		srcAccessMask,								// VkAccessFlags			srcAccessMask;
660 		dstAccessMask,								// VkAccessFlags			dstAccessMask;
661 		oldLayout,									// VkImageLayout			oldLayout;
662 		newLayout,									// VkImageLayout			newLayout;
663 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
664 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
665 		image,										// VkImage					image;
666 		subResourcerange							// VkImageSubresourceRange	subresourceRange;
667 	};
668 
669 	vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
670 }
671 
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & vertexData,VkPrimitiveTopology primitiveTopology)672 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology)
673 {
674 	// default to color white
675 	const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
676 
677 	drawPrimitives(result, vertexData, colorData, primitiveTopology);
678 }
679 
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & positionData,const std::vector<tcu::Vec4> & colorData,VkPrimitiveTopology primitiveTopology)680 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology)
681 {
682 	drawPrimitives(result, positionData, colorData, primitiveTopology, *m_image, *m_resolvedImage, *m_frameBuffer, m_renderSize, *m_resultBuffer, *m_resultBufferMemory);
683 }
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & positionData,const std::vector<tcu::Vec4> & colorData,VkPrimitiveTopology primitiveTopology,VkImage image,VkImage resolvedImage,VkFramebuffer frameBuffer,const deUint32 renderSize,VkBuffer resultBuffer,const Allocation & resultBufferMemory)684 void BaseRenderingTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, const std::vector<tcu::Vec4>& colorData, VkPrimitiveTopology primitiveTopology,
685 					VkImage image, VkImage resolvedImage, VkFramebuffer frameBuffer, const deUint32 renderSize, VkBuffer resultBuffer, const Allocation& resultBufferMemory)
686 {
687 	const DeviceInterface&						vkd						= m_context.getDeviceInterface();
688 	const VkDevice								vkDevice				= m_context.getDevice();
689 	const VkQueue								queue					= m_context.getUniversalQueue();
690 	const deUint32								queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
691 	Allocator&									allocator				= m_context.getDefaultAllocator();
692 	const size_t								attributeBatchSize		= de::dataSize(positionData);
693 	const auto									offscreenData			= getOffScreenPoints();
694 
695 	Move<VkCommandBuffer>						commandBuffer;
696 	Move<VkPipeline>							graphicsPipeline;
697 	Move<VkBuffer>								vertexBuffer;
698 	de::MovePtr<Allocation>						vertexBufferMemory;
699 	std::unique_ptr<BufferWithMemory>			offscreenDataBuffer;
700 	const VkPhysicalDeviceProperties			properties				= m_context.getDeviceProperties();
701 
702 	if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
703 	{
704 		std::stringstream message;
705 		message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
706 		TCU_THROW(NotSupportedError, message.str().c_str());
707 	}
708 
709 	// Create Graphics Pipeline
710 	{
711 		const VkVertexInputBindingDescription	vertexInputBindingDescription =
712 		{
713 			0u,								// deUint32					binding;
714 			sizeof(tcu::Vec4),				// deUint32					strideInBytes;
715 			VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	stepRate;
716 		};
717 
718 		const VkVertexInputAttributeDescription	vertexInputAttributeDescriptions[2] =
719 		{
720 			{
721 				0u,									// deUint32	location;
722 				0u,									// deUint32	binding;
723 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
724 				0u									// deUint32	offsetInBytes;
725 			},
726 			{
727 				1u,									// deUint32	location;
728 				0u,									// deUint32	binding;
729 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
730 				(deUint32)attributeBatchSize		// deUint32	offsetInBytes;
731 			}
732 		};
733 
734 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams =
735 		{
736 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
737 			DE_NULL,														// const void*								pNext;
738 			0,																// VkPipelineVertexInputStateCreateFlags	flags;
739 			1u,																// deUint32									bindingCount;
740 			&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
741 			2u,																// deUint32									attributeCount;
742 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
743 		};
744 
745 		const std::vector<VkViewport>	viewports	(1, makeViewport(tcu::UVec2(renderSize)));
746 		const std::vector<VkRect2D>		scissors	(1, makeRect2D(tcu::UVec2(renderSize)));
747 
748 		const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
749 		{
750 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
751 			DE_NULL,														// const void*								pNext;
752 			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
753 			m_sampleCount,													// VkSampleCountFlagBits					rasterizationSamples;
754 			VK_FALSE,														// VkBool32									sampleShadingEnable;
755 			0.0f,															// float									minSampleShading;
756 			DE_NULL,														// const VkSampleMask*						pSampleMask;
757 			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
758 			VK_FALSE														// VkBool32									alphaToOneEnable;
759 		};
760 
761 
762 		VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = *getRasterizationStateCreateInfo();
763 
764 		const VkPipelineRasterizationLineStateCreateInfoEXT* lineRasterizationStateInfo = getLineRasterizationStateCreateInfo();
765 
766 		if (lineRasterizationStateInfo != DE_NULL && lineRasterizationStateInfo->sType != 0)
767 			appendStructurePtrToVulkanChain(&rasterizationStateInfo.pNext, lineRasterizationStateInfo);
768 
769 		VkPipelineDynamicStateCreateInfo			dynamicStateCreateInfo =
770 		{
771 			VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	// VkStructureType                      sType
772 			DE_NULL,												// const void*                          pNext
773 			0u,														// VkPipelineDynamicStateCreateFlags    flags
774 			0u,														// deUint32                             dynamicStateCount
775 			DE_NULL													// const VkDynamicState*                pDynamicStates
776 		};
777 
778 		std::vector<VkDynamicState> dynamicStates;
779 
780 		if (getLineStippleDynamic())
781 			dynamicStates.push_back(VK_DYNAMIC_STATE_LINE_STIPPLE_EXT);
782 
783 #ifndef CTS_USES_VULKANSC
784 		if (isDynamicTopology())
785 			dynamicStates.push_back(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY);
786 #endif // CTS_USES_VULKANSC
787 
788 		if (getLineStippleDynamic())
789 		{
790 			dynamicStateCreateInfo.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
791 			dynamicStateCreateInfo.pDynamicStates = de::dataOrNull(dynamicStates);
792 		}
793 
794 		graphicsPipeline = makeGraphicsPipeline(vkd,								// const DeviceInterface&                        vk
795 												vkDevice,							// const VkDevice                                device
796 												*m_pipelineLayout,					// const VkPipelineLayout                        pipelineLayout
797 												*m_vertexShaderModule,				// const VkShaderModule                          vertexShaderModule
798 												DE_NULL,							// const VkShaderModule                          tessellationControlShaderModule
799 												DE_NULL,							// const VkShaderModule                          tessellationEvalShaderModule
800 												DE_NULL,							// const VkShaderModule                          geometryShaderModule
801 												rasterizationStateInfo.rasterizerDiscardEnable ? DE_NULL : *m_fragmentShaderModule,
802 																					// const VkShaderModule                          fragmentShaderModule
803 												*m_renderPass,						// const VkRenderPass                            renderPass
804 												viewports,							// const std::vector<VkViewport>&                viewports
805 												scissors,							// const std::vector<VkRect2D>&                  scissors
806 												primitiveTopology,					// const VkPrimitiveTopology                     topology
807 												0u,									// const deUint32                                subpass
808 												0u,									// const deUint32                                patchControlPoints
809 												&vertexInputStateParams,			// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
810 												&rasterizationStateInfo,			// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
811 												&multisampleStateParams,			// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
812 												DE_NULL,							// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo,
813 												getColorBlendStateCreateInfo(),		// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo,
814 												&dynamicStateCreateInfo);			// const VkPipelineDynamicStateCreateInfo*       dynamicStateCreateInfo
815 	}
816 
817 	// Create Vertex Buffer
818 	{
819 		const VkBufferCreateInfo			vertexBufferParams		=
820 		{
821 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
822 			DE_NULL,									// const void*			pNext;
823 			0u,											// VkBufferCreateFlags	flags;
824 			attributeBatchSize * 2,						// VkDeviceSize			size;
825 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
826 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
827 			1u,											// deUint32				queueFamilyCount;
828 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
829 		};
830 
831 		vertexBuffer		= createBuffer(vkd, vkDevice, &vertexBufferParams);
832 		vertexBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
833 
834 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
835 
836 		// Load vertices into vertex buffer
837 		deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
838 		deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) +  attributeBatchSize, colorData.data(), attributeBatchSize);
839 		flushAlloc(vkd, vkDevice, *vertexBufferMemory);
840 	}
841 
842 	if (!offscreenData.empty())
843 	{
844 		// Concatenate positions with vertex colors.
845 		const std::vector<tcu::Vec4>	colors				(offscreenData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
846 		std::vector<tcu::Vec4>			fullOffscreenData	(offscreenData);
847 		fullOffscreenData.insert(fullOffscreenData.end(), colors.begin(), colors.end());
848 
849 		// Copy full data to offscreen data buffer.
850 		const auto offscreenBufferSizeSz	= de::dataSize(fullOffscreenData);
851 		const auto offscreenBufferSize		= static_cast<VkDeviceSize>(offscreenBufferSizeSz);
852 		const auto offscreenDataCreateInfo	= makeBufferCreateInfo(offscreenBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
853 
854 		offscreenDataBuffer	.reset(new BufferWithMemory(vkd, vkDevice, allocator, offscreenDataCreateInfo, MemoryRequirement::HostVisible));
855 		auto& bufferAlloc	= offscreenDataBuffer->getAllocation();
856 		void* dataPtr		= bufferAlloc.getHostPtr();
857 
858 		deMemcpy(dataPtr, fullOffscreenData.data(), offscreenBufferSizeSz);
859 		flushAlloc(vkd, vkDevice, bufferAlloc);
860 	}
861 
862 	// Create Command Buffer
863 	commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
864 
865 	// Begin Command Buffer
866 	beginCommandBuffer(vkd, *commandBuffer);
867 
868 	addImageTransitionBarrier(*commandBuffer, image,
869 							  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags		srcStageMask
870 							  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,				// VkPipelineStageFlags		dstStageMask
871 							  0,												// VkAccessFlags			srcAccessMask
872 							  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask
873 							  VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
874 							  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);		// VkImageLayout			newLayout;
875 
876 	if (m_multisampling) {
877 		addImageTransitionBarrier(*commandBuffer, resolvedImage,
878 								  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags		srcStageMask
879 								  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,				// VkPipelineStageFlags		dstStageMask
880 								  0,												// VkAccessFlags			srcAccessMask
881 								  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask
882 								  VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
883 								  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);		// VkImageLayout			newLayout;
884 	}
885 
886 	// Begin Render Pass
887 	beginRenderPass(vkd, *commandBuffer, *m_renderPass, frameBuffer, vk::makeRect2D(0, 0, renderSize, renderSize), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
888 
889 	const VkDeviceSize						vertexBufferOffset		= 0;
890 
891 	vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
892 	vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
893 	if (getLineStippleDynamic())
894 	{
895 		vkd.cmdSetLineStippleEXT(*commandBuffer, lineStippleFactor, lineStipplePattern);
896 #ifndef CTS_USES_VULKANSC
897 		if (isDynamicTopology())
898 		{
899 			// Using a dynamic topology can interact with the dynamic line stipple set above on some implementations, so we try to
900 			// check nothing breaks here. We set a wrong topology, draw some offscreen data and go back to the right topology
901 			// _without_ re-setting the line stipple again. Side effects should not be visible.
902 			DE_ASSERT(!!offscreenDataBuffer);
903 
904 			vkd.cmdSetPrimitiveTopology(*commandBuffer, getWrongTopology());
905 			vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &offscreenDataBuffer->get(), &vertexBufferOffset);
906 			vkd.cmdDraw(*commandBuffer, static_cast<uint32_t>(offscreenData.size()), 1u, 0u, 0u);
907 			vkd.cmdSetPrimitiveTopology(*commandBuffer, getRightTopology());
908 		}
909 #endif // CTS_USES_VULKANSC
910 	}
911 	vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
912 	vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
913 	endRenderPass(vkd, *commandBuffer);
914 
915 	// Copy Image
916 	copyImageToBuffer(vkd, *commandBuffer, m_multisampling ? resolvedImage : image, resultBuffer, tcu::IVec2(renderSize, renderSize));
917 
918 	endCommandBuffer(vkd, *commandBuffer);
919 
920 	// Set Point Size
921 	{
922 		float	pointSize	= getPointSize();
923 		deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
924 		flushAlloc(vkd, vkDevice, *m_uniformBufferMemory);
925 	}
926 
927 	// Submit
928 	submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
929 
930 	invalidateAlloc(vkd, vkDevice, resultBufferMemory);
931 	tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(renderSize, renderSize, 1), resultBufferMemory.getHostPtr()));
932 }
933 
getLineWidth(void) const934 float BaseRenderingTestInstance::getLineWidth (void) const
935 {
936 	return 1.0f;
937 }
938 
getPointSize(void) const939 float BaseRenderingTestInstance::getPointSize (void) const
940 {
941 	return 1.0f;
942 }
943 
getRasterizationStateCreateInfo(void) const944 const VkPipelineRasterizationStateCreateInfo* BaseRenderingTestInstance::getRasterizationStateCreateInfo (void) const
945 {
946 	static VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
947 	{
948 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
949 		DE_NULL,														// const void*								pNext;
950 		0,																// VkPipelineRasterizationStateCreateFlags	flags;
951 		false,															// VkBool32									depthClipEnable;
952 		false,															// VkBool32									rasterizerDiscardEnable;
953 		VK_POLYGON_MODE_FILL,											// VkFillMode								fillMode;
954 		VK_CULL_MODE_NONE,												// VkCullMode								cullMode;
955 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
956 		VK_FALSE,														// VkBool32									depthBiasEnable;
957 		0.0f,															// float									depthBias;
958 		0.0f,															// float									depthBiasClamp;
959 		0.0f,															// float									slopeScaledDepthBias;
960 		getLineWidth(),													// float									lineWidth;
961 	};
962 
963 	rasterizationStateCreateInfo.lineWidth = getLineWidth();
964 	return &rasterizationStateCreateInfo;
965 }
966 
initLineRasterizationStateCreateInfo(void) const967 VkPipelineRasterizationLineStateCreateInfoEXT BaseRenderingTestInstance::initLineRasterizationStateCreateInfo (void) const
968 {
969 	VkPipelineRasterizationLineStateCreateInfoEXT lineRasterizationStateInfo =
970 	{
971 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT,	// VkStructureType				sType;
972 		DE_NULL,																// const void*					pNext;
973 		VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT,									// VkLineRasterizationModeEXT	lineRasterizationMode;
974 		VK_FALSE,																// VkBool32						stippledLineEnable;
975 		1,																		// uint32_t						lineStippleFactor;
976 		0xFFFF,																	// uint16_t						lineStipplePattern;
977 	};
978 
979 	return lineRasterizationStateInfo;
980 }
981 
getLineRasterizationStateCreateInfo(void)982 const VkPipelineRasterizationLineStateCreateInfoEXT* BaseRenderingTestInstance::getLineRasterizationStateCreateInfo (void)
983 {
984 	if (m_lineRasterizationStateInfo.sType != VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT)
985 		m_lineRasterizationStateInfo = initLineRasterizationStateCreateInfo();
986 
987 	return &m_lineRasterizationStateInfo;
988 }
989 
getColorBlendStateCreateInfo(void) const990 const VkPipelineColorBlendStateCreateInfo* BaseRenderingTestInstance::getColorBlendStateCreateInfo (void) const
991 {
992 	static const VkPipelineColorBlendAttachmentState	colorBlendAttachmentState	=
993 	{
994 		false,														// VkBool32			blendEnable;
995 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendColor;
996 		VK_BLEND_FACTOR_ZERO,										// VkBlend			destBlendColor;
997 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpColor;
998 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendAlpha;
999 		VK_BLEND_FACTOR_ZERO,										// VkBlend			destBlendAlpha;
1000 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpAlpha;
1001 		(VK_COLOR_COMPONENT_R_BIT |
1002 		 VK_COLOR_COMPONENT_G_BIT |
1003 		 VK_COLOR_COMPONENT_B_BIT |
1004 		 VK_COLOR_COMPONENT_A_BIT)									// VkChannelFlags	channelWriteMask;
1005 	};
1006 
1007 	static const VkPipelineColorBlendStateCreateInfo	colorBlendStateParams		=
1008 	{
1009 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1010 		DE_NULL,													// const void*									pNext;
1011 		0,															// VkPipelineColorBlendStateCreateFlags			flags;
1012 		false,														// VkBool32										logicOpEnable;
1013 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1014 		1u,															// deUint32										attachmentCount;
1015 		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
1016 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
1017 	};
1018 
1019 	return &colorBlendStateParams;
1020 }
1021 
getTextureFormat(void) const1022 const tcu::TextureFormat& BaseRenderingTestInstance::getTextureFormat (void) const
1023 {
1024 	return m_textureFormat;
1025 }
1026 
1027 class BaseTriangleTestInstance : public BaseRenderingTestInstance
1028 {
1029 public:
1030 							BaseTriangleTestInstance	(Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount, deUint32 renderSize = RESOLUTION_POT);
1031 	virtual tcu::TestStatus	iterate						(void);
1032 
1033 protected:
getIteration(void) const1034 	int						getIteration				(void) const	{ return m_iteration;		}
getIterationCount(void) const1035 	int						getIterationCount			(void) const	{ return m_iterationCount;	}
1036 
1037 private:
1038 	virtual void			generateTriangles			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
1039 	virtual bool			compareAndVerify			(std::vector<TriangleSceneSpec::SceneTriangle>&	triangles,
1040 														 tcu::Surface&									resultImage,
1041 														 std::vector<tcu::Vec4>&						drawBuffer);
1042 
1043 	int						m_iteration;
1044 	const int				m_iterationCount;
1045 	VkPrimitiveTopology		m_primitiveTopology;
1046 	bool					m_allIterationsPassed;
1047 };
1048 
BaseTriangleTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,VkSampleCountFlagBits sampleCount,deUint32 renderSize)1049 BaseTriangleTestInstance::BaseTriangleTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, VkSampleCountFlagBits sampleCount, deUint32 renderSize)
1050 	: BaseRenderingTestInstance		(context, sampleCount, renderSize)
1051 	, m_iteration					(0)
1052 	, m_iterationCount				(3)
1053 	, m_primitiveTopology			(primitiveTopology)
1054 	, m_allIterationsPassed			(true)
1055 {
1056 }
1057 
iterate(void)1058 tcu::TestStatus BaseTriangleTestInstance::iterate (void)
1059 {
1060 	const std::string								iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1061 	const tcu::ScopedLogSection						section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1062 	tcu::Surface									resultImage				(m_renderSize, m_renderSize);
1063 	std::vector<tcu::Vec4>							drawBuffer;
1064 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
1065 
1066 	generateTriangles(m_iteration, drawBuffer, triangles);
1067 
1068 	// draw image
1069 	drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
1070 
1071 	// compare
1072 	{
1073 		const bool compareOk = compareAndVerify(triangles, resultImage, drawBuffer);
1074 
1075 		if (!compareOk)
1076 			m_allIterationsPassed = false;
1077 	}
1078 
1079 	// result
1080 	if (++m_iteration == m_iterationCount)
1081 	{
1082 		if (m_allIterationsPassed)
1083 			return tcu::TestStatus::pass("Pass");
1084 		else
1085 			return tcu::TestStatus::fail("Incorrect rasterization");
1086 	}
1087 	else
1088 		return tcu::TestStatus::incomplete();
1089 }
1090 
compareAndVerify(std::vector<TriangleSceneSpec::SceneTriangle> & triangles,tcu::Surface & resultImage,std::vector<tcu::Vec4> &)1091 bool BaseTriangleTestInstance::compareAndVerify (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage, std::vector<tcu::Vec4>&)
1092 {
1093 	RasterizationArguments	args;
1094 	TriangleSceneSpec		scene;
1095 
1096 	tcu::IVec4				colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1097 
1098 	args.numSamples		= m_multisampling ? 1 : 0;
1099 	args.subpixelBits	= m_subpixelBits;
1100 	args.redBits		= colorBits[0];
1101 	args.greenBits		= colorBits[1];
1102 	args.blueBits		= colorBits[2];
1103 
1104 	scene.triangles.swap(triangles);
1105 
1106 	return verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1107 }
1108 
1109 class BaseLineTestInstance : public BaseRenderingTestInstance
1110 {
1111 public:
1112 								BaseLineTestInstance	(Context&					context,
1113 														 VkPrimitiveTopology		primitiveTopology,
1114 														 PrimitiveWideness			wideness,
1115 														 PrimitiveStrictness		strictness,
1116 														 VkSampleCountFlagBits		sampleCount,
1117 														 LineStipple				stipple,
1118 														 VkLineRasterizationModeEXT	lineRasterizationMode,
1119 														 LineStippleFactorCase		stippleFactor,
1120 														 const deUint32				additionalRenderSize = 0,
1121 														 const deUint32				renderSize = RESOLUTION_POT,
1122 														 const float				narrowLineWidth = 1.0f);
1123 	virtual tcu::TestStatus		iterate					(void);
1124 	virtual float				getLineWidth			(void) const;
getLineStippleEnable(void) const1125 	bool						getLineStippleEnable	(void) const { return m_stipple != LINESTIPPLE_DISABLED; }
getLineStippleDynamic(void) const1126 	virtual bool				getLineStippleDynamic	(void) const { return (m_stipple == LINESTIPPLE_DYNAMIC || m_stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY); }
isDynamicTopology(void) const1127 	virtual bool				isDynamicTopology		(void) const { return m_stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY; }
1128 
1129 	virtual
1130 	std::vector<tcu::Vec4>		getOffScreenPoints		(void) const;
1131 
1132 	virtual
1133 	VkPipelineRasterizationLineStateCreateInfoEXT	initLineRasterizationStateCreateInfo	(void) const;
1134 
1135 	virtual
1136 	const VkPipelineRasterizationLineStateCreateInfoEXT*	getLineRasterizationStateCreateInfo	(void);
1137 
1138 protected:
getIteration(void) const1139 	int							getIteration			(void) const	{ return m_iteration;		}
getIterationCount(void) const1140 	int							getIterationCount		(void) const	{ return m_iterationCount;	}
1141 
1142 private:
1143 	virtual void				generateLines			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
1144 	virtual bool				compareAndVerify		(std::vector<LineSceneSpec::SceneLine>&	lines,
1145 														 tcu::Surface&							resultImage,
1146 														 std::vector<tcu::Vec4>&				drawBuffer);
1147 
1148 	bool						resultHasAlpha			(tcu::Surface& result);
1149 
1150 	int							m_iteration;
1151 	const int					m_iterationCount;
1152 	VkPrimitiveTopology			m_primitiveTopology;
1153 	const PrimitiveWideness		m_primitiveWideness;
1154 	const PrimitiveStrictness	m_primitiveStrictness;
1155 	bool						m_allIterationsPassed;
1156 	bool						m_qualityWarning;
1157 	float						m_maxLineWidth;
1158 	std::vector<float>			m_lineWidths;
1159 	LineStipple					m_stipple;
1160 	VkLineRasterizationModeEXT	m_lineRasterizationMode;
1161 	LineStippleFactorCase		m_stippleFactor;
1162 	Move<VkImage>				m_additionalImage;
1163 	de::MovePtr<Allocation>		m_additionalImageMemory;
1164 	Move<VkImageView>			m_additionalImageView;
1165 	Move<VkImage>				m_additionalResolvedImage;
1166 	de::MovePtr<Allocation>		m_additionalResolvedImageMemory;
1167 	Move<VkImageView>			m_additionalResolvedImageView;
1168 	Move<VkFramebuffer>			m_additionalFrameBuffer;
1169 	Move<VkBuffer>				m_additionalResultBuffer;
1170 	de::MovePtr<Allocation>		m_additionalResultBufferMemory;
1171 };
1172 
BaseLineTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,PrimitiveWideness wideness,PrimitiveStrictness strictness,VkSampleCountFlagBits sampleCount,LineStipple stipple,VkLineRasterizationModeEXT lineRasterizationMode,LineStippleFactorCase stippleFactor,const deUint32 additionalRenderSize,const deUint32 renderSize,const float narrowLineWidth)1173 BaseLineTestInstance::BaseLineTestInstance (Context&					context,
1174 											VkPrimitiveTopology			primitiveTopology,
1175 											PrimitiveWideness			wideness,
1176 											PrimitiveStrictness			strictness,
1177 											VkSampleCountFlagBits		sampleCount,
1178 											LineStipple					stipple,
1179 											VkLineRasterizationModeEXT	lineRasterizationMode,
1180 											LineStippleFactorCase		stippleFactor,
1181 											const deUint32				additionalRenderSize,
1182 											const deUint32				renderSize,
1183 											const float					narrowLineWidth)
1184 	: BaseRenderingTestInstance	(context, sampleCount, renderSize, VK_FORMAT_R8G8B8A8_UNORM, additionalRenderSize)
1185 	, m_iteration				(0)
1186 	, m_iterationCount			(3)
1187 	, m_primitiveTopology		(primitiveTopology)
1188 	, m_primitiveWideness		(wideness)
1189 	, m_primitiveStrictness		(strictness)
1190 	, m_allIterationsPassed		(true)
1191 	, m_qualityWarning			(false)
1192 	, m_maxLineWidth			(1.0f)
1193 	, m_stipple					(stipple)
1194 	, m_lineRasterizationMode	(lineRasterizationMode)
1195 	, m_stippleFactor			(stippleFactor)
1196 {
1197 	DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
1198 
1199 	if (m_lineRasterizationMode != VK_LINE_RASTERIZATION_MODE_EXT_LAST)
1200 	{
1201 		if (context.isDeviceFunctionalitySupported("VK_EXT_line_rasterization"))
1202 		{
1203 			VkPhysicalDeviceLineRasterizationPropertiesEXT lineRasterizationProperties =
1204 			{
1205 				VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT,	// VkStructureType	sType;
1206 				DE_NULL,																// void*			pNext;
1207 				0u,																		// deUint32			lineSubPixelPrecisionBits;
1208 			};
1209 
1210 			VkPhysicalDeviceProperties2 deviceProperties2;
1211 			deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1212 			deviceProperties2.pNext = &lineRasterizationProperties;
1213 
1214 			context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &deviceProperties2);
1215 
1216 			m_subpixelBits = lineRasterizationProperties.lineSubPixelPrecisionBits;
1217 		}
1218 	}
1219 
1220 	// create line widths
1221 	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
1222 	{
1223 		m_lineWidths.resize(m_iterationCount, narrowLineWidth);
1224 
1225 		// Bump up m_maxLineWidth for conservative rasterization
1226 		if (narrowLineWidth > m_maxLineWidth)
1227 			m_maxLineWidth = narrowLineWidth;
1228 	}
1229 	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
1230 	{
1231 		const float*	range = context.getDeviceProperties().limits.lineWidthRange;
1232 
1233 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
1234 
1235 		DE_ASSERT(range[1] > 1.0f);
1236 
1237 		// set hand picked sizes
1238 		m_lineWidths.push_back(5.0f);
1239 		m_lineWidths.push_back(10.0f);
1240 
1241 		// Do not pick line width with 0.5 fractional value as rounding direction is not defined.
1242 		if (deFloatFrac(range[1]) == 0.5f)
1243 		{
1244 			m_lineWidths.push_back(range[1] - context.getDeviceProperties().limits.lineWidthGranularity);
1245 		}
1246 		else
1247 		{
1248 			m_lineWidths.push_back(range[1]);
1249 		}
1250 
1251 		DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
1252 
1253 		m_maxLineWidth = range[1];
1254 	}
1255 	else
1256 		DE_ASSERT(false);
1257 
1258 	// Create image, image view and frame buffer for testing at an additional resolution if required.
1259 	if (m_additionalRenderSize != 0)
1260 	{
1261 		const DeviceInterface&						vkd						= m_context.getDeviceInterface();
1262 		const VkDevice								vkDevice				= m_context.getDevice();
1263 		const deUint32								queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
1264 		Allocator&									allocator				= m_context.getDefaultAllocator();
1265 		DescriptorPoolBuilder						descriptorPoolBuilder;
1266 		DescriptorSetLayoutBuilder					descriptorSetLayoutBuilder;
1267 		{
1268 			const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1269 			const VkImageCreateInfo					imageCreateInfo			=
1270 			{
1271 				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
1272 				DE_NULL,									// const void*				pNext;
1273 				0u,											// VkImageCreateFlags		flags;
1274 				VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
1275 				m_imageFormat,								// VkFormat					format;
1276 				{ m_additionalRenderSize, m_additionalRenderSize, 1u },			// VkExtent3D				extent;
1277 				1u,											// deUint32					mipLevels;
1278 				1u,											// deUint32					arrayLayers;
1279 				m_sampleCount,								// VkSampleCountFlagBits	samples;
1280 				VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
1281 				imageUsage,									// VkImageUsageFlags		usage;
1282 				VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
1283 				1u,											// deUint32					queueFamilyIndexCount;
1284 				&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
1285 				VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
1286 			};
1287 
1288 			m_additionalImage = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
1289 
1290 			m_additionalImageMemory	= allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_additionalImage), MemoryRequirement::Any);
1291 			VK_CHECK(vkd.bindImageMemory(vkDevice, *m_additionalImage, m_additionalImageMemory->getMemory(), m_additionalImageMemory->getOffset()));
1292 		}
1293 
1294 		// Image View
1295 		{
1296 			const VkImageViewCreateInfo				imageViewCreateInfo		=
1297 			{
1298 				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
1299 				DE_NULL,									// const void*					pNext;
1300 				0u,											// VkImageViewCreateFlags		flags;
1301 				*m_additionalImage,							// VkImage						image;
1302 				VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
1303 				m_imageFormat,								// VkFormat						format;
1304 				makeComponentMappingRGBA(),					// VkComponentMapping			components;
1305 				{
1306 					VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
1307 					0u,											// deUint32						baseMipLevel;
1308 					1u,											// deUint32						mipLevels;
1309 					0u,											// deUint32						baseArrayLayer;
1310 					1u,											// deUint32						arraySize;
1311 				},											// VkImageSubresourceRange		subresourceRange;
1312 			};
1313 
1314 			m_additionalImageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
1315 		}
1316 
1317 		if (m_multisampling)
1318 		{
1319 			{
1320 				const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1321 				const VkImageCreateInfo					imageCreateInfo			=
1322 				{
1323 					VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
1324 					DE_NULL,									// const void*				pNext;
1325 					0u,											// VkImageCreateFlags		flags;
1326 					VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
1327 					m_imageFormat,								// VkFormat					format;
1328 					{ m_additionalRenderSize,	m_additionalRenderSize, 1u },			// VkExtent3D				extent;
1329 					1u,											// deUint32					mipLevels;
1330 					1u,											// deUint32					arrayLayers;
1331 					VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples;
1332 					VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
1333 					imageUsage,									// VkImageUsageFlags		usage;
1334 					VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
1335 					1u,											// deUint32					queueFamilyIndexCount;
1336 					&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
1337 					VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
1338 				};
1339 
1340 				m_additionalResolvedImage			= vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
1341 				m_additionalResolvedImageMemory	= allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_additionalResolvedImage), MemoryRequirement::Any);
1342 				VK_CHECK(vkd.bindImageMemory(vkDevice, *m_additionalResolvedImage, m_additionalResolvedImageMemory->getMemory(), m_additionalResolvedImageMemory->getOffset()));
1343 			}
1344 
1345 			// Image view
1346 			{
1347 				const VkImageViewCreateInfo				imageViewCreateInfo		=
1348 				{
1349 					VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
1350 					DE_NULL,									// const void*					pNext;
1351 					0u,											// VkImageViewCreateFlags		flags;
1352 					*m_additionalResolvedImage,					// VkImage						image;
1353 					VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
1354 					m_imageFormat,								// VkFormat						format;
1355 					makeComponentMappingRGBA(),					// VkComponentMapping			components;
1356 					{
1357 						VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
1358 						0u,											// deUint32						baseMipLevel;
1359 						1u,											// deUint32						mipLevels;
1360 						0u,											// deUint32						baseArrayLayer;
1361 						1u,											// deUint32						arraySize;
1362 					},											// VkImageSubresourceRange		subresourceRange;
1363 				};
1364 				m_additionalResolvedImageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
1365 			}
1366 		}
1367 
1368 		{
1369 			const VkImageView						attachments[]			=
1370 			{
1371 				*m_additionalImageView,
1372 				*m_additionalResolvedImageView
1373 			};
1374 
1375 			const VkFramebufferCreateInfo			framebufferCreateInfo	=
1376 			{
1377 				VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
1378 				DE_NULL,									// const void*				pNext;
1379 				0u,											// VkFramebufferCreateFlags	flags;
1380 				*m_renderPass,								// VkRenderPass				renderPass;
1381 				m_multisampling ? 2u : 1u,					// deUint32					attachmentCount;
1382 				attachments,								// const VkImageView*		pAttachments;
1383 				m_additionalRenderSize,						// deUint32					width;
1384 				m_additionalRenderSize,						// deUint32					height;
1385 				1u,											// deUint32					layers;
1386 			};
1387 			m_additionalFrameBuffer = createFramebuffer(vkd, vkDevice, &framebufferCreateInfo, DE_NULL);
1388 		}
1389 
1390 		// Framebuffer
1391 		{
1392 			const VkBufferCreateInfo				bufferCreateInfo		=
1393 			{
1394 				VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1395 				DE_NULL,									// const void*			pNext;
1396 				0u,											// VkBufferCreateFlags	flags;
1397 				m_additionalResultBufferSize,							// VkDeviceSize			size;
1398 				VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
1399 				VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1400 				1u,											// deUint32				queueFamilyIndexCount;
1401 				&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1402 			};
1403 
1404 			m_additionalResultBuffer			= createBuffer(vkd, vkDevice, &bufferCreateInfo);
1405 			m_additionalResultBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_additionalResultBuffer), MemoryRequirement::HostVisible);
1406 
1407 			VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_additionalResultBuffer, m_additionalResultBufferMemory->getMemory(), m_additionalResultBufferMemory->getOffset()));
1408 		}
1409 	}
1410 }
1411 
resultHasAlpha(tcu::Surface & resultImage)1412 bool BaseLineTestInstance::resultHasAlpha(tcu::Surface& resultImage)
1413 {
1414 	bool hasAlpha = false;
1415 	for (int y = 0; y < resultImage.getHeight() && !hasAlpha; ++y)
1416 	for (int x = 0; x < resultImage.getWidth(); ++x)
1417 	{
1418 		const tcu::RGBA		color				= resultImage.getPixel(x, y);
1419 		if (color.getAlpha() > 0 && color.getAlpha() < 0xFF)
1420 		{
1421 			hasAlpha = true;
1422 			break;
1423 		}
1424 	}
1425 	return hasAlpha;
1426 }
1427 
iterate(void)1428 tcu::TestStatus BaseLineTestInstance::iterate (void)
1429 {
1430 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1431 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1432 	const float								lineWidth				= getLineWidth();
1433 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
1434 	std::vector<tcu::Vec4>					drawBuffer;
1435 	std::vector<LineSceneSpec::SceneLine>	lines;
1436 
1437 	// supported?
1438 	if (lineWidth <= m_maxLineWidth)
1439 	{
1440 		// gen data
1441 		generateLines(m_iteration, drawBuffer, lines);
1442 
1443 		// draw image
1444 		drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
1445 
1446 		// compare
1447 		{
1448 			const bool compareOk = compareAndVerify(lines, resultImage, drawBuffer);
1449 
1450 			if (!compareOk)
1451 				m_allIterationsPassed = false;
1452 		}
1453 	}
1454 	else
1455 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
1456 
1457 	// result
1458 	if (++m_iteration == m_iterationCount)
1459 	{
1460 		if (!m_allIterationsPassed)
1461 			return tcu::TestStatus::fail("Incorrect rasterization");
1462 		else if (m_qualityWarning)
1463 			return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality line rasterization");
1464 		else
1465 			return tcu::TestStatus::pass("Pass");
1466 	}
1467 	else
1468 		return tcu::TestStatus::incomplete();
1469 }
1470 
compareAndVerify(std::vector<LineSceneSpec::SceneLine> & lines,tcu::Surface & resultImage,std::vector<tcu::Vec4> & drawBuffer)1471 bool BaseLineTestInstance::compareAndVerify (std::vector<LineSceneSpec::SceneLine>&	lines, tcu::Surface& resultImage, std::vector<tcu::Vec4>& drawBuffer)
1472 {
1473 	const float				lineWidth				= getLineWidth();
1474 	bool					result					= true;
1475 	tcu::Surface			additionalResultImage	(m_additionalRenderSize, m_additionalRenderSize);
1476 	RasterizationArguments	args;
1477 	LineSceneSpec			scene;
1478 	tcu::IVec4				colorBits	= tcu::getTextureFormatBitDepth(getTextureFormat());
1479 	bool					strict		= m_primitiveStrictness == PRIMITIVESTRICTNESS_STRICT;
1480 
1481 	args.numSamples		= m_multisampling ? 1 : 0;
1482 	args.subpixelBits	= m_subpixelBits;
1483 	args.redBits		= colorBits[0];
1484 	args.greenBits		= colorBits[1];
1485 	args.blueBits		= colorBits[2];
1486 
1487 	scene.lines.swap(lines);
1488 	scene.lineWidth = lineWidth;
1489 	scene.stippleEnable = getLineStippleEnable();
1490 	scene.stippleFactor = getLineStippleEnable() ? lineStippleFactor : 1;
1491 	scene.stipplePattern = getLineStippleEnable() ? lineStipplePattern : 0xFFFF;
1492 	scene.isStrip = m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
1493 	scene.isSmooth = m_lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
1494 	scene.isRectangular = m_lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT ||
1495 	                      m_lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
1496 
1497 	// Choose verification mode. Smooth lines assume mostly over-rasterization (bloated lines with a falloff).
1498 	// Stippled lines lose some precision across segments in a strip, so need a weaker threshold than normal
1499 	// lines. For simple cases, check for an exact match (STRICT).
1500 	if (scene.isSmooth)
1501 		scene.verificationMode = tcu::VERIFICATIONMODE_SMOOTH;
1502 	else if (scene.stippleEnable)
1503 		scene.verificationMode = tcu::VERIFICATIONMODE_WEAKER;
1504 	else
1505 		scene.verificationMode = tcu::VERIFICATIONMODE_STRICT;
1506 
1507 	if (m_lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT)
1508 	{
1509 		// bresenham is "no AA" in GL, so set numSamples to zero.
1510 		args.numSamples = 0;
1511 		if (!verifyLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog()))
1512 			result = false;
1513 	}
1514 	else
1515 	{
1516 		if (scene.isSmooth)
1517 		{
1518 			// Smooth lines get the fractional coverage multiplied into the alpha component,
1519 			// so do a quick check to validate that there is at least one pixel in the image
1520 			// with a fractional opacity.
1521 			bool hasAlpha = resultHasAlpha(resultImage);
1522 			if (!hasAlpha)
1523 			{
1524 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Missing alpha transparency (failed)." << tcu::TestLog::EndMessage;
1525 				result = false;
1526 			}
1527 		}
1528 
1529 		if (!verifyRelaxedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), (0 == m_multisampling), strict))
1530 		{
1531 			// Retry with weaker verification. If it passes, consider it a quality warning.
1532 			scene.verificationMode = tcu::VERIFICATIONMODE_WEAKER;
1533 			if (!verifyRelaxedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), false, strict))
1534 				result = false;
1535 			else
1536 				m_qualityWarning = true;
1537 		}
1538 
1539 		if (m_additionalRenderSize != 0)
1540 		{
1541 			const std::vector<tcu::Vec4> colorData(drawBuffer.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1542 
1543 			if (scene.isSmooth)
1544 				scene.verificationMode = tcu::VERIFICATIONMODE_SMOOTH;
1545 			else if (scene.stippleEnable)
1546 				scene.verificationMode = tcu::VERIFICATIONMODE_WEAKER;
1547 			else
1548 				scene.verificationMode = tcu::VERIFICATIONMODE_STRICT;
1549 
1550 			drawPrimitives(additionalResultImage, drawBuffer, colorData, m_primitiveTopology, *m_additionalImage, *m_additionalResolvedImage, *m_additionalFrameBuffer, m_additionalRenderSize, *m_additionalResultBuffer, *m_additionalResultBufferMemory);
1551 
1552 			// Compare
1553 			if (!verifyRelaxedLineGroupRasterization(additionalResultImage, scene, args, m_context.getTestContext().getLog(), (0 == m_multisampling), strict))
1554 			{
1555 				if (strict)
1556 				{
1557 					result = false;
1558 				}
1559 				else
1560 				{
1561 					// Retry with weaker verification. If it passes, consider it a quality warning.
1562 					scene.verificationMode = tcu::VERIFICATIONMODE_WEAKER;
1563 					if (!verifyRelaxedLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), (0 == m_multisampling), strict))
1564 						result = false;
1565 					else
1566 						m_qualityWarning = true;
1567 				}
1568 			}
1569 		}
1570 	}
1571 
1572 	return result;
1573 }
1574 
getLineWidth(void) const1575 float BaseLineTestInstance::getLineWidth (void) const
1576 {
1577 	return m_lineWidths[m_iteration];
1578 }
1579 
getOffScreenPoints(void) const1580 std::vector<tcu::Vec4> BaseLineTestInstance::getOffScreenPoints (void) const
1581 {
1582 	// These points will be used to draw something with the wrong topology.
1583 	// They are offscreen so as not to affect the render result.
1584 	return std::vector<tcu::Vec4>
1585 	{
1586 		tcu::Vec4(2.0f, 2.0f, 0.0f, 1.0f),
1587 		tcu::Vec4(2.0f, 3.0f, 0.0f, 1.0f),
1588 		tcu::Vec4(2.0f, 4.0f, 0.0f, 1.0f),
1589 		tcu::Vec4(2.0f, 5.0f, 0.0f, 1.0f),
1590 	};
1591 }
1592 
initLineRasterizationStateCreateInfo(void) const1593 VkPipelineRasterizationLineStateCreateInfoEXT BaseLineTestInstance::initLineRasterizationStateCreateInfo (void) const
1594 {
1595 	VkPipelineRasterizationLineStateCreateInfoEXT lineRasterizationStateInfo	=
1596 	{
1597 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT,	// VkStructureType				sType;
1598 		DE_NULL,																// const void*					pNext;
1599 		m_lineRasterizationMode,												// VkLineRasterizationModeEXT	lineRasterizationMode;
1600 		getLineStippleEnable() ? VK_TRUE : VK_FALSE,							// VkBool32						stippledLineEnable;
1601 		1,																		// uint32_t						lineStippleFactor;
1602 		0xFFFF,																	// uint16_t						lineStipplePattern;
1603 	};
1604 
1605 	if (m_stipple == LINESTIPPLE_STATIC)
1606 	{
1607 		lineRasterizationStateInfo.lineStippleFactor = lineStippleFactor;
1608 		lineRasterizationStateInfo.lineStipplePattern = lineStipplePattern;
1609 	}
1610 	else if (m_stipple == LINESTIPPLE_DISABLED)
1611 	{
1612 		if (m_stippleFactor == LineStippleFactorCase::ZERO)
1613 			lineRasterizationStateInfo.lineStippleFactor = 0u;
1614 		else if (m_stippleFactor == LineStippleFactorCase::LARGE)
1615 			lineRasterizationStateInfo.lineStippleFactor = 0xFEDCBA98u;
1616 	}
1617 
1618 	return lineRasterizationStateInfo;
1619 }
1620 
getLineRasterizationStateCreateInfo(void)1621 const VkPipelineRasterizationLineStateCreateInfoEXT* BaseLineTestInstance::getLineRasterizationStateCreateInfo (void)
1622 {
1623 	if (m_lineRasterizationMode == VK_LINE_RASTERIZATION_MODE_EXT_LAST)
1624 		return DE_NULL;
1625 
1626 	if (m_lineRasterizationStateInfo.sType != VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT)
1627 		m_lineRasterizationStateInfo = initLineRasterizationStateCreateInfo();
1628 
1629 	return &m_lineRasterizationStateInfo;
1630 }
1631 
1632 class PointTestInstance : public BaseRenderingTestInstance
1633 {
1634 public:
1635 							PointTestInstance		(Context&					context,
1636 													 PrimitiveWideness			wideness,
1637 													 PrimitiveStrictness		strictness,				// ignored
1638 													 VkSampleCountFlagBits		sampleCount,
1639 													 LineStipple				stipple,				// ignored
1640 													 VkLineRasterizationModeEXT	lineRasterizationMode,	// ignored
1641 													 LineStippleFactorCase		stippleFactor,			// ignored
1642 													 deUint32					additionalRenderSize,	// ignored
1643 													 deUint32					renderSize				= RESOLUTION_POT,
1644 													 float						pointSizeNarrow			= 1.0f);
1645 	virtual tcu::TestStatus	iterate					(void);
1646 	virtual float			getPointSize			(void) const;
1647 
1648 protected:
getIteration(void) const1649 	int						getIteration				(void) const	{ return m_iteration;		}
getIterationCount(void) const1650 	int						getIterationCount			(void) const	{ return m_iterationCount;	}
1651 
1652 private:
1653 	virtual void			generatePoints			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
1654 	virtual bool			compareAndVerify		(std::vector<PointSceneSpec::ScenePoint>&	points,
1655 													 tcu::Surface&								resultImage,
1656 													 std::vector<tcu::Vec4>&					drawBuffer);
1657 
1658 	int						m_iteration;
1659 	const int				m_iterationCount;
1660 	const PrimitiveWideness	m_primitiveWideness;
1661 	bool					m_allIterationsPassed;
1662 	float					m_maxPointSize;
1663 	std::vector<float>		m_pointSizes;
1664 };
1665 
PointTestInstance(Context & context,PrimitiveWideness wideness,PrimitiveStrictness strictness,VkSampleCountFlagBits sampleCount,LineStipple stipple,VkLineRasterizationModeEXT lineRasterizationMode,LineStippleFactorCase stippleFactor,deUint32 additionalRenderSize,deUint32 renderSize,float pointSizeNarrow)1666 PointTestInstance::PointTestInstance (Context&						context,
1667 									  PrimitiveWideness				wideness,
1668 									  PrimitiveStrictness			strictness,
1669 									  VkSampleCountFlagBits			sampleCount,
1670 									  LineStipple					stipple,
1671 									  VkLineRasterizationModeEXT	lineRasterizationMode,
1672 									  LineStippleFactorCase			stippleFactor,
1673 									  deUint32						additionalRenderSize,
1674 									  deUint32						renderSize,
1675 									  float							pointSizeNarrow)
1676 	: BaseRenderingTestInstance	(context, sampleCount, renderSize)
1677 	, m_iteration				(0)
1678 	, m_iterationCount			(3)
1679 	, m_primitiveWideness		(wideness)
1680 	, m_allIterationsPassed		(true)
1681 	, m_maxPointSize			(pointSizeNarrow)
1682 {
1683 	DE_UNREF(strictness);
1684 	DE_UNREF(stipple);
1685 	DE_UNREF(lineRasterizationMode);
1686 	DE_UNREF(stippleFactor);
1687 	DE_UNREF(additionalRenderSize);
1688 
1689 	// create point sizes
1690 	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
1691 	{
1692 		m_pointSizes.resize(m_iterationCount, pointSizeNarrow);
1693 	}
1694 	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
1695 	{
1696 		const float*	range = context.getDeviceProperties().limits.pointSizeRange;
1697 
1698 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
1699 
1700 		DE_ASSERT(range[1] > 1.0f);
1701 
1702 		// set hand picked sizes
1703 		m_pointSizes.push_back(10.0f);
1704 		m_pointSizes.push_back(25.0f);
1705 		m_pointSizes.push_back(range[1]);
1706 		DE_ASSERT((int)m_pointSizes.size() == m_iterationCount);
1707 
1708 		m_maxPointSize = range[1];
1709 	}
1710 	else
1711 		DE_ASSERT(false);
1712 }
1713 
iterate(void)1714 tcu::TestStatus PointTestInstance::iterate (void)
1715 {
1716 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1717 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
1718 	const float								pointSize				= getPointSize();
1719 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
1720 	std::vector<tcu::Vec4>					drawBuffer;
1721 	std::vector<PointSceneSpec::ScenePoint>	points;
1722 
1723 	// supported?
1724 	if (pointSize <= m_maxPointSize)
1725 	{
1726 		// gen data
1727 		generatePoints(m_iteration, drawBuffer, points);
1728 
1729 		// draw image
1730 		drawPrimitives(resultImage, drawBuffer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
1731 
1732 		// compare
1733 		{
1734 			const bool compareOk = compareAndVerify(points, resultImage, drawBuffer);
1735 
1736 			if (!compareOk)
1737 				m_allIterationsPassed = false;
1738 		}
1739 	}
1740 	else
1741 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point size " << pointSize << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
1742 
1743 	// result
1744 	if (++m_iteration == m_iterationCount)
1745 	{
1746 		if (m_allIterationsPassed)
1747 			return tcu::TestStatus::pass("Pass");
1748 		else
1749 			return tcu::TestStatus::fail("Incorrect rasterization");
1750 	}
1751 	else
1752 		return tcu::TestStatus::incomplete();
1753 }
1754 
compareAndVerify(std::vector<PointSceneSpec::ScenePoint> & points,tcu::Surface & resultImage,std::vector<tcu::Vec4> & drawBuffer)1755 bool PointTestInstance::compareAndVerify (std::vector<PointSceneSpec::ScenePoint>&	points,
1756 										  tcu::Surface&								resultImage,
1757 										  std::vector<tcu::Vec4>&					drawBuffer)
1758 {
1759 	RasterizationArguments	args;
1760 	PointSceneSpec			scene;
1761 
1762 	tcu::IVec4				colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
1763 
1764 	args.numSamples		= m_multisampling ? 1 : 0;
1765 	args.subpixelBits	= m_subpixelBits;
1766 	args.redBits		= colorBits[0];
1767 	args.greenBits		= colorBits[1];
1768 	args.blueBits		= colorBits[2];
1769 
1770 	scene.points.swap(points);
1771 
1772 	DE_UNREF(drawBuffer);
1773 
1774 	return verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
1775 }
1776 
getPointSize(void) const1777 float PointTestInstance::getPointSize (void) const
1778 {
1779 	return m_pointSizes[m_iteration];
1780 }
1781 
generatePoints(int iteration,std::vector<tcu::Vec4> & outData,std::vector<PointSceneSpec::ScenePoint> & outPoints)1782 void PointTestInstance::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
1783 {
1784 	outData.resize(6);
1785 
1786 	switch (iteration)
1787 	{
1788 		case 0:
1789 			// \note: these values are chosen arbitrarily
1790 			outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
1791 			outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
1792 			outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
1793 			outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
1794 			outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
1795 			outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
1796 			break;
1797 
1798 		case 1:
1799 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1800 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1801 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1802 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1803 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1804 			outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
1805 			break;
1806 
1807 		case 2:
1808 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1809 			outData[1] = tcu::Vec4(  0.3f, -0.9f, 0.0f, 1.0f);
1810 			outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
1811 			outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
1812 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1813 			outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
1814 			break;
1815 	}
1816 
1817 	outPoints.resize(outData.size());
1818 	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
1819 	{
1820 		outPoints[pointNdx].position = outData[pointNdx];
1821 		outPoints[pointNdx].pointSize = getPointSize();
1822 	}
1823 
1824 	// log
1825 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << getPointSize() << ")" << tcu::TestLog::EndMessage;
1826 	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
1827 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
1828 }
1829 
1830 template <typename ConcreteTestInstance>
1831 class PointSizeTestCase : public BaseRenderingTestCase
1832 {
1833 public:
PointSizeTestCase(tcu::TestContext & context,std::string & name,deUint32 renderSize,float pointSize,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)1834 							PointSizeTestCase	(tcu::TestContext&		context,
1835 												 std::string&			name,
1836 												 deUint32				renderSize,
1837 												 float					pointSize,
1838 												 VkSampleCountFlagBits	sampleCount = VK_SAMPLE_COUNT_1_BIT)
1839 								: BaseRenderingTestCase (context, name, sampleCount)
1840 								, m_pointSize	(pointSize)
1841 								, m_renderSize	(renderSize)
1842 							{}
1843 
createInstance(Context & context) const1844 	virtual TestInstance*	createInstance		(Context& context) const
1845 							{
1846 								VkPhysicalDeviceProperties	properties	(context.getDeviceProperties());
1847 
1848 								if (m_renderSize > properties.limits.maxViewportDimensions[0] || m_renderSize > properties.limits.maxViewportDimensions[1])
1849 									TCU_THROW(NotSupportedError , "Viewport dimensions not supported");
1850 
1851 								if (m_renderSize > properties.limits.maxFramebufferWidth || m_renderSize > properties.limits.maxFramebufferHeight)
1852 									TCU_THROW(NotSupportedError , "Framebuffer width/height not supported");
1853 
1854 								return new ConcreteTestInstance(context, m_renderSize, m_pointSize);
1855 							}
1856 
checkSupport(Context & context) const1857 	virtual	void			checkSupport		(Context& context) const
1858 							{
1859 								context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_LARGE_POINTS);
1860 							}
1861 protected:
1862 	const float				m_pointSize;
1863 	const deUint32			m_renderSize;
1864 };
1865 
1866 class PointSizeTestInstance : public BaseRenderingTestInstance
1867 {
1868 public:
1869 								PointSizeTestInstance	(Context& context, deUint32 renderSize, float pointSize);
1870 	virtual tcu::TestStatus		iterate					(void);
1871 	virtual float				getPointSize			(void) const;
1872 
1873 protected:
1874 	void						generatePointData		(PointSceneSpec::ScenePoint& outPoint);
1875 	virtual Move<VkPipeline>	createPipeline			(void);
1876 	virtual void				bindDrawData			(VkCommandBuffer commandBuffer, VkPipeline graphicsPipeline, VkBuffer vertexBuffer);
1877 	void						drawPoint				(tcu::PixelBufferAccess& result, tcu::PointSceneSpec::ScenePoint& point);
1878 	bool						verifyPoint				(tcu::TestLog& log, tcu::PixelBufferAccess& access, float pointSize);
1879 	bool						isPointSizeClamped		(float pointSize, float maxPointSizeLimit);
1880 
1881 	const float					m_pointSize;
1882 	const float					m_maxPointSize;
1883 	const deUint32				m_renderSize;
1884 	const VkFormat				m_format;
1885 };
1886 
PointSizeTestInstance(Context & context,deUint32 renderSize,float pointSize)1887 PointSizeTestInstance::PointSizeTestInstance (Context& context, deUint32 renderSize, float pointSize)
1888 	: BaseRenderingTestInstance	(context, vk::VK_SAMPLE_COUNT_1_BIT, renderSize, VK_FORMAT_R8_UNORM)
1889 	, m_pointSize				(pointSize)
1890 	, m_maxPointSize			(context.getDeviceProperties().limits.pointSizeRange[1])
1891 	, m_renderSize				(renderSize)
1892 	, m_format					(VK_FORMAT_R8_UNORM) // Use single-channel format to minimize memory allocation when using large render targets
1893 {
1894 }
1895 
iterate(void)1896 tcu::TestStatus PointSizeTestInstance::iterate (void)
1897 {
1898 	tcu::TextureLevel			resultBuffer	(mapVkFormat(m_format), m_renderSize, m_renderSize);
1899 	tcu::PixelBufferAccess		access			(resultBuffer.getAccess());
1900 	PointSceneSpec::ScenePoint	point;
1901 
1902 	// Generate data
1903 	generatePointData(point);
1904 
1905 	// Draw
1906 	drawPoint(access, point);
1907 
1908 	// Compare
1909 #ifdef CTS_USES_VULKANSC
1910 	if (m_context.getTestContext().getCommandLine().isSubProcess())
1911 #endif // CTS_USES_VULKANSC
1912 	{
1913 		// pointSize must either be specified pointSize or clamped to device limit pointSizeRange[1]
1914 		const float	pointSize	(deFloatMin(m_pointSize, m_maxPointSize));
1915 		const bool	compareOk	(verifyPoint(m_context.getTestContext().getLog(), access, pointSize));
1916 
1917 		// Result
1918 		if (compareOk)
1919 			return isPointSizeClamped(pointSize, m_maxPointSize) ? tcu::TestStatus::pass("Pass, pointSize clamped to pointSizeRange[1]") : tcu::TestStatus::pass("Pass");
1920 		else
1921 			return tcu::TestStatus::fail("Incorrect rasterization");
1922 	}
1923 	return tcu::TestStatus::pass("Pass");
1924 }
1925 
getPointSize(void) const1926 float PointSizeTestInstance::getPointSize (void) const
1927 {
1928 	return m_pointSize;
1929 }
1930 
generatePointData(PointSceneSpec::ScenePoint & outPoint)1931 void PointSizeTestInstance::generatePointData (PointSceneSpec::ScenePoint& outPoint)
1932 {
1933 	const tcu::PointSceneSpec::ScenePoint point =
1934 	{
1935 		tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),	// position
1936 		tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),	// color
1937 		m_pointSize							// pointSize
1938 	};
1939 
1940 	outPoint = point;
1941 
1942 	// log
1943 	{
1944 		tcu::TestLog& log = m_context.getTestContext().getLog();
1945 
1946 		log << tcu::TestLog::Message << "Point position: "	<< de::toString(point.position)		<< tcu::TestLog::EndMessage;
1947 		log << tcu::TestLog::Message << "Point color: "		<< de::toString(point.color)		<< tcu::TestLog::EndMessage;
1948 		log << tcu::TestLog::Message << "Point size: "		<< de::toString(point.pointSize)	<< tcu::TestLog::EndMessage;
1949 		log << tcu::TestLog::Message << "Render size: "		<< de::toString(m_renderSize)		<< tcu::TestLog::EndMessage;
1950 		log << tcu::TestLog::Message << "Format: "			<< de::toString(m_format)			<< tcu::TestLog::EndMessage;
1951 	}
1952 }
1953 
createPipeline(void)1954 Move<VkPipeline> PointSizeTestInstance::createPipeline (void)
1955 {
1956 	const DeviceInterface&						vkd									(m_context.getDeviceInterface());
1957 	const VkDevice								vkDevice							(m_context.getDevice());
1958 	const std::vector<VkViewport>				viewports							(1, makeViewport(tcu::UVec2(m_renderSize)));
1959 	const std::vector<VkRect2D>					scissors							(1, makeRect2D(tcu::UVec2(m_renderSize)));
1960 
1961 	const VkVertexInputBindingDescription		vertexInputBindingDescription		=
1962 	{
1963 		0u,									// deUint32					binding;
1964 		(deUint32)(2 * sizeof(tcu::Vec4)),	// deUint32					strideInBytes;
1965 		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	stepRate;
1966 	};
1967 
1968 	const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[2]	=
1969 	{
1970 		{
1971 			0u,								// deUint32	location;
1972 			0u,								// deUint32	binding;
1973 			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1974 			0u								// deUint32	offsetInBytes;
1975 		},
1976 		{
1977 			1u,								// deUint32	location;
1978 			0u,								// deUint32	binding;
1979 			VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
1980 			(deUint32)sizeof(tcu::Vec4)		// deUint32	offsetInBytes;
1981 		}
1982 	};
1983 
1984 	const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
1985 	{
1986 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
1987 		DE_NULL,													// const void*								pNext;
1988 		0,															// VkPipelineVertexInputStateCreateFlags	flags;
1989 		1u,															// deUint32									bindingCount;
1990 		&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1991 		2u,															// deUint32									attributeCount;
1992 		vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1993 	};
1994 
1995 	return makeGraphicsPipeline(vkd,									// const DeviceInterface&							 vk
1996 								vkDevice,								// const VkDevice									 device
1997 								*m_pipelineLayout,						// const VkPipelineLayout							 pipelineLayout
1998 								*m_vertexShaderModule,					// const VkShaderModule								 vertexShaderModule
1999 								DE_NULL,								// const VkShaderModule								 tessellationControlShaderModule
2000 								DE_NULL,								// const VkShaderModule								 tessellationEvalShaderModule
2001 								DE_NULL,								// const VkShaderModule								 geometryShaderModule
2002 								*m_fragmentShaderModule,				// const VkShaderModule								 fragmentShaderModule
2003 								*m_renderPass,							// const VkRenderPass								 renderPass
2004 								viewports,								// const std::vector<VkViewport>&					 viewports
2005 								scissors,								// const std::vector<VkRect2D>&						 scissors
2006 								VK_PRIMITIVE_TOPOLOGY_POINT_LIST,		// const VkPrimitiveTopology						 topology
2007 								0u,										// const deUint32									 subpass
2008 								0u,										// const deUint32									 patchControlPoints
2009 								&vertexInputStateParams,				// const VkPipelineVertexInputStateCreateInfo*		 vertexInputStateCreateInfo
2010 								getRasterizationStateCreateInfo(),		// const VkPipelineRasterizationStateCreateInfo*	 rasterizationStateCreateInfo
2011 								DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*		 multisampleStateCreateInfo
2012 								DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*		 depthStencilStateCreateInfo,
2013 								getColorBlendStateCreateInfo());		// const VkPipelineColorBlendStateCreateInfo*		 colorBlendStateCreateInfo
2014 }
2015 
bindDrawData(VkCommandBuffer commandBuffer,VkPipeline graphicsPipeline,VkBuffer vertexBuffer)2016 void PointSizeTestInstance::bindDrawData (VkCommandBuffer commandBuffer, VkPipeline graphicsPipeline, VkBuffer vertexBuffer)
2017 {
2018 	const DeviceInterface&	vkd					(m_context.getDeviceInterface());
2019 	const VkDevice			vkDevice			(m_context.getDevice());
2020 	const VkDeviceSize		vertexBufferOffset	= 0;
2021 
2022 	vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
2023 	vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
2024 	vkd.cmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
2025 
2026 	// Set Point Size
2027 	{
2028 		float pointSize = getPointSize();
2029 
2030 		deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
2031 		flushAlloc(vkd, vkDevice, *m_uniformBufferMemory);
2032 	}
2033 }
2034 
drawPoint(tcu::PixelBufferAccess & result,PointSceneSpec::ScenePoint & point)2035 void PointSizeTestInstance::drawPoint (tcu::PixelBufferAccess& result, PointSceneSpec::ScenePoint& point)
2036 {
2037 	const tcu::Vec4			positionData		(point.position);
2038 	const tcu::Vec4			colorData			(point.color);
2039 
2040 	const DeviceInterface&	vkd					(m_context.getDeviceInterface());
2041 	const VkDevice			vkDevice			(m_context.getDevice());
2042 	const VkQueue			queue				(m_context.getUniversalQueue());
2043 	const deUint32			queueFamilyIndex	(m_context.getUniversalQueueFamilyIndex());
2044 	const size_t			attributeBatchSize	(sizeof(tcu::Vec4));
2045 	Allocator&				allocator			(m_context.getDefaultAllocator());
2046 
2047 	Move<VkCommandBuffer>	commandBuffer;
2048 	Move<VkPipeline>		graphicsPipeline;
2049 	Move<VkBuffer>			vertexBuffer;
2050 	de::MovePtr<Allocation>	vertexBufferMemory;
2051 
2052 	// Create Graphics Pipeline
2053 	graphicsPipeline = createPipeline();
2054 
2055 	// Create Vertex Buffer
2056 	{
2057 		const VkBufferCreateInfo	vertexBufferParams =
2058 		{
2059 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
2060 			DE_NULL,								// const void*			pNext;
2061 			0u,										// VkBufferCreateFlags	flags;
2062 			attributeBatchSize * 2,					// VkDeviceSize			size;
2063 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,		// VkBufferUsageFlags	usage;
2064 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
2065 			1u,										// deUint32				queueFamilyCount;
2066 			&queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
2067 		};
2068 
2069 		vertexBuffer		= createBuffer(vkd, vkDevice, &vertexBufferParams);
2070 		vertexBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
2071 
2072 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
2073 
2074 		// Load vertices into vertex buffer
2075 		deMemcpy(vertexBufferMemory->getHostPtr(), &positionData, attributeBatchSize);
2076 		deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) +  attributeBatchSize, &colorData, attributeBatchSize);
2077 		flushAlloc(vkd, vkDevice, *vertexBufferMemory);
2078 	}
2079 
2080 	// Create Command Buffer
2081 	commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2082 
2083 	// Begin Command Buffer
2084 	beginCommandBuffer(vkd, *commandBuffer);
2085 
2086 	addImageTransitionBarrier(*commandBuffer, *m_image,
2087 							  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,			// VkPipelineStageFlags		srcStageMask
2088 							  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,			// VkPipelineStageFlags		dstStageMask
2089 							  0,											// VkAccessFlags			srcAccessMask
2090 							  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask
2091 							  VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			oldLayout;
2092 							  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);	// VkImageLayout			newLayout;
2093 
2094 	// Begin Render Pass
2095 	beginRenderPass(vkd, *commandBuffer, *m_renderPass, *m_frameBuffer, vk::makeRect2D(0, 0, m_renderSize, m_renderSize), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
2096 
2097 	bindDrawData(commandBuffer.get(), graphicsPipeline.get(), vertexBuffer.get());
2098 	vkd.cmdDraw(*commandBuffer, 1, 1, 0, 0);
2099 	endRenderPass(vkd, *commandBuffer);
2100 
2101 	// Copy Image
2102 	copyImageToBuffer(vkd, *commandBuffer, *m_image, *m_resultBuffer, tcu::IVec2(m_renderSize, m_renderSize));
2103 
2104 	endCommandBuffer(vkd, *commandBuffer);
2105 
2106 	// Submit
2107 	submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
2108 
2109 	invalidateAlloc(vkd, vkDevice, *m_resultBufferMemory);
2110 #ifdef CTS_USES_VULKANSC
2111 	if (m_context.getTestContext().getCommandLine().isSubProcess())
2112 #endif // CTS_USES_VULKANSC
2113 	{
2114 		tcu::copy(result, tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
2115 	}
2116 }
2117 
verifyPoint(tcu::TestLog & log,tcu::PixelBufferAccess & image,float pointSize)2118 bool PointSizeTestInstance::verifyPoint (tcu::TestLog& log, tcu::PixelBufferAccess& image, float pointSize)
2119 {
2120 	const float	expectedPointColor				(1.0f);
2121 	const float	expectedBackgroundColor			(0.0f);
2122 	deUint32	pointWidth						(0u);
2123 	deUint32	pointHeight						(0u);
2124 	bool		incorrectlyColoredPixelsFound	(false);
2125 	bool		isOk							(true);
2126 
2127 	// Verify rasterized point width and color
2128 	for (size_t x = 0; x < (deUint32)image.getWidth(); x++)
2129 	{
2130 		float pixelColor = image.getPixel((deUint32)x, image.getHeight() / 2).x();
2131 
2132 		if (pixelColor == expectedPointColor)
2133 			pointWidth++;
2134 
2135 		if ((pixelColor != expectedPointColor) && (pixelColor != expectedBackgroundColor))
2136 			incorrectlyColoredPixelsFound = true;
2137 	}
2138 
2139 	// Verify rasterized point height and color
2140 	for (size_t y = 0; y < (deUint32)image.getHeight(); y++)
2141 	{
2142 		float pixelColor = image.getPixel((deUint32)y, image.getWidth() / 2).x();
2143 
2144 		if (pixelColor == expectedPointColor)
2145 			pointHeight++;
2146 
2147 		if ((pixelColor != expectedPointColor) && (pixelColor != expectedBackgroundColor))
2148 			incorrectlyColoredPixelsFound = true;
2149 	}
2150 
2151 	// Compare amount of rasterized point pixels to expected pointSize.
2152 	if ((pointWidth != (deUint32)deRoundFloatToInt32(pointSize)) || (pointHeight != (deUint32)deRoundFloatToInt32(pointSize)))
2153 	{
2154 		log << tcu::TestLog::Message << "Incorrect point size. Expected pointSize: " << de::toString(pointSize)
2155 			<< ". Rasterized point width: " << pointWidth << " pixels, height: "
2156 			<< pointHeight << " pixels." << tcu::TestLog::EndMessage;
2157 
2158 		isOk = false;
2159 	}
2160 
2161 	// Check incorrectly colored pixels
2162 	if (incorrectlyColoredPixelsFound)
2163 	{
2164 		log << tcu::TestLog::Message << "Incorrectly colored pixels found." << tcu::TestLog::EndMessage;
2165 		isOk = false;
2166 	}
2167 
2168 	return isOk;
2169 }
2170 
isPointSizeClamped(float pointSize,float maxPointSizeLimit)2171 bool PointSizeTestInstance::isPointSizeClamped (float pointSize, float maxPointSizeLimit)
2172 {
2173 	return (pointSize == maxPointSizeLimit);
2174 }
2175 
2176 class PointDefaultSizeTestInstance : public PointSizeTestInstance
2177 {
2178 public:
2179 								PointDefaultSizeTestInstance	(Context& context, deUint32 renderSize, VkShaderStageFlags stage);
2180 
2181 protected:
2182 	Move<VkPipeline>			createPipeline					(void) override;
2183 	void						bindDrawData					(VkCommandBuffer commandBuffer, VkPipeline graphicsPipeline, VkBuffer vertexBuffer) override;
2184 
2185 	const VkShaderStageFlags	m_tessellationBits				= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
2186 	const VkShaderStageFlags	m_geometryBits					= VK_SHADER_STAGE_GEOMETRY_BIT;
2187 
2188 	Move<VkShaderModule>		m_tessellationControlShaderModule;
2189 	Move<VkShaderModule>		m_tessellationEvaluationShaderModule;
2190 	Move<VkShaderModule>		m_geometryShaderModule;
2191 
2192 	bool						m_hasTessellationStage;
2193 	bool						m_hasGeometryStage;
2194 };
2195 
PointDefaultSizeTestInstance(Context & context,deUint32 renderSize,VkShaderStageFlags stage)2196 PointDefaultSizeTestInstance::PointDefaultSizeTestInstance	(Context& context, deUint32 renderSize, VkShaderStageFlags stage)
2197 	: PointSizeTestInstance(context, renderSize, 1.0f)
2198 	, m_hasTessellationStage(stage & m_tessellationBits)
2199 	, m_hasGeometryStage(stage & m_geometryBits)
2200 {
2201 	const DeviceInterface&		vkd					= m_context.getDeviceInterface();
2202 	const VkDevice				vkDevice			= m_context.getDevice();
2203 
2204 	if (m_hasTessellationStage)
2205 	{
2206 		m_tessellationControlShaderModule			= createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("tessellation_control_shader"), 0);
2207 		m_tessellationEvaluationShaderModule		= createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("tessellation_evaluation_shader"), 0);
2208 	}
2209 
2210 	if (m_hasGeometryStage)
2211 	{
2212 		m_geometryShaderModule						= createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("geometry_shader"), 0);
2213 	}
2214 }
2215 
createPipeline(void)2216 Move<VkPipeline> PointDefaultSizeTestInstance::createPipeline (void)
2217 {
2218 	const DeviceInterface&						vkd									(m_context.getDeviceInterface());
2219 	const VkDevice								vkDevice							(m_context.getDevice());
2220 	const std::vector<VkViewport>				viewports							(1, makeViewport(tcu::UVec2(m_renderSize)));
2221 	const std::vector<VkRect2D>					scissors							(1, makeRect2D(tcu::UVec2(m_renderSize)));
2222 	const VkPrimitiveTopology					topology							= m_hasTessellationStage ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
2223 	const deUint32								patchCount							= m_hasTessellationStage ? 1u : 0u;
2224 
2225 	const VkVertexInputBindingDescription		vertexInputBindingDescription		=
2226 	{
2227 		0u,									// deUint32					binding;
2228 		(deUint32)(2 * sizeof(tcu::Vec4)),	// deUint32					strideInBytes;
2229 		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	stepRate;
2230 	};
2231 
2232 	const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions	=
2233 	{
2234 		0u,								// deUint32	location;
2235 		0u,								// deUint32	binding;
2236 		VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format;
2237 		0u								// deUint32	offsetInBytes;
2238 	};
2239 
2240 	const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
2241 	{
2242 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
2243 		DE_NULL,													// const void*								pNext;
2244 		0,															// VkPipelineVertexInputStateCreateFlags	flags;
2245 		1u,															// deUint32									bindingCount;
2246 		&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
2247 		1u,															// deUint32									attributeCount;
2248 		&vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
2249 	};
2250 
2251 	return makeGraphicsPipeline(vkd,									// const DeviceInterface&							 vk
2252 								vkDevice,								// const VkDevice									 device
2253 								*m_pipelineLayout,						// const VkPipelineLayout							 pipelineLayout
2254 								*m_vertexShaderModule,					// const VkShaderModule								 vertexShaderModule
2255 								*m_tessellationControlShaderModule,		// const VkShaderModule								 tessellationControlShaderModule
2256 								*m_tessellationEvaluationShaderModule,	// const VkShaderModule								 tessellationEvalShaderModule
2257 								*m_geometryShaderModule,				// const VkShaderModule								 geometryShaderModule
2258 								*m_fragmentShaderModule,				// const VkShaderModule								 fragmentShaderModule
2259 								*m_renderPass,							// const VkRenderPass								 renderPass
2260 								viewports,								// const std::vector<VkViewport>&					 viewports
2261 								scissors,								// const std::vector<VkRect2D>&						 scissors
2262 								topology,								// const VkPrimitiveTopology						 topology
2263 								0u,										// const deUint32									 subpass
2264 								patchCount,								// const deUint32									 patchControlPoints
2265 								&vertexInputStateParams,				// const VkPipelineVertexInputStateCreateInfo*		 vertexInputStateCreateInfo
2266 								getRasterizationStateCreateInfo(),		// const VkPipelineRasterizationStateCreateInfo*	 rasterizationStateCreateInfo
2267 								DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*		 multisampleStateCreateInfo
2268 								DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*		 depthStencilStateCreateInfo,
2269 								getColorBlendStateCreateInfo());		// const VkPipelineColorBlendStateCreateInfo*		 colorBlendStateCreateInfo
2270 }
2271 
bindDrawData(VkCommandBuffer commandBuffer,VkPipeline graphicsPipeline,VkBuffer vertexBuffer)2272 void PointDefaultSizeTestInstance::bindDrawData (VkCommandBuffer commandBuffer, VkPipeline graphicsPipeline, VkBuffer vertexBuffer)
2273 {
2274 	const DeviceInterface&	vkd					(m_context.getDeviceInterface());
2275 	const VkDeviceSize		vertexBufferOffset	= 0;
2276 
2277 	vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
2278 	vkd.cmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
2279 }
2280 
2281 class PointDefaultSizeTestCase : public BaseRenderingTestCase
2282 {
2283 public:
2284 					PointDefaultSizeTestCase	(tcu::TestContext&		context,
2285 												 std::string			name,
2286 												 deUint32				renderSize,
2287 												 VkShaderStageFlags		stage,
2288 												 VkSampleCountFlagBits	sampleCount = VK_SAMPLE_COUNT_1_BIT);
2289 
2290 	void			initPrograms				(vk::SourceCollections& programCollection) const override;
2291 	TestInstance*	createInstance				(Context& context) const override;
2292 	void			checkSupport				(Context& context) const override;
2293 
2294 protected:
2295 	const deUint32				m_renderSize;
2296 	const VkShaderStageFlags	m_stage;
2297 };
2298 
PointDefaultSizeTestCase(tcu::TestContext & context,std::string name,deUint32 renderSize,VkShaderStageFlags stage,VkSampleCountFlagBits sampleCount)2299 PointDefaultSizeTestCase::PointDefaultSizeTestCase	(tcu::TestContext&		context,
2300 													 std::string			name,
2301 													 deUint32				renderSize,
2302 													 VkShaderStageFlags		stage,
2303 													 VkSampleCountFlagBits	sampleCount)
2304 	: BaseRenderingTestCase	(context, name, sampleCount)
2305 	, m_renderSize			(renderSize)
2306 	, m_stage				(stage)
2307 {
2308 }
2309 
initPrograms(vk::SourceCollections & programCollection) const2310 void PointDefaultSizeTestCase::initPrograms			(vk::SourceCollections& programCollection) const
2311 {
2312 	std::ostringstream vert;
2313 	std::ostringstream tesc;
2314 	std::ostringstream tese;
2315 	std::ostringstream geom;
2316 	std::ostringstream frag;
2317 
2318 	vert
2319 		<< "#version 450\n"
2320 		<< "layout(location = 0) in highp vec4 a_position;\n"
2321 		<< "void main()"
2322 		<< "{\n"
2323 		<< "	gl_Position = a_position;\n"
2324 		<< "}\n"
2325 		;
2326 
2327 	tesc
2328 		<< "#version 450\n"
2329 		<< "layout(vertices = 1) out;\n"
2330 		<< "void main()\n"
2331 		<< "{\n"
2332 		<< "	gl_TessLevelOuter[0] = 1.0;\n"
2333 		<< "	gl_TessLevelOuter[1] = 1.0;\n"
2334 		<< "	gl_TessLevelOuter[2] = 1.0;\n"
2335 		<< "	gl_TessLevelOuter[3] = 1.0;\n"
2336 		<< "	gl_TessLevelInner[0] = 1.0;\n"
2337 		<< "	gl_TessLevelInner[1] = 1.0;\n"
2338 		<< "\n"
2339 		<< "	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
2340 		<< "}\n"
2341 		;
2342 
2343 	tese
2344 		<< "#version 450\n"
2345 		<< "layout(isolines, point_mode) in;\n"
2346 		<< "void main()\n"
2347 		<< "{\n"
2348 		<< "	gl_Position = gl_in[0].gl_Position;\n"
2349 		<< "}\n"
2350 		;
2351 
2352 	geom
2353 		<< "#version 450\n"
2354 		<< "layout(points) in;\n"
2355 		<< "layout(points, max_vertices=1) out;\n"
2356 		<< "void main()\n"
2357 		<< "{\n"
2358 		<< "	gl_Position = gl_in[0].gl_Position;\n"
2359 		<< "	EmitVertex();\n"
2360 		<< "	EndPrimitive();\n"
2361 		<< "}\n"
2362 		;
2363 
2364 	frag
2365 		<< "#version 450\n"
2366 		<< "layout(location = 0) out highp vec4 fragColor;\n"
2367 		<< "void main()"
2368 		<< "{\n"
2369 		<< "	fragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
2370 		<< "}\n"
2371 		;
2372 
2373 	programCollection.glslSources.add("vertext_shader") << glu::VertexSource(vert.str());
2374 	programCollection.glslSources.add("tessellation_control_shader") << glu::TessellationControlSource(tesc.str());
2375 	programCollection.glslSources.add("tessellation_evaluation_shader") << glu::TessellationEvaluationSource(tese.str());
2376 	programCollection.glslSources.add("geometry_shader") << glu::GeometrySource(geom.str());
2377 	programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(frag.str());
2378 }
2379 
createInstance(Context & context) const2380 TestInstance* PointDefaultSizeTestCase::createInstance	(Context& context) const
2381 {
2382 	VkPhysicalDeviceProperties	properties	(context.getDeviceProperties());
2383 
2384 	if (m_renderSize > properties.limits.maxViewportDimensions[0] || m_renderSize > properties.limits.maxViewportDimensions[1])
2385 		TCU_THROW(NotSupportedError , "Viewport dimensions not supported");
2386 
2387 	if (m_renderSize > properties.limits.maxFramebufferWidth || m_renderSize > properties.limits.maxFramebufferHeight)
2388 		TCU_THROW(NotSupportedError , "Framebuffer width/height not supported");
2389 
2390 	return new PointDefaultSizeTestInstance(context, m_renderSize, m_stage);
2391 }
2392 
checkSupport(Context & context) const2393 void PointDefaultSizeTestCase::checkSupport				(Context& context) const
2394 {
2395 	const VkShaderStageFlags	tessellationBits	= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
2396 	const VkShaderStageFlags	geometryBits		= VK_SHADER_STAGE_GEOMETRY_BIT;
2397 
2398 	if (m_stage & tessellationBits)
2399 	{
2400 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE);
2401 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
2402 	}
2403 
2404 	if (m_stage & geometryBits)
2405 	{
2406 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE);
2407 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
2408 	}
2409 
2410 	context.requireDeviceFunctionality("VK_KHR_maintenance5");
2411 }
2412 
2413 template <typename ConcreteTestInstance>
2414 class BaseTestCase : public BaseRenderingTestCase
2415 {
2416 public:
BaseTestCase(tcu::TestContext & context,const std::string & name,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)2417 							BaseTestCase	(tcu::TestContext& context, const std::string& name, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
2418 								: BaseRenderingTestCase(context, name, sampleCount)
2419 							{}
2420 
createInstance(Context & context) const2421 	virtual TestInstance*	createInstance	(Context& context) const
2422 							{
2423 								return new ConcreteTestInstance(context, m_sampleCount);
2424 							}
2425 };
2426 
2427 class TrianglesTestInstance : public BaseTriangleTestInstance
2428 {
2429 public:
TrianglesTestInstance(Context & context,VkSampleCountFlagBits sampleCount)2430 							TrianglesTestInstance	(Context& context, VkSampleCountFlagBits sampleCount)
2431 								: BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, sampleCount)
2432 							{}
2433 
2434 	void					generateTriangles		(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
2435 };
2436 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)2437 void TrianglesTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
2438 {
2439 	outData.resize(6);
2440 
2441 	switch (iteration)
2442 	{
2443 		case 0:
2444 			// \note: these values are chosen arbitrarily
2445 			outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
2446 			outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
2447 			outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
2448 			outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
2449 			outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
2450 			outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
2451 			break;
2452 
2453 		case 1:
2454 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
2455 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
2456 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
2457 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
2458 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
2459 			outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
2460 			break;
2461 
2462 		case 2:
2463 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
2464 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
2465 			outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
2466 			outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
2467 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
2468 			outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
2469 			break;
2470 	}
2471 
2472 	outTriangles.resize(2);
2473 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
2474 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = false;
2475 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = false;
2476 
2477 	outTriangles[1].positions[0] = outData[3];	outTriangles[1].sharedEdge[0] = false;
2478 	outTriangles[1].positions[1] = outData[4];	outTriangles[1].sharedEdge[1] = false;
2479 	outTriangles[1].positions[2] = outData[5];	outTriangles[1].sharedEdge[2] = false;
2480 
2481 	// log
2482 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
2483 	for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
2484 	{
2485 		m_context.getTestContext().getLog()
2486 			<< tcu::TestLog::Message
2487 			<< "Triangle " << (triangleNdx+1) << ":"
2488 			<< "\n\t" << outTriangles[triangleNdx].positions[0]
2489 			<< "\n\t" << outTriangles[triangleNdx].positions[1]
2490 			<< "\n\t" << outTriangles[triangleNdx].positions[2]
2491 			<< tcu::TestLog::EndMessage;
2492 	}
2493 }
2494 
2495 class TriangleStripTestInstance : public BaseTriangleTestInstance
2496 {
2497 public:
TriangleStripTestInstance(Context & context,VkSampleCountFlagBits sampleCount)2498 				TriangleStripTestInstance		(Context& context, VkSampleCountFlagBits sampleCount)
2499 					: BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, sampleCount)
2500 				{}
2501 
2502 	void		generateTriangles				(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
2503 };
2504 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)2505 void TriangleStripTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
2506 {
2507 	outData.resize(5);
2508 
2509 	switch (iteration)
2510 	{
2511 		case 0:
2512 			// \note: these values are chosen arbitrarily
2513 			outData[0] = tcu::Vec4(-0.504f,  0.8f,   0.0f, 1.0f);
2514 			outData[1] = tcu::Vec4(-0.2f,   -0.2f,   0.0f, 1.0f);
2515 			outData[2] = tcu::Vec4(-0.2f,    0.199f, 0.0f, 1.0f);
2516 			outData[3] = tcu::Vec4( 0.5f,    0.201f, 0.0f, 1.0f);
2517 			outData[4] = tcu::Vec4( 1.5f,    0.4f,   0.0f, 1.0f);
2518 			break;
2519 
2520 		case 1:
2521 			outData[0] = tcu::Vec4(-0.499f, 0.129f,  0.0f, 1.0f);
2522 			outData[1] = tcu::Vec4(-0.501f,  -0.3f,  0.0f, 1.0f);
2523 			outData[2] = tcu::Vec4(  0.11f,  -0.2f,  0.0f, 1.0f);
2524 			outData[3] = tcu::Vec4(  0.11f,  -0.31f, 0.0f, 1.0f);
2525 			outData[4] = tcu::Vec4(  0.88f,   0.9f,  0.0f, 1.0f);
2526 			break;
2527 
2528 		case 2:
2529 			outData[0] = tcu::Vec4( -0.9f, -0.3f,  0.0f, 1.0f);
2530 			outData[1] = tcu::Vec4(  1.1f, -0.9f,  0.0f, 1.0f);
2531 			outData[2] = tcu::Vec4(-0.87f, -0.1f,  0.0f, 1.0f);
2532 			outData[3] = tcu::Vec4(-0.11f,  0.19f, 0.0f, 1.0f);
2533 			outData[4] = tcu::Vec4( 0.88f,  0.7f,  0.0f, 1.0f);
2534 			break;
2535 	}
2536 
2537 	outTriangles.resize(3);
2538 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
2539 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = true;
2540 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = false;
2541 
2542 	outTriangles[1].positions[0] = outData[2];	outTriangles[1].sharedEdge[0] = true;
2543 	outTriangles[1].positions[1] = outData[1];	outTriangles[1].sharedEdge[1] = false;
2544 	outTriangles[1].positions[2] = outData[3];	outTriangles[1].sharedEdge[2] = true;
2545 
2546 	outTriangles[2].positions[0] = outData[2];	outTriangles[2].sharedEdge[0] = true;
2547 	outTriangles[2].positions[1] = outData[3];	outTriangles[2].sharedEdge[1] = false;
2548 	outTriangles[2].positions[2] = outData[4];	outTriangles[2].sharedEdge[2] = false;
2549 
2550 	// log
2551 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
2552 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
2553 	{
2554 		m_context.getTestContext().getLog()
2555 			<< tcu::TestLog::Message
2556 			<< "\t" << outData[vtxNdx]
2557 			<< tcu::TestLog::EndMessage;
2558 	}
2559 }
2560 
2561 class TriangleFanTestInstance : public BaseTriangleTestInstance
2562 {
2563 public:
2564 				TriangleFanTestInstance			(Context& context, VkSampleCountFlagBits sampleCount);
2565 
2566 
2567 	void		generateTriangles				(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
2568 };
2569 
TriangleFanTestInstance(Context & context,VkSampleCountFlagBits sampleCount)2570 TriangleFanTestInstance::TriangleFanTestInstance (Context& context, VkSampleCountFlagBits sampleCount)
2571 	: BaseTriangleTestInstance(context, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, sampleCount)
2572 {
2573 #ifndef CTS_USES_VULKANSC
2574 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
2575 		!context.getPortabilitySubsetFeatures().triangleFans)
2576 	{
2577 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
2578 	}
2579 #endif // CTS_USES_VULKANSC
2580 }
2581 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)2582 void TriangleFanTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
2583 {
2584 	outData.resize(5);
2585 
2586 	switch (iteration)
2587 	{
2588 		case 0:
2589 			// \note: these values are chosen arbitrarily
2590 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
2591 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
2592 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
2593 			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
2594 			outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
2595 			break;
2596 
2597 		case 1:
2598 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
2599 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
2600 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
2601 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
2602 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
2603 			break;
2604 
2605 		case 2:
2606 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
2607 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
2608 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
2609 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
2610 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
2611 			break;
2612 	}
2613 
2614 	outTriangles.resize(3);
2615 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
2616 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = false;
2617 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = true;
2618 
2619 	outTriangles[1].positions[0] = outData[0];	outTriangles[1].sharedEdge[0] = true;
2620 	outTriangles[1].positions[1] = outData[2];	outTriangles[1].sharedEdge[1] = false;
2621 	outTriangles[1].positions[2] = outData[3];	outTriangles[1].sharedEdge[2] = true;
2622 
2623 	outTriangles[2].positions[0] = outData[0];	outTriangles[2].sharedEdge[0] = true;
2624 	outTriangles[2].positions[1] = outData[3];	outTriangles[2].sharedEdge[1] = false;
2625 	outTriangles[2].positions[2] = outData[4];	outTriangles[2].sharedEdge[2] = false;
2626 
2627 	// log
2628 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
2629 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
2630 	{
2631 		m_context.getTestContext().getLog()
2632 			<< tcu::TestLog::Message
2633 			<< "\t" << outData[vtxNdx]
2634 			<< tcu::TestLog::EndMessage;
2635 	}
2636 }
2637 
2638 struct ConservativeTestConfig
2639 {
2640 	VkConservativeRasterizationModeEXT	conservativeRasterizationMode;
2641 	float								extraOverestimationSize;
2642 	VkPrimitiveTopology					primitiveTopology;
2643 	bool								degeneratePrimitives;
2644 	float								lineWidth;
2645 	deUint32							resolution;
2646 };
2647 
getExtraOverestimationSize(const float overestimationSizeDesired,const VkPhysicalDeviceConservativeRasterizationPropertiesEXT & conservativeRasterizationProperties)2648 float getExtraOverestimationSize (const float overestimationSizeDesired, const VkPhysicalDeviceConservativeRasterizationPropertiesEXT& conservativeRasterizationProperties)
2649 {
2650 	const float extraOverestimationSize	= overestimationSizeDesired == TCU_INFINITY ? conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize
2651 										: overestimationSizeDesired == -TCU_INFINITY ? conservativeRasterizationProperties.extraPrimitiveOverestimationSizeGranularity
2652 										: overestimationSizeDesired;
2653 
2654 	return extraOverestimationSize;
2655 }
2656 
2657 template <typename ConcreteTestInstance>
2658 class ConservativeTestCase : public BaseRenderingTestCase
2659 {
2660 public:
ConservativeTestCase(tcu::TestContext & context,const std::string & name,const ConservativeTestConfig & conservativeTestConfig,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)2661 									ConservativeTestCase		(tcu::TestContext&					context,
2662 																 const std::string&					name,
2663 																 const ConservativeTestConfig&		conservativeTestConfig,
2664 																 VkSampleCountFlagBits				sampleCount = VK_SAMPLE_COUNT_1_BIT)
2665 										: BaseRenderingTestCase		(context, name, sampleCount)
2666 										, m_conservativeTestConfig	(conservativeTestConfig)
2667 									{}
2668 
2669 	virtual void					checkSupport				(Context& context) const;
2670 
createInstance(Context & context) const2671 	virtual TestInstance*			createInstance				(Context& context) const
2672 									{
2673 										return new ConcreteTestInstance(context, m_conservativeTestConfig, m_sampleCount);
2674 									}
2675 
2676 protected:
2677 	bool							isUseLineSubPixel			(Context& context) const;
2678 	deUint32						getSubPixelResolution		(Context& context) const;
2679 
2680 	const ConservativeTestConfig	m_conservativeTestConfig;
2681 };
2682 
2683 template <typename ConcreteTestInstance>
isUseLineSubPixel(Context & context) const2684 bool ConservativeTestCase<ConcreteTestInstance>::isUseLineSubPixel (Context& context) const
2685 {
2686 	return (isPrimitiveTopologyLine(m_conservativeTestConfig.primitiveTopology) && context.isDeviceFunctionalitySupported("VK_EXT_line_rasterization"));
2687 }
2688 
2689 template <typename ConcreteTestInstance>
getSubPixelResolution(Context & context) const2690 deUint32 ConservativeTestCase<ConcreteTestInstance>::getSubPixelResolution (Context& context) const
2691 {
2692 	if (isUseLineSubPixel(context))
2693 	{
2694 		const VkPhysicalDeviceLineRasterizationPropertiesEXT	lineRasterizationPropertiesEXT	= context.getLineRasterizationPropertiesEXT();
2695 
2696 		return lineRasterizationPropertiesEXT.lineSubPixelPrecisionBits;
2697 	}
2698 	else
2699 	{
2700 		return context.getDeviceProperties().limits.subPixelPrecisionBits;
2701 	}
2702 }
2703 
2704 template <typename ConcreteTestInstance>
checkSupport(Context & context) const2705 void ConservativeTestCase<ConcreteTestInstance>::checkSupport (Context& context) const
2706 {
2707 	context.requireDeviceFunctionality("VK_EXT_conservative_rasterization");
2708 
2709 	const VkPhysicalDeviceConservativeRasterizationPropertiesEXT	conservativeRasterizationProperties	= context.getConservativeRasterizationPropertiesEXT();
2710 	const deUint32													subPixelPrecisionBits				= getSubPixelResolution(context);
2711 	const deUint32													subPixelPrecision					= 1<<subPixelPrecisionBits;
2712 	const bool														linesPrecision						= isUseLineSubPixel(context);
2713 	const float														primitiveOverestimationSizeMult		= float(subPixelPrecision) * conservativeRasterizationProperties.primitiveOverestimationSize;
2714 	const bool														topologyLineOrPoint					= isPrimitiveTopologyLine(m_conservativeTestConfig.primitiveTopology) || isPrimitiveTopologyPoint(m_conservativeTestConfig.primitiveTopology);
2715 
2716 	DE_ASSERT(subPixelPrecisionBits < sizeof(deUint32) * 8);
2717 
2718 	context.getTestContext().getLog()
2719 		<< tcu::TestLog::Message
2720 		<< "maxExtraPrimitiveOverestimationSize="			<< conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize << '\n'
2721 		<< "extraPrimitiveOverestimationSizeGranularity="	<< conservativeRasterizationProperties.extraPrimitiveOverestimationSizeGranularity << '\n'
2722 		<< "degenerateLinesRasterized="						<< conservativeRasterizationProperties.degenerateLinesRasterized << '\n'
2723 		<< "degenerateTrianglesRasterized="					<< conservativeRasterizationProperties.degenerateTrianglesRasterized << '\n'
2724 		<< "primitiveOverestimationSize="					<< conservativeRasterizationProperties.primitiveOverestimationSize << " (==" << primitiveOverestimationSizeMult << '/' << subPixelPrecision << ")\n"
2725 		<< "subPixelPrecisionBits="							<< subPixelPrecisionBits << (linesPrecision ? " (using VK_EXT_line_rasterization)" : " (using limits)") << '\n'
2726 		<< tcu::TestLog::EndMessage;
2727 
2728 	if (conservativeRasterizationProperties.extraPrimitiveOverestimationSizeGranularity > conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize)
2729 		TCU_FAIL("Granularity cannot be greater than maximum extra size");
2730 
2731 	if (topologyLineOrPoint)
2732 	{
2733 		if (!conservativeRasterizationProperties.conservativePointAndLineRasterization)
2734 			TCU_THROW(NotSupportedError, "Conservative line and point rasterization is not supported");
2735 	}
2736 
2737 	if (m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT)
2738 	{
2739 		if (conservativeRasterizationProperties.primitiveUnderestimation == DE_FALSE)
2740 			TCU_THROW(NotSupportedError, "Underestimation is not supported");
2741 
2742 		if (isPrimitiveTopologyLine(m_conservativeTestConfig.primitiveTopology))
2743 		{
2744 			const float	testLineWidth	= m_conservativeTestConfig.lineWidth;
2745 
2746 			if (testLineWidth != 1.0f)
2747 			{
2748 				const VkPhysicalDeviceLimits&	limits					= context.getDeviceProperties().limits;
2749 				const float						lineWidthRange[2]		= { limits.lineWidthRange[0], limits.lineWidthRange[1] };
2750 				const float						lineWidthGranularity	= limits.lineWidthGranularity;
2751 
2752 				context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_WIDE_LINES);
2753 
2754 				if (lineWidthGranularity == 0.0f)
2755 					TCU_THROW(NotSupportedError, "Wide lines required for test, but are not supported");
2756 
2757 				DE_ASSERT(lineWidthGranularity > 0.0f && lineWidthRange[0] > 0.0f && lineWidthRange[1] >= lineWidthRange[0]);
2758 
2759 				if (!de::inBounds(testLineWidth, lineWidthRange[0], lineWidthRange[1]))
2760 					TCU_THROW(NotSupportedError, "Tested line width is not supported");
2761 
2762 				const float	n	= (testLineWidth - lineWidthRange[0]) / lineWidthGranularity;
2763 
2764 				if (deFloatFrac(n) != 0.0f || n * lineWidthGranularity + lineWidthRange[0] != testLineWidth)
2765 					TCU_THROW(NotSupportedError, "Exact match of line width is required for the test");
2766 			}
2767 		}
2768 		else if (isPrimitiveTopologyPoint(m_conservativeTestConfig.primitiveTopology))
2769 		{
2770 			const float	testPointSize	= m_conservativeTestConfig.lineWidth;
2771 
2772 			if (testPointSize != 1.0f)
2773 			{
2774 				const VkPhysicalDeviceLimits&	limits					= context.getDeviceProperties().limits;
2775 				const float						pointSizeRange[2]		= { limits.pointSizeRange[0], limits.pointSizeRange[1] };
2776 				const float						pointSizeGranularity	= limits.pointSizeGranularity;
2777 
2778 				context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_LARGE_POINTS);
2779 
2780 				if (pointSizeGranularity == 0.0f)
2781 					TCU_THROW(NotSupportedError, "Large points required for test, but are not supported");
2782 
2783 				DE_ASSERT(pointSizeGranularity > 0.0f && pointSizeRange[0] > 0.0f && pointSizeRange[1] >= pointSizeRange[0]);
2784 
2785 				if (!de::inBounds(testPointSize, pointSizeRange[0], pointSizeRange[1]))
2786 					TCU_THROW(NotSupportedError, "Tested point size is not supported");
2787 
2788 				const float	n	= (testPointSize - pointSizeRange[0]) / pointSizeGranularity;
2789 
2790 				if (deFloatFrac(n) != 0.0f || n * pointSizeGranularity + pointSizeRange[0] != testPointSize)
2791 					TCU_THROW(NotSupportedError, "Exact match of point size is required for the test");
2792 			}
2793 		}
2794 	}
2795 	else if (m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT)
2796 	{
2797 		const float extraOverestimationSize	= getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, conservativeRasterizationProperties);
2798 
2799 		if (extraOverestimationSize > conservativeRasterizationProperties.maxExtraPrimitiveOverestimationSize)
2800 			TCU_THROW(NotSupportedError, "Specified overestimation size is not supported");
2801 
2802 		if (topologyLineOrPoint)
2803 		{
2804 			if (!conservativeRasterizationProperties.conservativePointAndLineRasterization)
2805 				TCU_THROW(NotSupportedError, "Conservative line and point rasterization is not supported");
2806 		}
2807 
2808 		if (isPrimitiveTopologyTriangle(m_conservativeTestConfig.primitiveTopology))
2809 		{
2810 			if (m_conservativeTestConfig.degeneratePrimitives)
2811 			{
2812 				// Enforce specification minimum required limit to avoid division by zero
2813 				DE_ASSERT(subPixelPrecisionBits >= 4);
2814 
2815 				// Make sure float precision of 22 bits is enough, i.e. resoultion in subpixel quarters less than float precision
2816 				if (m_conservativeTestConfig.resolution * (1<<(subPixelPrecisionBits + 2)) > (1<<21))
2817 					TCU_THROW(NotSupportedError, "Subpixel resolution is too high to generate degenerate primitives");
2818 			}
2819 		}
2820 	}
2821 	else
2822 		TCU_THROW(InternalError, "Non-conservative mode tests are not supported by this class");
2823 }
2824 
2825 class ConservativeTraingleTestInstance : public BaseTriangleTestInstance
2826 {
2827 public:
ConservativeTraingleTestInstance(Context & context,ConservativeTestConfig conservativeTestConfig,VkSampleCountFlagBits sampleCount)2828 																				ConservativeTraingleTestInstance				(Context&				context,
2829 																																 ConservativeTestConfig	conservativeTestConfig,
2830 																																 VkSampleCountFlagBits	sampleCount)
2831 																					: BaseTriangleTestInstance						(context,
2832 																																	 conservativeTestConfig.primitiveTopology,
2833 																																	 sampleCount,
2834 																																	 conservativeTestConfig.resolution)
2835 																					, m_conservativeTestConfig						(conservativeTestConfig)
2836 																					, m_conservativeRasterizationProperties			(context.getConservativeRasterizationPropertiesEXT())
2837 																					, m_rasterizationConservativeStateCreateInfo	(initRasterizationConservativeStateCreateInfo())
2838 																					, m_rasterizationStateCreateInfo				(initRasterizationStateCreateInfo())
2839 																				{}
2840 
2841 	void																		generateTriangles								(int											iteration,
2842 																																 std::vector<tcu::Vec4>&						outData,
2843 																																 std::vector<TriangleSceneSpec::SceneTriangle>&	outTriangles);
2844 	const VkPipelineRasterizationStateCreateInfo*								getRasterizationStateCreateInfo					(void) const;
2845 
2846 protected:
2847 	virtual const VkPipelineRasterizationLineStateCreateInfoEXT*				getLineRasterizationStateCreateInfo				(void);
2848 
2849 	virtual bool																compareAndVerify								(std::vector<TriangleSceneSpec::SceneTriangle>&	triangles,
2850 																																 tcu::Surface&									resultImage,
2851 																																 std::vector<tcu::Vec4>&						drawBuffer);
2852 	virtual bool																compareAndVerifyOverestimatedNormal				(std::vector<TriangleSceneSpec::SceneTriangle>&	triangles,
2853 																																 tcu::Surface&									resultImage);
2854 	virtual bool																compareAndVerifyOverestimatedDegenerate			(std::vector<TriangleSceneSpec::SceneTriangle>&	triangles,
2855 																																 tcu::Surface&									resultImage);
2856 	virtual bool																compareAndVerifyUnderestimatedNormal			(std::vector<TriangleSceneSpec::SceneTriangle>&	triangles,
2857 																																 tcu::Surface&									resultImage);
2858 	virtual bool																compareAndVerifyUnderestimatedDegenerate		(std::vector<TriangleSceneSpec::SceneTriangle>&	triangles,
2859 																																 tcu::Surface&									resultImage);
2860 	void																		generateNormalTriangles							(int											iteration,
2861 																																 std::vector<tcu::Vec4>&						outData,
2862 																																 std::vector<TriangleSceneSpec::SceneTriangle>&	outTriangles);
2863 	void																		generateDegenerateTriangles					(int											iteration,
2864 																																 std::vector<tcu::Vec4>&						outData,
2865 																																 std::vector<TriangleSceneSpec::SceneTriangle>&	outTriangles);
2866 	void																		drawPrimitives									(tcu::Surface&									result,
2867 																																 const std::vector<tcu::Vec4>&					vertexData,
2868 																																 VkPrimitiveTopology							primitiveTopology);
2869 
2870 private:
2871 	const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>	initRasterizationConservativeStateCreateInfo	(void);
2872 	const std::vector<VkPipelineRasterizationStateCreateInfo>					initRasterizationStateCreateInfo				(void);
2873 
2874 	const ConservativeTestConfig												m_conservativeTestConfig;
2875 	const VkPhysicalDeviceConservativeRasterizationPropertiesEXT				m_conservativeRasterizationProperties;
2876 	const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>	m_rasterizationConservativeStateCreateInfo;
2877 	const std::vector<VkPipelineRasterizationStateCreateInfo>					m_rasterizationStateCreateInfo;
2878 };
2879 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)2880 void ConservativeTraingleTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
2881 {
2882 	if (m_conservativeTestConfig.degeneratePrimitives)
2883 		generateDegenerateTriangles(iteration, outData, outTriangles);
2884 	else
2885 		generateNormalTriangles(iteration, outData, outTriangles);
2886 }
2887 
generateNormalTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)2888 void ConservativeTraingleTestInstance::generateNormalTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
2889 {
2890 	const float	halfPixel						= 1.0f / float(m_renderSize);
2891 	const float extraOverestimationSize			= getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
2892 	const float	overestimate					= 2.0f * halfPixel * (m_conservativeRasterizationProperties.primitiveOverestimationSize + extraOverestimationSize);
2893 	const float	overestimateMargin				= overestimate;
2894 	const float	underestimateMargin				= 0.0f;
2895 	const bool	isOverestimate					= m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
2896 	const float	margin							= isOverestimate ? overestimateMargin : underestimateMargin;
2897 	const char*	overestimateIterationComments[]	= { "Corner touch", "Any portion pixel coverage", "Edge touch" };
2898 
2899 	outData.resize(6);
2900 
2901 	switch (iteration)
2902 	{
2903 		case 0:
2904 		{
2905 			// Corner touch
2906 			const float edge	= 2 * halfPixel + margin;
2907 			const float left	= -1.0f + edge;
2908 			const float right	= +1.0f - edge;
2909 			const float up		= -1.0f + edge;
2910 			const float down	= +1.0f - edge;
2911 
2912 			outData[0] = tcu::Vec4( left, down, 0.0f, 1.0f);
2913 			outData[1] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2914 			outData[2] = tcu::Vec4(right, down, 0.0f, 1.0f);
2915 
2916 			outData[3] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2917 			outData[4] = tcu::Vec4(right, down, 0.0f, 1.0f);
2918 			outData[5] = tcu::Vec4(right,   up, 0.0f, 1.0f);
2919 
2920 			break;
2921 		}
2922 
2923 		case 1:
2924 		{
2925 			// Partial coverage
2926 			const float eps		= halfPixel / 32.0f;
2927 			const float edge	= 4.0f * halfPixel  + margin - eps;
2928 			const float left	= -1.0f + edge;
2929 			const float right	= +1.0f - edge;
2930 			const float up		= -1.0f + edge;
2931 			const float down	= +1.0f - edge;
2932 
2933 			outData[0] = tcu::Vec4( left, down, 0.0f, 1.0f);
2934 			outData[1] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2935 			outData[2] = tcu::Vec4(right, down, 0.0f, 1.0f);
2936 
2937 			outData[3] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2938 			outData[4] = tcu::Vec4(right, down, 0.0f, 1.0f);
2939 			outData[5] = tcu::Vec4(right,   up, 0.0f, 1.0f);
2940 
2941 			break;
2942 		}
2943 
2944 		case 2:
2945 		{
2946 			// Edge touch
2947 			const float edge	= 6.0f * halfPixel + margin;
2948 			const float left	= -1.0f + edge;
2949 			const float right	= +1.0f - edge;
2950 			const float up		= -1.0f + edge;
2951 			const float down	= +1.0f - edge;
2952 
2953 			outData[0] = tcu::Vec4( left, down, 0.0f, 1.0f);
2954 			outData[1] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2955 			outData[2] = tcu::Vec4(right, down, 0.0f, 1.0f);
2956 
2957 			outData[3] = tcu::Vec4( left,   up, 0.0f, 1.0f);
2958 			outData[4] = tcu::Vec4(right, down, 0.0f, 1.0f);
2959 			outData[5] = tcu::Vec4(right,   up, 0.0f, 1.0f);
2960 
2961 			break;
2962 		}
2963 
2964 		default:
2965 			TCU_THROW(InternalError, "Unexpected iteration");
2966 	}
2967 
2968 	outTriangles.resize(outData.size() / 3);
2969 
2970 	for (size_t ndx = 0; ndx < outTriangles.size(); ++ndx)
2971 	{
2972 		outTriangles[ndx].positions[0] = outData[3 * ndx + 0];	outTriangles[ndx].sharedEdge[0] = false;
2973 		outTriangles[ndx].positions[1] = outData[3 * ndx + 1];	outTriangles[ndx].sharedEdge[1] = false;
2974 		outTriangles[ndx].positions[2] = outData[3 * ndx + 2];	outTriangles[ndx].sharedEdge[2] = false;
2975 	}
2976 
2977 	// log
2978 	if (isOverestimate)
2979 	{
2980 		m_context.getTestContext().getLog()
2981 			<< tcu::TestLog::Message
2982 			<< "Testing " << overestimateIterationComments[iteration] << " "
2983 			<< "with rendering " << outTriangles.size() << " triangle(s):"
2984 			<< tcu::TestLog::EndMessage;
2985 	}
2986 	else
2987 	{
2988 		m_context.getTestContext().getLog()
2989 			<< tcu::TestLog::Message
2990 			<< "Rendering " << outTriangles.size() << " triangle(s):"
2991 			<< tcu::TestLog::EndMessage;
2992 	}
2993 
2994 	for (size_t ndx = 0; ndx < outTriangles.size(); ++ndx)
2995 	{
2996 		const deUint32	 multiplier	= m_renderSize / 2;
2997 
2998 		m_context.getTestContext().getLog()
2999 			<< tcu::TestLog::Message
3000 			<< "Triangle " << (ndx + 1) << ":"
3001 			<< "\n\t" << outTriangles[ndx].positions[0] << " == " << (float(multiplier) * outTriangles[ndx].positions[0]) << "/" << multiplier
3002 			<< "\n\t" << outTriangles[ndx].positions[1] << " == " << (float(multiplier) * outTriangles[ndx].positions[1]) << "/" << multiplier
3003 			<< "\n\t" << outTriangles[ndx].positions[2] << " == " << (float(multiplier) * outTriangles[ndx].positions[2]) << "/" << multiplier
3004 			<< tcu::TestLog::EndMessage;
3005 	}
3006 }
3007 
generateDegenerateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)3008 void ConservativeTraingleTestInstance::generateDegenerateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
3009 {
3010 	tcu::TestLog&	log								= m_context.getTestContext().getLog();
3011 	const float		pixelSize						= 2.0f / float(m_renderSize);
3012 	const deUint32	subPixels						= 1u << m_context.getDeviceProperties().limits.subPixelPrecisionBits;
3013 	const float		subPixelSize					= pixelSize / float(subPixels);
3014 	const float		extraOverestimationSize			= getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
3015 	const float		totalOverestimate				= m_conservativeRasterizationProperties.primitiveOverestimationSize + extraOverestimationSize;
3016 	const float		totalOverestimateInSubPixels	= deFloatCeil(totalOverestimate * float(subPixels));
3017 	const float		overestimate					= subPixelSize * totalOverestimateInSubPixels;
3018 	const float		overestimateSafetyMargin		= subPixelSize * 0.125f;
3019 	const float		overestimateMargin				= overestimate + overestimateSafetyMargin;
3020 	const float		underestimateMargin				= 0.0f;
3021 	const bool		isOverestimate					= m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
3022 	const float		margin							= isOverestimate ? overestimateMargin : underestimateMargin;
3023 	const char*		overestimateIterationComments[]	= { "Backfacing", "Generate pixels", "Use provoking vertex" };
3024 
3025 	if (pixelSize < 2 * overestimateMargin)
3026 		TCU_THROW(NotSupportedError, "Could not generate degenerate triangle for such overestimate parameters");
3027 
3028 	outData.clear();
3029 
3030 	switch (iteration)
3031 	{
3032 		case 0:
3033 		case 1:
3034 		case 2:
3035 		{
3036 			for (int rowNdx = 0; rowNdx < 3; ++rowNdx)
3037 			for (int colNdx = 0; colNdx < 4; ++colNdx)
3038 			{
3039 				const float	offsetX		= -1.0f + float(4 * (colNdx + 1)) * pixelSize;
3040 				const float	offsetY		= -1.0f + float(4 * (rowNdx + 1)) * pixelSize;
3041 				const float	left		= offsetX + margin;
3042 				const float	right		= offsetX + margin + 0.25f * subPixelSize;
3043 				const float	up			= offsetY + margin;
3044 				const float	down		= offsetY + margin + 0.25f * subPixelSize;
3045 				const bool	luPresent	= (rowNdx & 1) == 0;
3046 				const bool	rdPresent	= (rowNdx & 2) == 0;
3047 				const bool	luCW		= (colNdx & 1) == 0;
3048 				const bool	rdCW		= (colNdx & 2) == 0;
3049 
3050 				DE_ASSERT(left < right);
3051 				DE_ASSERT(up < down);
3052 
3053 				if (luPresent)
3054 				{
3055 					if (luCW)
3056 					{
3057 						// CW triangle left up
3058 						outData.push_back(tcu::Vec4( left, down, 0.0f, 1.0f));
3059 						outData.push_back(tcu::Vec4( left,   up, 0.0f, 1.0f));
3060 						outData.push_back(tcu::Vec4(right,   up, 0.0f, 1.0f));
3061 					}
3062 					else
3063 					{
3064 						// CCW triangle left up
3065 						outData.push_back(tcu::Vec4(right,   up, 0.0f, 1.0f));
3066 						outData.push_back(tcu::Vec4( left,   up, 0.0f, 1.0f));
3067 						outData.push_back(tcu::Vec4( left, down, 0.0f, 1.0f));
3068 					}
3069 				}
3070 
3071 				if (rdPresent)
3072 				{
3073 					if (rdCW)
3074 					{
3075 						// CW triangle right down
3076 						outData.push_back(tcu::Vec4(right,   up, 0.0f, 1.0f));
3077 						outData.push_back(tcu::Vec4(right, down, 0.0f, 1.0f));
3078 						outData.push_back(tcu::Vec4( left, down, 0.0f, 1.0f));
3079 					}
3080 					else
3081 					{
3082 						// CCW triangle right down
3083 						outData.push_back(tcu::Vec4( left, down, 0.0f, 1.0f));
3084 						outData.push_back(tcu::Vec4(right, down, 0.0f, 1.0f));
3085 						outData.push_back(tcu::Vec4(right,   up, 0.0f, 1.0f));
3086 					}
3087 				}
3088 			}
3089 
3090 			break;
3091 		}
3092 
3093 		default:
3094 			TCU_THROW(InternalError, "Unexpected iteration");
3095 	}
3096 
3097 	outTriangles.resize(outData.size() / 3);
3098 
3099 	for (size_t ndx = 0; ndx < outTriangles.size(); ++ndx)
3100 	{
3101 		outTriangles[ndx].positions[0] = outData[3 * ndx + 0];	outTriangles[ndx].sharedEdge[0] = false;
3102 		outTriangles[ndx].positions[1] = outData[3 * ndx + 1];	outTriangles[ndx].sharedEdge[1] = false;
3103 		outTriangles[ndx].positions[2] = outData[3 * ndx + 2];	outTriangles[ndx].sharedEdge[2] = false;
3104 	}
3105 
3106 	// log
3107 	if (isOverestimate)
3108 	{
3109 		m_context.getTestContext().getLog()
3110 			<< tcu::TestLog::Message
3111 			<< "Testing " << overestimateIterationComments[iteration] << " "
3112 			<< "with rendering " << outTriangles.size() << " triangle(s):"
3113 			<< tcu::TestLog::EndMessage;
3114 	}
3115 	else
3116 	{
3117 		m_context.getTestContext().getLog()
3118 			<< tcu::TestLog::Message
3119 			<< "Rendering " << outTriangles.size() << " triangle(s):"
3120 			<< tcu::TestLog::EndMessage;
3121 	}
3122 
3123 	for (int ndx = 0; ndx < (int)outTriangles.size(); ++ndx)
3124 	{
3125 		const deUint32	multiplierInt	= m_renderSize / 2;
3126 		const deUint32	multiplierFrac	= subPixels;
3127 		std::string		coordsString;
3128 
3129 		for (size_t vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
3130 		{
3131 			const tcu::Vec4&	pos				= outTriangles[ndx].positions[vertexNdx];
3132 			std::ostringstream	coordsFloat;
3133 			std::ostringstream	coordsNatural;
3134 
3135 			for (int coordNdx = 0; coordNdx < 2; ++coordNdx)
3136 			{
3137 				const char*	sep		= (coordNdx < 1) ? "," : "";
3138 				const float	coord	= pos[coordNdx];
3139 				const char	sign	= deSign(coord) < 0 ? '-' : '+';
3140 				const float	m		= deFloatFloor(float(multiplierInt) * deFloatAbs(coord));
3141 				const float	r		= deFloatFrac(float(multiplierInt) * deFloatAbs(coord)) * float(multiplierFrac);
3142 
3143 				coordsFloat << std::fixed << std::setw(13) << std::setprecision(10) << coord << sep;
3144 				coordsNatural << sign << '(' << m << '+' << r << '/' << multiplierFrac << ')' << sep;
3145 			}
3146 
3147 			coordsString += "\n\t[" + coordsFloat.str() + "] == [" + coordsNatural.str() + "] / " + de::toString(multiplierInt);
3148 		}
3149 
3150 		log << tcu::TestLog::Message
3151 			<< "Triangle " << (ndx + 1) << ':'
3152 			<< coordsString
3153 			<< tcu::TestLog::EndMessage;
3154 	}
3155 }
3156 
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & vertexData,VkPrimitiveTopology primitiveTopology)3157 void ConservativeTraingleTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology)
3158 {
3159 	if (m_conservativeTestConfig.degeneratePrimitives && getIteration() == 2)
3160 	{
3161 		// Set provoking vertex color to white
3162 		tcu::Vec4				colorProvoking	(1.0f, 1.0f, 1.0f, 1.0f);
3163 		tcu::Vec4				colorOther		(0.0f, 1.0f, 1.0f, 1.0f);
3164 		std::vector<tcu::Vec4>	colorData;
3165 
3166 		colorData.reserve(vertexData.size());
3167 
3168 		for (size_t vertexNdx = 0; vertexNdx < vertexData.size(); ++vertexNdx)
3169 			if (vertexNdx % 3 == 0)
3170 				colorData.push_back(colorProvoking);
3171 			else
3172 				colorData.push_back(colorOther);
3173 
3174 		BaseRenderingTestInstance::drawPrimitives(result, vertexData, colorData, primitiveTopology);
3175 	}
3176 	else
3177 		BaseRenderingTestInstance::drawPrimitives(result, vertexData, primitiveTopology);
3178 }
3179 
compareAndVerify(std::vector<TriangleSceneSpec::SceneTriangle> & triangles,tcu::Surface & resultImage,std::vector<tcu::Vec4> & drawBuffer)3180 bool ConservativeTraingleTestInstance::compareAndVerify (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage, std::vector<tcu::Vec4>& drawBuffer)
3181 {
3182 	DE_UNREF(drawBuffer);
3183 
3184 	switch (m_conservativeTestConfig.conservativeRasterizationMode)
3185 	{
3186 		case VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT:
3187 		{
3188 			if (m_conservativeTestConfig.degeneratePrimitives)
3189 				return compareAndVerifyOverestimatedDegenerate(triangles, resultImage);
3190 			else
3191 				return compareAndVerifyOverestimatedNormal(triangles, resultImage);
3192 		}
3193 
3194 		case VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT:
3195 		{
3196 			if (m_conservativeTestConfig.degeneratePrimitives)
3197 				return compareAndVerifyUnderestimatedDegenerate(triangles, resultImage);
3198 			else
3199 				return compareAndVerifyUnderestimatedNormal(triangles, resultImage);
3200 		}
3201 
3202 		default:
3203 			TCU_THROW(InternalError, "Unknown conservative rasterization mode");
3204 	}
3205 }
3206 
compareAndVerifyOverestimatedNormal(std::vector<TriangleSceneSpec::SceneTriangle> & triangles,tcu::Surface & resultImage)3207 bool ConservativeTraingleTestInstance::compareAndVerifyOverestimatedNormal (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage)
3208 {
3209 	DE_UNREF(triangles);
3210 
3211 	const int			start					= getIteration() + 1;
3212 	const int			end						= resultImage.getHeight() - start;
3213 	const tcu::RGBA		backgroundColor			= tcu::RGBA(0, 0, 0, 255);
3214 	const tcu::RGBA		foregroundColor			= tcu::RGBA(255, 255, 255, 255);
3215 	const tcu::RGBA		unexpectedPixelColor	= tcu::RGBA(255, 0, 0, 255);
3216 	tcu::TestLog&		log						= m_context.getTestContext().getLog();
3217 	int					errX					= 0;
3218 	int					errY					= 0;
3219 	deUint32			errValue				= 0;
3220 	bool				result					= true;
3221 
3222 	DE_ASSERT(resultImage.getHeight() == resultImage.getWidth());
3223 
3224 	for (int y = start; result && y < end; ++y)
3225 	for (int x = start; result && x < end; ++x)
3226 	{
3227 		if (resultImage.getPixel(x,y).getPacked() != foregroundColor.getPacked())
3228 		{
3229 			result		= false;
3230 			errX		= x;
3231 			errY		= y;
3232 			errValue	= resultImage.getPixel(x,y).getPacked();
3233 
3234 			break;
3235 		}
3236 	}
3237 
3238 	if (!result)
3239 	{
3240 		tcu::Surface	errorMask		(resultImage.getWidth(), resultImage.getHeight());
3241 		tcu::Surface	expectedImage	(resultImage.getWidth(), resultImage.getHeight());
3242 
3243 		for (int y = 0; y < errorMask.getHeight(); ++y)
3244 		for (int x = 0; x < errorMask.getWidth(); ++x)
3245 		{
3246 			errorMask.setPixel(x, y, backgroundColor);
3247 			expectedImage.setPixel(x, y, backgroundColor);
3248 		}
3249 
3250 		for (int y = start; y < end; ++y)
3251 		for (int x = start; x < end; ++x)
3252 		{
3253 			expectedImage.setPixel(x, y, foregroundColor);
3254 
3255 			if (resultImage.getPixel(x, y).getPacked() != foregroundColor.getPacked())
3256 				errorMask.setPixel(x, y, unexpectedPixelColor);
3257 		}
3258 
3259 		log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
3260 			<< tcu::TestLog::EndMessage;
3261 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3262 			<< tcu::TestLog::Image("Result",	"Result",		resultImage)
3263 			<< tcu::TestLog::Image("Expected",	"Expected",		expectedImage)
3264 			<< tcu::TestLog::Image("ErrorMask", "ErrorMask",	errorMask)
3265 			<< tcu::TestLog::EndImageSet;
3266 	}
3267 	else
3268 	{
3269 		log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
3270 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3271 			<< tcu::TestLog::Image("Result", "Result", resultImage)
3272 			<< tcu::TestLog::EndImageSet;
3273 	}
3274 
3275 	return result;
3276 }
3277 
compareAndVerifyOverestimatedDegenerate(std::vector<TriangleSceneSpec::SceneTriangle> & triangles,tcu::Surface & resultImage)3278 bool ConservativeTraingleTestInstance::compareAndVerifyOverestimatedDegenerate (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage)
3279 {
3280 	DE_UNREF(triangles);
3281 
3282 	const char*			iterationComments[]		= { "Cull back face triangles", "Cull front face triangles", "Cull none" };
3283 	const tcu::RGBA		backgroundColor			= tcu::RGBA(0, 0, 0, 255);
3284 	const tcu::RGBA		foregroundColor			= tcu::RGBA(255, 255, 255, 255);
3285 	const tcu::RGBA		unexpectedPixelColor	= tcu::RGBA(255, 0, 0, 255);
3286 	tcu::TestLog&		log						= m_context.getTestContext().getLog();
3287 	bool				result					= true;
3288 	tcu::Surface		referenceImage			(resultImage.getWidth(), resultImage.getHeight());
3289 
3290 	for (int y = 0; y < resultImage.getHeight(); ++y)
3291 	for (int x = 0; x < resultImage.getWidth(); ++x)
3292 		referenceImage.setPixel(x, y, backgroundColor);
3293 
3294 	if (m_conservativeRasterizationProperties.degenerateTrianglesRasterized)
3295 	{
3296 		if (getIteration() != 0)
3297 		{
3298 			log << tcu::TestLog::Message << "Triangles expected to be rasterized with at least one pixel of white color each" << tcu::TestLog::EndMessage;
3299 
3300 			for (int rowNdx = 0; rowNdx < 3; ++rowNdx)
3301 			for (int colNdx = 0; colNdx < 4; ++colNdx)
3302 			{
3303 				referenceImage.setPixel(4 * (colNdx + 1), 4 * (rowNdx + 1), foregroundColor);
3304 
3305 				// Allow implementations that need to be extra conservative with degenerate triangles,
3306 				// which may cause extra coverage.
3307 				if (resultImage.getPixel(4 * (colNdx + 1) - 1, 4 * (rowNdx + 1) - 1) == foregroundColor)
3308 					referenceImage.setPixel(4 * (colNdx + 1) - 1, 4 * (rowNdx + 1) - 1, foregroundColor);
3309 				if (resultImage.getPixel(4 * (colNdx + 1) - 1, 4 * (rowNdx + 1)) == foregroundColor)
3310 					referenceImage.setPixel(4 * (colNdx + 1) - 1, 4 * (rowNdx + 1), foregroundColor);
3311 				if (resultImage.getPixel(4 * (colNdx + 1), 4 * (rowNdx + 1) - 1) == foregroundColor)
3312 					referenceImage.setPixel(4 * (colNdx + 1), 4 * (rowNdx + 1) - 1, foregroundColor);
3313 			}
3314 		}
3315 		else
3316 			log << tcu::TestLog::Message << "Triangles expected to be culled due to backfacing culling and all degenerate triangles assumed to be backfacing" << tcu::TestLog::EndMessage;
3317 	}
3318 	else
3319 		log << tcu::TestLog::Message << "Triangles expected to be culled due to degenerateTrianglesRasterized=false" << tcu::TestLog::EndMessage;
3320 
3321 	for (int y = 0; result && y < resultImage.getHeight(); ++y)
3322 	for (int x = 0; result && x < resultImage.getWidth(); ++x)
3323 	{
3324 		if (resultImage.getPixel(x,y).getPacked() != referenceImage.getPixel(x,y).getPacked())
3325 		{
3326 			result = false;
3327 
3328 			break;
3329 		}
3330 	}
3331 
3332 	if (!result)
3333 	{
3334 		tcu::Surface	errorMask	(resultImage.getWidth(), resultImage.getHeight());
3335 
3336 		for (int y = 0; y < errorMask.getHeight(); ++y)
3337 		for (int x = 0; x < errorMask.getWidth(); ++x)
3338 		{
3339 			if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
3340 				errorMask.setPixel(x, y, unexpectedPixelColor);
3341 			else
3342 				errorMask.setPixel(x, y, backgroundColor);
3343 		}
3344 
3345 		log << tcu::TestLog::Message << "Invalid pixels found for mode '" << iterationComments[getIteration()] << "'"
3346 			<< tcu::TestLog::EndMessage;
3347 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3348 			<< tcu::TestLog::Image("Result",	"Result",		resultImage)
3349 			<< tcu::TestLog::Image("Reference",	"Reference",	referenceImage)
3350 			<< tcu::TestLog::Image("ErrorMask", "ErrorMask",	errorMask)
3351 			<< tcu::TestLog::EndImageSet;
3352 	}
3353 	else
3354 	{
3355 		log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
3356 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3357 			<< tcu::TestLog::Image("Result", "Result", resultImage)
3358 			<< tcu::TestLog::EndImageSet;
3359 	}
3360 
3361 	return result;
3362 }
3363 
compareAndVerifyUnderestimatedNormal(std::vector<TriangleSceneSpec::SceneTriangle> & triangles,tcu::Surface & resultImage)3364 bool ConservativeTraingleTestInstance::compareAndVerifyUnderestimatedNormal (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage)
3365 {
3366 	DE_UNREF(triangles);
3367 
3368 	const tcu::RGBA		backgroundColor			= tcu::RGBA(0, 0, 0, 255);
3369 	const tcu::RGBA		foregroundColor			= tcu::RGBA(255, 255, 255, 255);
3370 	const tcu::RGBA		unexpectedPixelColor	= tcu::RGBA(255, 0, 0, 255);
3371 	const tcu::IVec2	viewportSize			= tcu::IVec2(resultImage.getWidth(), resultImage.getHeight());
3372 	tcu::TestLog&		log						= m_context.getTestContext().getLog();
3373 	int					errX					= -1;
3374 	int					errY					= -1;
3375 	deUint32			errValue				= 0;
3376 	tcu::Surface		referenceImage			(resultImage.getWidth(), resultImage.getHeight());
3377 	bool				result					= true;
3378 
3379 	DE_ASSERT(resultImage.getHeight() == resultImage.getWidth());
3380 
3381 	for (int y = 0; y < resultImage.getHeight(); ++y)
3382 	for (int x = 0; x < resultImage.getWidth(); ++x)
3383 		referenceImage.setPixel(x, y, backgroundColor);
3384 
3385 	for (size_t triangleNdx = 0; triangleNdx < triangles.size(); ++triangleNdx)
3386 	{
3387 		const tcu::Vec4&	p0	= triangles[triangleNdx].positions[0];
3388 		const tcu::Vec4&	p1	= triangles[triangleNdx].positions[1];
3389 		const tcu::Vec4&	p2	= triangles[triangleNdx].positions[2];
3390 
3391 		for (int y = 0; y < resultImage.getHeight(); ++y)
3392 		for (int x = 0; x < resultImage.getWidth(); ++x)
3393 		{
3394 			if (calculateUnderestimateTriangleCoverage(p0, p1, p2, tcu::IVec2(x,y), m_subpixelBits, viewportSize) == tcu::COVERAGE_FULL)
3395 				referenceImage.setPixel(x, y, foregroundColor);
3396 		}
3397 	}
3398 
3399 	for (int y = 0; result && y < resultImage.getHeight(); ++y)
3400 	for (int x = 0; result && x < resultImage.getWidth(); ++x)
3401 		if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
3402 		{
3403 			result		= false;
3404 			errX		= x;
3405 			errY		= y;
3406 			errValue	= resultImage.getPixel(x,y).getPacked();
3407 		}
3408 
3409 	if (!result)
3410 	{
3411 		tcu::Surface	errorMask	(resultImage.getWidth(), resultImage.getHeight());
3412 
3413 		for (int y = 0; y < errorMask.getHeight(); ++y)
3414 		for (int x = 0; x < errorMask.getWidth(); ++x)
3415 		{
3416 			if (resultImage.getPixel(x,y).getPacked() != referenceImage.getPixel(x,y).getPacked())
3417 				errorMask.setPixel(x, y, unexpectedPixelColor);
3418 			else
3419 				errorMask.setPixel(x, y, backgroundColor);
3420 		}
3421 
3422 		log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
3423 			<< tcu::TestLog::EndMessage;
3424 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3425 			<< tcu::TestLog::Image("Result",	"Result",		resultImage)
3426 			<< tcu::TestLog::Image("Refernce",	"Refernce",		referenceImage)
3427 			<< tcu::TestLog::Image("ErrorMask", "ErrorMask",	errorMask)
3428 			<< tcu::TestLog::EndImageSet;
3429 	}
3430 	else
3431 	{
3432 		log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
3433 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3434 			<< tcu::TestLog::Image("Result", "Result", resultImage)
3435 			<< tcu::TestLog::EndImageSet;
3436 	}
3437 
3438 	return result;
3439 }
3440 
compareAndVerifyUnderestimatedDegenerate(std::vector<TriangleSceneSpec::SceneTriangle> & triangles,tcu::Surface & resultImage)3441 bool ConservativeTraingleTestInstance::compareAndVerifyUnderestimatedDegenerate (std::vector<TriangleSceneSpec::SceneTriangle>& triangles, tcu::Surface& resultImage)
3442 {
3443 	DE_UNREF(triangles);
3444 
3445 	const char*			iterationComments[]		= { "Cull back face triangles", "Cull front face triangles", "Cull none" };
3446 	const tcu::RGBA		backgroundColor			= tcu::RGBA(0, 0, 0, 255);
3447 	const tcu::RGBA		unexpectedPixelColor	= tcu::RGBA(255, 0, 0, 255);
3448 	tcu::TestLog&		log						= m_context.getTestContext().getLog();
3449 	int					errX					= 0;
3450 	int					errY					= 0;
3451 	deUint32			errValue				= 0;
3452 	bool				result					= true;
3453 
3454 	if (m_conservativeRasterizationProperties.degenerateTrianglesRasterized)
3455 	{
3456 		if (getIteration() != 0)
3457 			log << tcu::TestLog::Message << "Triangles expected to be not rendered due to no one triangle can fully cover fragment" << tcu::TestLog::EndMessage;
3458 		else
3459 			log << tcu::TestLog::Message << "Triangles expected to be culled due to backfacing culling and all degenerate triangles assumed to be backfacing" << tcu::TestLog::EndMessage;
3460 	}
3461 	else
3462 		log << tcu::TestLog::Message << "Triangles expected to be culled due to degenerateTrianglesRasterized=false" << tcu::TestLog::EndMessage;
3463 
3464 	for (int y = 0; result && y < resultImage.getHeight(); ++y)
3465 	for (int x = 0; result && x < resultImage.getWidth(); ++x)
3466 	{
3467 		if (resultImage.getPixel(x, y).getPacked() != backgroundColor.getPacked())
3468 		{
3469 			result		= false;
3470 			errX		= x;
3471 			errY		= y;
3472 			errValue	= resultImage.getPixel(x,y).getPacked();
3473 
3474 			break;
3475 		}
3476 	}
3477 
3478 	if (!result)
3479 	{
3480 		tcu::Surface	referenceImage	(resultImage.getWidth(), resultImage.getHeight());
3481 		tcu::Surface	errorMask		(resultImage.getWidth(), resultImage.getHeight());
3482 
3483 		for (int y = 0; y < resultImage.getHeight(); ++y)
3484 		for (int x = 0; x < resultImage.getWidth(); ++x)
3485 			referenceImage.setPixel(x, y, backgroundColor);
3486 
3487 		for (int y = 0; y < errorMask.getHeight(); ++y)
3488 		for (int x = 0; x < errorMask.getWidth(); ++x)
3489 		{
3490 			if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
3491 				errorMask.setPixel(x, y, unexpectedPixelColor);
3492 			else
3493 				errorMask.setPixel(x, y, backgroundColor);
3494 		}
3495 
3496 		log << tcu::TestLog::Message << "Invalid pixels found for mode '" << iterationComments[getIteration()] << "' starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
3497 			<< tcu::TestLog::EndMessage;
3498 
3499 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3500 			<< tcu::TestLog::Image("Result",	"Result",		resultImage)
3501 			<< tcu::TestLog::Image("Reference",	"Reference",	referenceImage)
3502 			<< tcu::TestLog::Image("ErrorMask", "ErrorMask",	errorMask)
3503 			<< tcu::TestLog::EndImageSet;
3504 	}
3505 	else
3506 	{
3507 		log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
3508 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
3509 			<< tcu::TestLog::Image("Result", "Result", resultImage)
3510 			<< tcu::TestLog::EndImageSet;
3511 	}
3512 
3513 	return result;
3514 }
3515 
initRasterizationConservativeStateCreateInfo(void)3516 const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT> ConservativeTraingleTestInstance::initRasterizationConservativeStateCreateInfo (void)
3517 {
3518 	const float															extraOverestimationSize	= getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
3519 	std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>	result;
3520 
3521 	result.reserve(getIterationCount());
3522 
3523 	for (int iteration = 0; iteration < getIterationCount(); ++iteration)
3524 	{
3525 		const VkPipelineRasterizationConservativeStateCreateInfoEXT	rasterizationConservativeStateCreateInfo	=
3526 		{
3527 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,	//  VkStructureType											sType;
3528 			DE_NULL,																		//  const void*												pNext;
3529 			(VkPipelineRasterizationConservativeStateCreateFlagsEXT)0,						//  VkPipelineRasterizationConservativeStateCreateFlagsEXT	flags;
3530 			m_conservativeTestConfig.conservativeRasterizationMode,							//  VkConservativeRasterizationModeEXT						conservativeRasterizationMode;
3531 			extraOverestimationSize															//  float													extraPrimitiveOverestimationSize;
3532 		};
3533 
3534 		result.push_back(rasterizationConservativeStateCreateInfo);
3535 	}
3536 
3537 	return result;
3538 }
3539 
initRasterizationStateCreateInfo(void)3540 const std::vector<VkPipelineRasterizationStateCreateInfo> ConservativeTraingleTestInstance::initRasterizationStateCreateInfo (void)
3541 {
3542 	std::vector<VkPipelineRasterizationStateCreateInfo>	result;
3543 
3544 	result.reserve(getIterationCount());
3545 
3546 	for (int iteration = 0; iteration < getIterationCount(); ++iteration)
3547 	{
3548 		const VkCullModeFlags							cullModeFlags					= (!m_conservativeTestConfig.degeneratePrimitives) ? VK_CULL_MODE_NONE
3549 																						: (iteration == 0) ? VK_CULL_MODE_BACK_BIT
3550 																						: (iteration == 1) ? VK_CULL_MODE_FRONT_BIT
3551 																						: VK_CULL_MODE_NONE;
3552 
3553 		const VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
3554 		{
3555 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		//  VkStructureType							sType;
3556 			&m_rasterizationConservativeStateCreateInfo[iteration],			//  const void*								pNext;
3557 			0,																//  VkPipelineRasterizationStateCreateFlags	flags;
3558 			false,															//  VkBool32								depthClampEnable;
3559 			false,															//  VkBool32								rasterizerDiscardEnable;
3560 			VK_POLYGON_MODE_FILL,											//  VkPolygonMode							polygonMode;
3561 			cullModeFlags,													//  VkCullModeFlags							cullMode;
3562 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								//  VkFrontFace								frontFace;
3563 			VK_FALSE,														//  VkBool32								depthBiasEnable;
3564 			0.0f,															//  float									depthBiasConstantFactor;
3565 			0.0f,															//  float									depthBiasClamp;
3566 			0.0f,															//  float									depthBiasSlopeFactor;
3567 			getLineWidth(),													//  float									lineWidth;
3568 		};
3569 
3570 		result.push_back(rasterizationStateCreateInfo);
3571 	}
3572 
3573 	return result;
3574 }
3575 
getRasterizationStateCreateInfo(void) const3576 const VkPipelineRasterizationStateCreateInfo* ConservativeTraingleTestInstance::getRasterizationStateCreateInfo	(void) const
3577 {
3578 	return &m_rasterizationStateCreateInfo[getIteration()];
3579 }
3580 
getLineRasterizationStateCreateInfo(void)3581 const VkPipelineRasterizationLineStateCreateInfoEXT* ConservativeTraingleTestInstance::getLineRasterizationStateCreateInfo	(void)
3582 {
3583 	return DE_NULL;
3584 }
3585 
3586 
3587 class ConservativeLineTestInstance : public BaseLineTestInstance
3588 {
3589 public:
3590 																				ConservativeLineTestInstance					(Context&								context,
3591 																																 ConservativeTestConfig					conservativeTestConfig,
3592 																																 VkSampleCountFlagBits					sampleCount);
3593 
3594 	void																		generateLines									(int									iteration,
3595 																																 std::vector<tcu::Vec4>&				outData,
3596 																																 std::vector<LineSceneSpec::SceneLine>&	outLines);
3597 	const VkPipelineRasterizationStateCreateInfo*								getRasterizationStateCreateInfo					(void) const;
3598 
3599 protected:
3600 	virtual const VkPipelineRasterizationLineStateCreateInfoEXT*				getLineRasterizationStateCreateInfo				(void);
3601 
3602 	virtual bool																compareAndVerify								(std::vector<LineSceneSpec::SceneLine>&	lines,
3603 																																 tcu::Surface&							resultImage,
3604 																																 std::vector<tcu::Vec4>&				drawBuffer);
3605 	virtual bool																compareAndVerifyOverestimatedNormal				(std::vector<LineSceneSpec::SceneLine>&	lines,
3606 																																 tcu::Surface&							resultImage);
3607 	virtual bool																compareAndVerifyOverestimatedDegenerate			(std::vector<LineSceneSpec::SceneLine>&	lines,
3608 																																 tcu::Surface&							resultImage);
3609 	virtual bool																compareAndVerifyUnderestimatedNormal			(std::vector<LineSceneSpec::SceneLine>&	lines,
3610 																																 tcu::Surface&							resultImage);
3611 	virtual bool																compareAndVerifyUnderestimatedDegenerate		(std::vector<LineSceneSpec::SceneLine>&	lines,
3612 																																 tcu::Surface&							resultImage);
3613 	void																		generateNormalLines								(int									iteration,
3614 																																 std::vector<tcu::Vec4>&				outData,
3615 																																 std::vector<LineSceneSpec::SceneLine>&	outLines);
3616 	void																		generateDegenerateLines							(int									iteration,
3617 																																 std::vector<tcu::Vec4>&				outData,
3618 																																 std::vector<LineSceneSpec::SceneLine>&	outLines);
3619 	void																		drawPrimitives									(tcu::Surface&							result,
3620 																																 const std::vector<tcu::Vec4>&			vertexData,
3621 																																 VkPrimitiveTopology					primitiveTopology);
3622 
3623 private:
3624 	const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>	initRasterizationConservativeStateCreateInfo	(void);
3625 	const std::vector<VkPipelineRasterizationStateCreateInfo>					initRasterizationStateCreateInfo				(void);
3626 
3627 	const ConservativeTestConfig												m_conservativeTestConfig;
3628 	const VkPhysicalDeviceConservativeRasterizationPropertiesEXT				m_conservativeRasterizationProperties;
3629 	const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>	m_rasterizationConservativeStateCreateInfo;
3630 	const std::vector<VkPipelineRasterizationStateCreateInfo>					m_rasterizationStateCreateInfo;
3631 };
3632 
ConservativeLineTestInstance(Context & context,ConservativeTestConfig conservativeTestConfig,VkSampleCountFlagBits sampleCount)3633 ConservativeLineTestInstance::ConservativeLineTestInstance (Context&				context,
3634 															ConservativeTestConfig	conservativeTestConfig,
3635 															VkSampleCountFlagBits	sampleCount)
3636 	: BaseLineTestInstance							(
3637 														context,
3638 														conservativeTestConfig.primitiveTopology,
3639 														PRIMITIVEWIDENESS_NARROW,
3640 														PRIMITIVESTRICTNESS_IGNORE,
3641 														sampleCount,
3642 														LINESTIPPLE_DISABLED,
3643 														VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT,
3644 														LineStippleFactorCase::DEFAULT,
3645 														0,
3646 														conservativeTestConfig.resolution,
3647 														conservativeTestConfig.lineWidth
3648 													)
3649 	, m_conservativeTestConfig						(conservativeTestConfig)
3650 	, m_conservativeRasterizationProperties			(context.getConservativeRasterizationPropertiesEXT())
3651 	, m_rasterizationConservativeStateCreateInfo	(initRasterizationConservativeStateCreateInfo())
3652 	, m_rasterizationStateCreateInfo				(initRasterizationStateCreateInfo())
3653 {
3654 }
3655 
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)3656 void ConservativeLineTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
3657 {
3658 	if (m_conservativeTestConfig.degeneratePrimitives)
3659 		generateDegenerateLines(iteration, outData, outLines);
3660 	else
3661 		generateNormalLines(iteration, outData, outLines);
3662 }
3663 
generateNormalLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)3664 void ConservativeLineTestInstance::generateNormalLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
3665 {
3666 	const char*		iterationComment		= "";
3667 	const float		halfPixel				= 1.0f / float(m_renderSize);
3668 	const float		extraOverestimationSize	= getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
3669 	const float		overestimate			= 2.0f * halfPixel * (m_conservativeRasterizationProperties.primitiveOverestimationSize + extraOverestimationSize);
3670 	const float		overestimateMargin		= overestimate;
3671 	const float		underestimateMargin		= 0.0f;
3672 	const bool		isOverestimate			= m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
3673 	const float		margin					= isOverestimate ? overestimateMargin : underestimateMargin;
3674 	const float		edge					= 4 * halfPixel + margin;
3675 	const float		left					= -1.0f + edge;
3676 	const float		right					= +1.0f - edge;
3677 	const float		up						= -1.0f + edge;
3678 	const float		down					= +1.0f - edge;
3679 
3680 	outData.reserve(2);
3681 
3682 	if (isOverestimate)
3683 	{
3684 		const char*		iterationComments[]		= { "Horizontal up line", "Vertical line", "Horizontal down line" };
3685 
3686 		iterationComment = iterationComments[iteration];
3687 
3688 		switch (iteration)
3689 		{
3690 			case 0:
3691 			{
3692 				outData.push_back(tcu::Vec4(              left,   up + halfPixel, 0.0f, 1.0f));
3693 				outData.push_back(tcu::Vec4(             right,   up + halfPixel, 0.0f, 1.0f));
3694 
3695 				break;
3696 			}
3697 
3698 			case 1:
3699 			{
3700 				outData.push_back(tcu::Vec4(  left + halfPixel,               up, 0.0f, 1.0f));
3701 				outData.push_back(tcu::Vec4(  left + halfPixel,             down, 0.0f, 1.0f));
3702 
3703 				break;
3704 			}
3705 
3706 			case 2:
3707 			{
3708 				outData.push_back(tcu::Vec4(              left, down - halfPixel, 0.0f, 1.0f));
3709 				outData.push_back(tcu::Vec4(             right, down - halfPixel, 0.0f, 1.0f));
3710 
3711 				break;
3712 			}
3713 
3714 			default:
3715 				TCU_THROW(InternalError, "Unexpected iteration");
3716 		}
3717 	}
3718 	else
3719 	{
3720 		const char*		iterationComments[]	= { "Horizontal lines", "Vertical lines", "Diagonal lines" };
3721 		const deUint32	subPixels			= 1u << m_subpixelBits;
3722 		const float		subPixelSize		= 2.0f * halfPixel / float(subPixels);
3723 		const float		blockStep			= 16.0f * 2.0f * halfPixel;
3724 		const float		lineWidth			= 2.0f * halfPixel * getLineWidth();
3725 		const float		offsets[]			=
3726 		{
3727 			float(1) * blockStep,
3728 			float(2) * blockStep + halfPixel,
3729 			float(3) * blockStep + 0.5f * lineWidth + 2.0f * subPixelSize,
3730 			float(4) * blockStep + 0.5f * lineWidth - 2.0f * subPixelSize,
3731 		};
3732 
3733 		iterationComment = iterationComments[iteration];
3734 
3735 		outData.reserve(DE_LENGTH_OF_ARRAY(offsets));
3736 
3737 		switch (iteration)
3738 		{
3739 			case 0:
3740 			{
3741 				for (size_t lineNdx = 0; lineNdx < DE_LENGTH_OF_ARRAY(offsets); ++lineNdx)
3742 				{
3743 					outData.push_back(tcu::Vec4( left + halfPixel, up + offsets[lineNdx], 0.0f, 1.0f));
3744 					outData.push_back(tcu::Vec4(right - halfPixel, up + offsets[lineNdx], 0.0f, 1.0f));
3745 				}
3746 
3747 				break;
3748 			}
3749 
3750 			case 1:
3751 			{
3752 				for (size_t lineNdx = 0; lineNdx < DE_LENGTH_OF_ARRAY(offsets); ++lineNdx)
3753 				{
3754 					outData.push_back(tcu::Vec4(left + offsets[lineNdx],   up + halfPixel, 0.0f, 1.0f));
3755 					outData.push_back(tcu::Vec4(left + offsets[lineNdx], down - halfPixel, 0.0f, 1.0f));
3756 				}
3757 
3758 				break;
3759 			}
3760 
3761 			case 2:
3762 			{
3763 				for (size_t lineNdx = 0; lineNdx < DE_LENGTH_OF_ARRAY(offsets); ++lineNdx)
3764 				{
3765 					outData.push_back(tcu::Vec4(left + offsets[lineNdx],          up + halfPixel, 0.0f, 1.0f));
3766 					outData.push_back(tcu::Vec4(      right - halfPixel, down - offsets[lineNdx], 0.0f, 1.0f));
3767 				}
3768 
3769 				break;
3770 			}
3771 
3772 			default:
3773 				TCU_THROW(InternalError, "Unexpected iteration");
3774 		}
3775 	}
3776 
3777 	DE_ASSERT(outData.size() % 2 == 0);
3778 	outLines.resize(outData.size() / 2);
3779 	for(size_t lineNdx = 0; lineNdx < outLines.size(); ++lineNdx)
3780 	{
3781 		outLines[lineNdx].positions[0] = outData[2 * lineNdx + 0];
3782 		outLines[lineNdx].positions[1] = outData[2 * lineNdx + 1];
3783 	}
3784 
3785 	// log
3786 	m_context.getTestContext().getLog()
3787 		<< tcu::TestLog::Message
3788 		<< "Testing " << iterationComment << " "
3789 		<< "with rendering " << outLines.size() << " line(s):"
3790 		<< tcu::TestLog::EndMessage;
3791 
3792 	for (int ndx = 0; ndx < (int)outLines.size(); ++ndx)
3793 	{
3794 		const deUint32	 multiplier	= m_renderSize / 2;
3795 
3796 		m_context.getTestContext().getLog()
3797 			<< tcu::TestLog::Message
3798 			<< "Line " << (ndx+1) << ":"
3799 			<< "\n\t" << outLines[ndx].positions[0] << " == " << (float(multiplier) * outLines[ndx].positions[0]) << "/" << multiplier
3800 			<< "\n\t" << outLines[ndx].positions[1] << " == " << (float(multiplier) * outLines[ndx].positions[1]) << "/" << multiplier
3801 			<< tcu::TestLog::EndMessage;
3802 	}
3803 }
3804 
generateDegenerateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)3805 void ConservativeLineTestInstance::generateDegenerateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
3806 {
3807 	const bool		isOverestimate		= m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
3808 	const float		pixelSize			= 2.0f / float(m_renderSize);
3809 	const deUint32	subPixels			= 1u << m_context.getDeviceProperties().limits.subPixelPrecisionBits;
3810 	const float		subPixelSize		= pixelSize / float(subPixels);
3811 	const char*		iterationComments[]	= { "Horizontal line", "Vertical line", "Diagonal line" };
3812 
3813 	outData.clear();
3814 
3815 	if (isOverestimate)
3816 	{
3817 		const float		extraOverestimationSize			= getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
3818 		const float		totalOverestimate				= m_conservativeRasterizationProperties.primitiveOverestimationSize + extraOverestimationSize;
3819 		const float		totalOverestimateInSubPixels	= deFloatCeil(totalOverestimate * float(subPixels));
3820 		const float		overestimate					= subPixelSize * totalOverestimateInSubPixels;
3821 		const float		overestimateSafetyMargin		= subPixelSize * 0.125f;
3822 		const float		margin							= overestimate + overestimateSafetyMargin;
3823 		const float		originOffset					= -1.0f + 1 * pixelSize;
3824 		const float		originLeft						= originOffset + margin;
3825 		const float		originRight						= originOffset + margin + 0.25f * subPixelSize;
3826 		const float		originUp						= originOffset + margin;
3827 		const float		originDown						= originOffset + margin + 0.25f * subPixelSize;
3828 
3829 		switch (iteration)
3830 		{
3831 			case 0:
3832 			{
3833 				outData.push_back(tcu::Vec4( originLeft,   originUp, 0.0f, 1.0f));
3834 				outData.push_back(tcu::Vec4(originRight,   originUp, 0.0f, 1.0f));
3835 
3836 				break;
3837 			}
3838 
3839 			case 1:
3840 			{
3841 				outData.push_back(tcu::Vec4( originLeft,   originUp, 0.0f, 1.0f));
3842 				outData.push_back(tcu::Vec4( originLeft, originDown, 0.0f, 1.0f));
3843 
3844 				break;
3845 			}
3846 
3847 			case 2:
3848 			{
3849 				outData.push_back(tcu::Vec4( originLeft,   originUp, 0.0f, 1.0f));
3850 				outData.push_back(tcu::Vec4(originRight, originDown, 0.0f, 1.0f));
3851 
3852 				break;
3853 			}
3854 
3855 			default:
3856 				TCU_THROW(InternalError, "Unexpected iteration");
3857 		}
3858 	}
3859 	else
3860 	{
3861 		size_t rowStart	= 3 * getIteration();
3862 		size_t rowEnd	= 3 * (getIteration() + 1);
3863 
3864 		for (size_t rowNdx = rowStart; rowNdx < rowEnd; ++rowNdx)
3865 		for (size_t colNdx = 0; colNdx < 3 * 3; ++colNdx)
3866 		{
3867 			const float		originOffsetY	= -1.0f + float(4 * (1 + rowNdx)) * pixelSize;
3868 			const float		originOffsetX	= -1.0f + float(4 * (1 + colNdx)) * pixelSize;
3869 			const float		x0				= float(rowNdx % 3);
3870 			const float		y0				= float(rowNdx / 3);
3871 			const float		x1				= float(colNdx % 3);
3872 			const float		y1				= float(colNdx / 3);
3873 			const tcu::Vec4	p0				= tcu::Vec4(originOffsetX + x0 * pixelSize / 2.0f, originOffsetY + y0 * pixelSize / 2.0f, 0.0f, 1.0f);
3874 			const tcu::Vec4	p1				= tcu::Vec4(originOffsetX + x1 * pixelSize / 2.0f, originOffsetY + y1 * pixelSize / 2.0f, 0.0f, 1.0f);
3875 
3876 			if (x0 == x1 && y0 == y1)
3877 				continue;
3878 
3879 			outData.push_back(p0);
3880 			outData.push_back(p1);
3881 		}
3882 	}
3883 
3884 	outLines.resize(outData.size() / 2);
3885 
3886 	for (size_t ndx = 0; ndx < outLines.size(); ++ndx)
3887 	{
3888 		outLines[ndx].positions[0] = outData[2 * ndx + 0];
3889 		outLines[ndx].positions[1] = outData[2 * ndx + 1];
3890 	}
3891 
3892 	// log
3893 	m_context.getTestContext().getLog()
3894 		<< tcu::TestLog::Message
3895 		<< "Testing " << iterationComments[iteration] << " "
3896 		<< "with rendering " << outLines.size() << " line(s):"
3897 		<< tcu::TestLog::EndMessage;
3898 
3899 	for (int ndx = 0; ndx < (int)outLines.size(); ++ndx)
3900 	{
3901 		const deUint32	multiplierInt	= m_renderSize / 2;
3902 		const deUint32	multiplierFrac	= subPixels;
3903 		std::string		coordsString;
3904 
3905 		for (size_t vertexNdx = 0; vertexNdx < 2; ++vertexNdx)
3906 		{
3907 			const tcu::Vec4&	pos				= outLines[ndx].positions[vertexNdx];
3908 			std::ostringstream	coordsFloat;
3909 			std::ostringstream	coordsNatural;
3910 
3911 			for (int coordNdx = 0; coordNdx < 2; ++coordNdx)
3912 			{
3913 				const char*	sep		= (coordNdx < 1) ? "," : "";
3914 				const float	coord	= pos[coordNdx];
3915 				const char	sign	= deSign(coord) < 0 ? '-' : '+';
3916 				const float	m		= deFloatFloor(float(multiplierInt) * deFloatAbs(coord));
3917 				const float	r		= deFloatFrac(float(multiplierInt) * deFloatAbs(coord)) * float(multiplierFrac);
3918 
3919 				coordsFloat << std::fixed << std::setw(13) << std::setprecision(10) << coord << sep;
3920 				coordsNatural << sign << '(' << m << '+' << r << '/' << multiplierFrac << ')' << sep;
3921 			}
3922 
3923 			coordsString += "\n\t[" + coordsFloat.str() + "] == [" + coordsNatural.str() + "] / " + de::toString(multiplierInt);
3924 		}
3925 
3926 		m_context.getTestContext().getLog()
3927 			<< tcu::TestLog::Message
3928 			<< "Line " << (ndx + 1) << ':'
3929 			<< coordsString
3930 			<< tcu::TestLog::EndMessage;
3931 	}
3932 }
3933 
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & vertexData,VkPrimitiveTopology primitiveTopology)3934 void ConservativeLineTestInstance::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, VkPrimitiveTopology primitiveTopology)
3935 {
3936 	if (m_conservativeTestConfig.degeneratePrimitives)
3937 	{
3938 		// Set provoking vertex color to white
3939 		tcu::Vec4				colorProvoking	(1.0f, 1.0f, 1.0f, 1.0f);
3940 		tcu::Vec4				colorOther		(0.0f, 1.0f, 1.0f, 1.0f);
3941 		std::vector<tcu::Vec4>	colorData;
3942 
3943 		colorData.reserve(vertexData.size());
3944 
3945 		for (size_t vertexNdx = 0; vertexNdx < vertexData.size(); ++vertexNdx)
3946 			if (vertexNdx % 2 == 0)
3947 				colorData.push_back(colorProvoking);
3948 			else
3949 				colorData.push_back(colorOther);
3950 
3951 		BaseRenderingTestInstance::drawPrimitives(result, vertexData, colorData, primitiveTopology);
3952 	}
3953 	else
3954 		BaseRenderingTestInstance::drawPrimitives(result, vertexData, primitiveTopology);
3955 }
3956 
compareAndVerify(std::vector<LineSceneSpec::SceneLine> & lines,tcu::Surface & resultImage,std::vector<tcu::Vec4> & drawBuffer)3957 bool ConservativeLineTestInstance::compareAndVerify (std::vector<LineSceneSpec::SceneLine>& lines, tcu::Surface& resultImage, std::vector<tcu::Vec4>& drawBuffer)
3958 {
3959 	DE_UNREF(drawBuffer);
3960 
3961 	switch (m_conservativeTestConfig.conservativeRasterizationMode)
3962 	{
3963 		case VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT:
3964 		{
3965 			if (m_conservativeTestConfig.degeneratePrimitives)
3966 				return compareAndVerifyOverestimatedDegenerate(lines, resultImage);
3967 			else
3968 				return compareAndVerifyOverestimatedNormal(lines, resultImage);
3969 		}
3970 		case VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT:
3971 		{
3972 			if (m_conservativeTestConfig.degeneratePrimitives)
3973 				return compareAndVerifyUnderestimatedDegenerate(lines, resultImage);
3974 			else
3975 				return compareAndVerifyUnderestimatedNormal(lines, resultImage);
3976 		}
3977 
3978 		default:
3979 			TCU_THROW(InternalError, "Unknown conservative rasterization mode");
3980 	}
3981 }
3982 
compareAndVerifyOverestimatedNormal(std::vector<LineSceneSpec::SceneLine> & lines,tcu::Surface & resultImage)3983 bool ConservativeLineTestInstance::compareAndVerifyOverestimatedNormal (std::vector<LineSceneSpec::SceneLine>& lines, tcu::Surface& resultImage)
3984 {
3985 	DE_UNREF(lines);
3986 
3987 	const int			b						= 3; // bar width
3988 	const int			w						= resultImage.getWidth() - 1;
3989 	const int			h						= resultImage.getHeight() - 1;
3990 	const int			xStarts[]				= {     1,     1,     1 };
3991 	const int			xEnds[]					= { w - 1,     b, w - 1 };
3992 	const int			yStarts[]				= {     1,     1, h - b };
3993 	const int			yEnds[]					= {     b, h - 1, h - 1 };
3994 	const int			xStart					= xStarts[getIteration()];
3995 	const int			xEnd					= xEnds[getIteration()];
3996 	const int			yStart					= yStarts[getIteration()];
3997 	const int			yEnd					= yEnds[getIteration()];
3998 	const tcu::RGBA		backgroundColor			= tcu::RGBA(0, 0, 0, 255);
3999 	const tcu::RGBA		foregroundColor			= tcu::RGBA(255, 255, 255, 255);
4000 	const tcu::RGBA		unexpectedPixelColor	= tcu::RGBA(255, 0, 0, 255);
4001 	tcu::TestLog&		log						= m_context.getTestContext().getLog();
4002 	int					errX					= 0;
4003 	int					errY					= 0;
4004 	deUint32			errValue				= 0;
4005 	bool				result					= true;
4006 
4007 	DE_ASSERT(resultImage.getHeight() == resultImage.getWidth());
4008 
4009 	for (int y = yStart; result && y < yEnd; ++y)
4010 	for (int x = xStart; result && x < xEnd; ++x)
4011 	{
4012 		if (resultImage.getPixel(x,y).getPacked() != foregroundColor.getPacked())
4013 		{
4014 			result		= false;
4015 			errX		= x;
4016 			errY		= y;
4017 			errValue	= resultImage.getPixel(x,y).getPacked();
4018 
4019 			break;
4020 		}
4021 	}
4022 
4023 	if (!result)
4024 	{
4025 		tcu::Surface	errorMask	(resultImage.getWidth(), resultImage.getHeight());
4026 
4027 		for (int y = 0; y < errorMask.getHeight(); ++y)
4028 		for (int x = 0; x < errorMask.getWidth(); ++x)
4029 			errorMask.setPixel(x, y, backgroundColor);
4030 
4031 		for (int y = yStart; y < yEnd; ++y)
4032 		for (int x = xStart; x < xEnd; ++x)
4033 		{
4034 			if (resultImage.getPixel(x,y).getPacked() != foregroundColor.getPacked())
4035 				errorMask.setPixel(x,y, unexpectedPixelColor);
4036 		}
4037 
4038 		log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
4039 			<< tcu::TestLog::EndMessage;
4040 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4041 			<< tcu::TestLog::Image("Result",	"Result",		resultImage)
4042 			<< tcu::TestLog::Image("ErrorMask", "ErrorMask",	errorMask)
4043 			<< tcu::TestLog::EndImageSet;
4044 	}
4045 	else
4046 	{
4047 		log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
4048 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4049 			<< tcu::TestLog::Image("Result", "Result", resultImage)
4050 			<< tcu::TestLog::EndImageSet;
4051 	}
4052 
4053 	return result;
4054 }
4055 
compareAndVerifyOverestimatedDegenerate(std::vector<LineSceneSpec::SceneLine> & lines,tcu::Surface & resultImage)4056 bool ConservativeLineTestInstance::compareAndVerifyOverestimatedDegenerate (std::vector<LineSceneSpec::SceneLine>& lines, tcu::Surface& resultImage)
4057 {
4058 	DE_UNREF(lines);
4059 
4060 	const char*			iterationComments[]		= { "Horizontal line", "Vertical line", "Diagonal line" };
4061 	const tcu::RGBA		backgroundColor			= tcu::RGBA(0, 0, 0, 255);
4062 	const tcu::RGBA		foregroundColor			= tcu::RGBA(255, 255, 255, 255);
4063 	const tcu::RGBA		unexpectedPixelColor	= tcu::RGBA(255, 0, 0, 255);
4064 	tcu::TestLog&		log						= m_context.getTestContext().getLog();
4065 	bool				result					= true;
4066 	tcu::Surface		referenceImage			(resultImage.getWidth(), resultImage.getHeight());
4067 
4068 	for (int y = 0; y < resultImage.getHeight(); ++y)
4069 	for (int x = 0; x < resultImage.getWidth(); ++x)
4070 		referenceImage.setPixel(x, y, backgroundColor);
4071 
4072 	if (m_conservativeRasterizationProperties.degenerateLinesRasterized)
4073 	{
4074 		log << tcu::TestLog::Message << "Lines expected to be rasterized with white color" << tcu::TestLog::EndMessage;
4075 
4076 		// This pixel will alway be covered due to the placement of the line.
4077 		referenceImage.setPixel(1, 1, foregroundColor);
4078 
4079 		// Additional pixels will be covered based on the extra bloat added to the primitive.
4080 		const float extraOverestimation = getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
4081 		const int xExtent = 1 + int((extraOverestimation * 2.0f) + 0.5f);
4082 		const int yExtent = xExtent;
4083 
4084 		for (int y = 0; y <= yExtent; ++y)
4085 		for (int x = 0; x <= xExtent; ++x)
4086 			referenceImage.setPixel(x, y, foregroundColor);
4087 	}
4088 	else
4089 		log << tcu::TestLog::Message << "Lines expected to be culled" << tcu::TestLog::EndMessage;
4090 
4091 	for (int y = 0; result && y < resultImage.getHeight(); ++y)
4092 	for (int x = 0; result && x < resultImage.getWidth(); ++x)
4093 	{
4094 		if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
4095 		{
4096 			result = false;
4097 
4098 			break;
4099 		}
4100 	}
4101 
4102 	if (!result)
4103 	{
4104 		tcu::Surface	errorMask	(resultImage.getWidth(), resultImage.getHeight());
4105 
4106 		for (int y = 0; y < errorMask.getHeight(); ++y)
4107 		for (int x = 0; x < errorMask.getWidth(); ++x)
4108 		{
4109 			if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
4110 				errorMask.setPixel(x, y, unexpectedPixelColor);
4111 			else
4112 				errorMask.setPixel(x, y, backgroundColor);
4113 		}
4114 
4115 		log << tcu::TestLog::Message << "Invalid pixels found for mode " << iterationComments[getIteration()]
4116 			<< tcu::TestLog::EndMessage;
4117 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4118 			<< tcu::TestLog::Image("Result",	"Result",		resultImage)
4119 			<< tcu::TestLog::Image("Reference",	"Reference",	referenceImage)
4120 			<< tcu::TestLog::Image("ErrorMask", "ErrorMask",	errorMask)
4121 			<< tcu::TestLog::EndImageSet;
4122 	}
4123 	else
4124 	{
4125 		log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
4126 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4127 			<< tcu::TestLog::Image("Result", "Result", resultImage)
4128 			<< tcu::TestLog::EndImageSet;
4129 	}
4130 
4131 	return result;
4132 }
4133 
compareAndVerifyUnderestimatedNormal(std::vector<LineSceneSpec::SceneLine> & lines,tcu::Surface & resultImage)4134 bool ConservativeLineTestInstance::compareAndVerifyUnderestimatedNormal (std::vector<LineSceneSpec::SceneLine>& lines, tcu::Surface& resultImage)
4135 {
4136 	DE_UNREF(lines);
4137 
4138 	const tcu::RGBA		backgroundColor			= tcu::RGBA(0, 0, 0, 255);
4139 	const tcu::RGBA		foregroundColor			= tcu::RGBA(255, 255, 255, 255);
4140 	const tcu::RGBA		unexpectedPixelColor	= tcu::RGBA(255, 0, 0, 255);
4141 	tcu::TestLog&		log						= m_context.getTestContext().getLog();
4142 	int					errX					= -1;
4143 	int					errY					= -1;
4144 	tcu::RGBA			errValue;
4145 	bool				result					= true;
4146 	tcu::Surface		referenceImage			(resultImage.getWidth(), resultImage.getHeight());
4147 
4148 	DE_ASSERT(resultImage.getHeight() == resultImage.getWidth());
4149 
4150 	for (int y = 0; y < referenceImage.getHeight(); ++y)
4151 	for (int x = 0; x < referenceImage.getWidth(); ++x)
4152 		referenceImage.setPixel(x, y, backgroundColor);
4153 
4154 	if (getLineWidth() > 1.0f)
4155 	{
4156 		const tcu::IVec2	viewportSize(resultImage.getWidth(), resultImage.getHeight());
4157 
4158 		for (size_t lineNdx = 0; lineNdx < lines.size(); ++lineNdx)
4159 		for (int y = 0; y < resultImage.getHeight(); ++y)
4160 		for (int x = 0; x < resultImage.getWidth(); ++x)
4161 		{
4162 			if (calculateUnderestimateLineCoverage(lines[lineNdx].positions[0], lines[lineNdx].positions[1], getLineWidth(), tcu::IVec2(x,y), viewportSize) == tcu::COVERAGE_FULL)
4163 				referenceImage.setPixel(x, y, foregroundColor);
4164 		}
4165 	}
4166 
4167 	for (int y = 0; result && y < resultImage.getHeight(); ++y)
4168 	for (int x = 0; result && x < resultImage.getWidth(); ++x)
4169 	{
4170 		if (resultImage.getPixel(x,y).getPacked() != referenceImage.getPixel(x,y).getPacked())
4171 		{
4172 			result		= false;
4173 			errX		= x;
4174 			errY		= y;
4175 			errValue	= resultImage.getPixel(x,y);
4176 
4177 			break;
4178 		}
4179 	}
4180 
4181 	if (!result)
4182 	{
4183 		tcu::Surface	errorMask	(resultImage.getWidth(), resultImage.getHeight());
4184 
4185 		for (int y = 0; y < errorMask.getHeight(); ++y)
4186 		for (int x = 0; x < errorMask.getWidth(); ++x)
4187 			errorMask.setPixel(x, y, backgroundColor);
4188 
4189 		for (int y = 0; y < errorMask.getHeight(); ++y)
4190 		for (int x = 0; x < errorMask.getWidth();  ++x)
4191 		{
4192 			if (resultImage.getPixel(x,y).getPacked() != referenceImage.getPixel(x,y).getPacked())
4193 				errorMask.setPixel(x, y, unexpectedPixelColor);
4194 		}
4195 
4196 		log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " errValue=" << errValue
4197 			<< tcu::TestLog::EndMessage;
4198 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4199 			<< tcu::TestLog::Image("Result",	"Result",		resultImage)
4200 			<< tcu::TestLog::Image("Reference",	"Reference",	referenceImage)
4201 			<< tcu::TestLog::Image("ErrorMask", "ErrorMask",	errorMask)
4202 			<< tcu::TestLog::EndImageSet;
4203 	}
4204 	else
4205 	{
4206 		log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
4207 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4208 			<< tcu::TestLog::Image("Result", "Result", resultImage)
4209 			<< tcu::TestLog::EndImageSet;
4210 	}
4211 
4212 	return result;
4213 }
4214 
compareAndVerifyUnderestimatedDegenerate(std::vector<LineSceneSpec::SceneLine> & lines,tcu::Surface & resultImage)4215 bool ConservativeLineTestInstance::compareAndVerifyUnderestimatedDegenerate (std::vector<LineSceneSpec::SceneLine>& lines, tcu::Surface& resultImage)
4216 {
4217 	DE_UNREF(lines);
4218 
4219 	const tcu::RGBA		backgroundColor			= tcu::RGBA(0, 0, 0, 255);
4220 	const tcu::RGBA		unexpectedPixelColor	= tcu::RGBA(255, 0, 0, 255);
4221 	tcu::TestLog&		log						= m_context.getTestContext().getLog();
4222 	bool				result					= true;
4223 	tcu::Surface		referenceImage			(resultImage.getWidth(), resultImage.getHeight());
4224 
4225 	for (int y = 0; y < resultImage.getHeight(); ++y)
4226 	for (int x = 0; x < resultImage.getWidth(); ++x)
4227 		referenceImage.setPixel(x, y, backgroundColor);
4228 
4229 	log << tcu::TestLog::Message << "No lines expected to be rasterized" << tcu::TestLog::EndMessage;
4230 
4231 	for (int y = 0; result && y < resultImage.getHeight(); ++y)
4232 	for (int x = 0; result && x < resultImage.getWidth(); ++x)
4233 	{
4234 		if (resultImage.getPixel(x,y).getPacked() != referenceImage.getPixel(x,y).getPacked())
4235 		{
4236 			result = false;
4237 
4238 			break;
4239 		}
4240 	}
4241 
4242 	if (!result)
4243 	{
4244 		tcu::Surface	errorMask	(resultImage.getWidth(), resultImage.getHeight());
4245 
4246 		for (int y = 0; y < errorMask.getHeight(); ++y)
4247 		for (int x = 0; x < errorMask.getWidth(); ++x)
4248 		{
4249 			if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
4250 				errorMask.setPixel(x, y, unexpectedPixelColor);
4251 			else
4252 				errorMask.setPixel(x, y, backgroundColor);
4253 		}
4254 
4255 		log << tcu::TestLog::Message << "Invalid pixels found" << tcu::TestLog::EndMessage;
4256 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4257 			<< tcu::TestLog::Image("Result",	"Result",		resultImage)
4258 			<< tcu::TestLog::Image("Reference",	"Reference",	referenceImage)
4259 			<< tcu::TestLog::Image("ErrorMask", "ErrorMask",	errorMask)
4260 			<< tcu::TestLog::EndImageSet;
4261 	}
4262 	else
4263 	{
4264 		log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
4265 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4266 			<< tcu::TestLog::Image("Result", "Result", resultImage)
4267 			<< tcu::TestLog::EndImageSet;
4268 	}
4269 
4270 	return result;
4271 }
4272 
initRasterizationConservativeStateCreateInfo(void)4273 const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT> ConservativeLineTestInstance::initRasterizationConservativeStateCreateInfo (void)
4274 {
4275 	const float															extraOverestimationSize	= getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
4276 	std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>	result;
4277 
4278 	result.reserve(getIterationCount());
4279 
4280 	for (int iteration = 0; iteration < getIterationCount(); ++iteration)
4281 	{
4282 		const VkPipelineRasterizationConservativeStateCreateInfoEXT	rasterizationConservativeStateCreateInfo	=
4283 		{
4284 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,	//  VkStructureType											sType;
4285 			DE_NULL,																		//  const void*												pNext;
4286 			(VkPipelineRasterizationConservativeStateCreateFlagsEXT)0,						//  VkPipelineRasterizationConservativeStateCreateFlagsEXT	flags;
4287 			m_conservativeTestConfig.conservativeRasterizationMode,							//  VkConservativeRasterizationModeEXT						conservativeRasterizationMode;
4288 			extraOverestimationSize															//  float													extraPrimitiveOverestimationSize;
4289 		};
4290 
4291 		result.push_back(rasterizationConservativeStateCreateInfo);
4292 	}
4293 
4294 	return result;
4295 }
4296 
initRasterizationStateCreateInfo(void)4297 const std::vector<VkPipelineRasterizationStateCreateInfo> ConservativeLineTestInstance::initRasterizationStateCreateInfo (void)
4298 {
4299 	std::vector<VkPipelineRasterizationStateCreateInfo>	result;
4300 
4301 	result.reserve(getIterationCount());
4302 
4303 	for (int iteration = 0; iteration < getIterationCount(); ++iteration)
4304 	{
4305 		const VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
4306 		{
4307 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		//  VkStructureType							sType;
4308 			&m_rasterizationConservativeStateCreateInfo[iteration],			//  const void*								pNext;
4309 			0,																//  VkPipelineRasterizationStateCreateFlags	flags;
4310 			false,															//  VkBool32								depthClampEnable;
4311 			false,															//  VkBool32								rasterizerDiscardEnable;
4312 			VK_POLYGON_MODE_FILL,											//  VkPolygonMode							polygonMode;
4313 			VK_CULL_MODE_NONE,												//  VkCullModeFlags							cullMode;
4314 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								//  VkFrontFace								frontFace;
4315 			VK_FALSE,														//  VkBool32								depthBiasEnable;
4316 			0.0f,															//  float									depthBiasConstantFactor;
4317 			0.0f,															//  float									depthBiasClamp;
4318 			0.0f,															//  float									depthBiasSlopeFactor;
4319 			getLineWidth(),													//  float									lineWidth;
4320 		};
4321 
4322 		result.push_back(rasterizationStateCreateInfo);
4323 	}
4324 
4325 	return result;
4326 }
4327 
getRasterizationStateCreateInfo(void) const4328 const VkPipelineRasterizationStateCreateInfo* ConservativeLineTestInstance::getRasterizationStateCreateInfo	(void) const
4329 {
4330 	return &m_rasterizationStateCreateInfo[getIteration()];
4331 }
4332 
getLineRasterizationStateCreateInfo(void)4333 const VkPipelineRasterizationLineStateCreateInfoEXT* ConservativeLineTestInstance::getLineRasterizationStateCreateInfo	(void)
4334 {
4335 	return DE_NULL;
4336 }
4337 
4338 
4339 class ConservativePointTestInstance : public PointTestInstance
4340 {
4341 public:
ConservativePointTestInstance(Context & context,ConservativeTestConfig conservativeTestConfig,VkSampleCountFlagBits sampleCount)4342 																				ConservativePointTestInstance					(Context&				context,
4343 																																 ConservativeTestConfig	conservativeTestConfig,
4344 																																 VkSampleCountFlagBits	sampleCount)
4345 																					: PointTestInstance								(
4346 																																		context,
4347 																																		PRIMITIVEWIDENESS_NARROW,
4348 																																		PRIMITIVESTRICTNESS_IGNORE,
4349 																																		sampleCount,
4350 																																		LINESTIPPLE_DISABLED,
4351 																																		VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT,
4352 																																		LineStippleFactorCase::DEFAULT,
4353 																																		0,
4354 																																		conservativeTestConfig.resolution,
4355 																																		conservativeTestConfig.lineWidth
4356 																																	)
4357 																					, m_conservativeTestConfig						(conservativeTestConfig)
4358 																					, m_conservativeRasterizationProperties			(context.getConservativeRasterizationPropertiesEXT())
4359 																					, m_rasterizationConservativeStateCreateInfo	(initRasterizationConservativeStateCreateInfo())
4360 																					, m_rasterizationStateCreateInfo				(initRasterizationStateCreateInfo())
4361 																					, m_renderStart									()
4362 																					, m_renderEnd									()
4363 																				{}
4364 
4365 	void																		generatePoints									(int										iteration,
4366 																																 std::vector<tcu::Vec4>&					outData,
4367 																																 std::vector<PointSceneSpec::ScenePoint>&	outPoints);
4368 	const VkPipelineRasterizationStateCreateInfo*								getRasterizationStateCreateInfo					(void) const;
4369 
4370 protected:
4371 	virtual const VkPipelineRasterizationLineStateCreateInfoEXT*				getLineRasterizationStateCreateInfo				(void);
4372 
4373 	virtual bool																compareAndVerify								(std::vector<PointSceneSpec::ScenePoint>&	points,
4374 																																 tcu::Surface&								resultImage,
4375 																																 std::vector<tcu::Vec4>&					drawBuffer);
4376 	virtual bool																compareAndVerifyOverestimated					(std::vector<PointSceneSpec::ScenePoint>&	points,
4377 																																 tcu::Surface&								resultImage);
4378 	virtual bool																compareAndVerifyUnderestimated					(std::vector<PointSceneSpec::ScenePoint>&	points,
4379 																																 tcu::Surface&								resultImage);
4380 
4381 private:
4382 	const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>	initRasterizationConservativeStateCreateInfo	(void);
4383 	const std::vector<VkPipelineRasterizationStateCreateInfo>					initRasterizationStateCreateInfo				(void);
4384 
4385 	const ConservativeTestConfig												m_conservativeTestConfig;
4386 	const VkPhysicalDeviceConservativeRasterizationPropertiesEXT				m_conservativeRasterizationProperties;
4387 	const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>	m_rasterizationConservativeStateCreateInfo;
4388 	const std::vector<VkPipelineRasterizationStateCreateInfo>					m_rasterizationStateCreateInfo;
4389 	std::vector<int>															m_renderStart;
4390 	std::vector<int>															m_renderEnd;
4391 };
4392 
generatePoints(int iteration,std::vector<tcu::Vec4> & outData,std::vector<PointSceneSpec::ScenePoint> & outPoints)4393 void ConservativePointTestInstance::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
4394 {
4395 	const float	pixelSize		= 2.0f / float(m_renderSize);
4396 	const bool	isOverestimate	= m_conservativeTestConfig.conservativeRasterizationMode == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
4397 
4398 	m_renderStart.clear();
4399 	m_renderEnd.clear();
4400 
4401 	if (isOverestimate)
4402 	{
4403 		const float	extraOverestimationSize	= getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
4404 		const float	overestimate			= m_conservativeRasterizationProperties.primitiveOverestimationSize + extraOverestimationSize;
4405 		const float	halfRenderAreaSize		= overestimate + 0.5f;
4406 		const float	pointCenterOffset		= 2.0f + 0.5f * float(iteration) + halfRenderAreaSize;
4407 		const float	pointEdgeStart			= pointCenterOffset - halfRenderAreaSize;
4408 		const float	pointEdgeEnd			= pointEdgeStart + 2 * halfRenderAreaSize;
4409 		const int	renderStart				= int(deFloatFloor(pointEdgeStart)) + int((deFloatFrac(pointEdgeStart) > 0.0f) ? 0 : -1);
4410 		const int	renderEnd				= int(deFloatCeil(pointEdgeEnd)) + int((deFloatFrac(pointEdgeEnd) > 0.0f) ? 0 : 1);
4411 
4412 		outData.push_back(tcu::Vec4(-1.0f + pixelSize * pointCenterOffset, -1.0f + pixelSize * pointCenterOffset, 0.0f, 1.0f));
4413 
4414 		m_renderStart.push_back(renderStart);
4415 		m_renderEnd.push_back(renderEnd);
4416 	}
4417 	else
4418 	{
4419 		const float	pointSize			= m_conservativeTestConfig.lineWidth;
4420 		const float	halfRenderAreaSize	= pointSize / 2.0f;
4421 
4422 		switch (iteration)
4423 		{
4424 			case 0:
4425 			{
4426 				const float	pointCenterOffset	= (pointSize + 1.0f + deFloatFrac(pointSize)) / 2.0f;
4427 				const float	pointEdgeStart		= pointCenterOffset - halfRenderAreaSize;
4428 				const float	pointEdgeEnd		= pointEdgeStart + 2.0f * halfRenderAreaSize;
4429 				const int	renderStart			= (m_renderSize / 2) + int(deFloatCeil(pointEdgeStart));
4430 				const int	renderEnd			= (m_renderSize / 2) + int(deFloatFloor(pointEdgeEnd));
4431 
4432 				outData.push_back(tcu::Vec4(pixelSize * pointCenterOffset, pixelSize * pointCenterOffset, 0.0f, 1.0f));
4433 
4434 				m_renderStart.push_back(renderStart);
4435 				m_renderEnd.push_back(renderEnd);
4436 
4437 				break;
4438 			}
4439 
4440 			case 1:
4441 			{
4442 				const float subPixelSize		= 1.0f / float(1u<<(m_subpixelBits - 1));
4443 				const float	pointBottomLeft		= 1.0f - subPixelSize;
4444 				const float	pointCenterOffset	= pointBottomLeft + pointSize / 2.0f;
4445 				const float	pointEdgeStart		= pointCenterOffset - halfRenderAreaSize;
4446 				const float	pointEdgeEnd		= pointEdgeStart + 2.0f * halfRenderAreaSize;
4447 				const int	renderStart			= (m_renderSize / 2) + int(deFloatCeil(pointEdgeStart));
4448 				const int	renderEnd			= (m_renderSize / 2) + int(deFloatFloor(pointEdgeEnd));
4449 
4450 				outData.push_back(tcu::Vec4(pixelSize * pointCenterOffset, pixelSize * pointCenterOffset, 0.0f, 1.0f));
4451 
4452 				m_renderStart.push_back(renderStart);
4453 				m_renderEnd.push_back(renderEnd);
4454 
4455 				break;
4456 			}
4457 
4458 			case 2:
4459 			{
4460 				// Edges of a point are considered not covered. Top-left coverage rule is not applicable for underestimate rasterization.
4461 				const float	pointCenterOffset	= (pointSize + deFloatFrac(pointSize)) / 2.0f;
4462 				const float	pointEdgeStart		= pointCenterOffset - halfRenderAreaSize;
4463 				const float	pointEdgeEnd		= pointEdgeStart + 2.0f * halfRenderAreaSize;
4464 				const int	renderStart			= (m_renderSize / 2) + int(deFloatCeil(pointEdgeStart)) + 1;
4465 				const int	renderEnd			= (m_renderSize / 2) + int(deFloatFloor(pointEdgeEnd)) - 1;
4466 
4467 				outData.push_back(tcu::Vec4(pixelSize * pointCenterOffset, pixelSize * pointCenterOffset, 0.0f, 1.0f));
4468 
4469 				m_renderStart.push_back(renderStart);
4470 				m_renderEnd.push_back(renderEnd);
4471 
4472 				break;
4473 			}
4474 
4475 			default:
4476 				TCU_THROW(InternalError, "Unexpected iteration");
4477 		}
4478 	}
4479 
4480 	outPoints.resize(outData.size());
4481 	for (size_t ndx = 0; ndx < outPoints.size(); ++ndx)
4482 	{
4483 		outPoints[ndx].position = outData[ndx];
4484 		outPoints[ndx].pointSize = getPointSize();
4485 	}
4486 
4487 	// log
4488 	m_context.getTestContext().getLog()
4489 		<< tcu::TestLog::Message
4490 		<< "Testing conservative point rendering "
4491 		<< "with rendering " << outPoints.size() << " points(s):"
4492 		<< tcu::TestLog::EndMessage;
4493 	for (int ndx = 0; ndx < (int)outPoints.size(); ++ndx)
4494 	{
4495 		const deUint32	 multiplier	= m_renderSize / 2;
4496 
4497 		m_context.getTestContext().getLog()
4498 			<< tcu::TestLog::Message
4499 			<< "Point " << (ndx+1) << ":"
4500 			<< "\n\t" << outPoints[ndx].position << " == " << (float(multiplier) * outPoints[ndx].position) << "/" << multiplier
4501 			<< tcu::TestLog::EndMessage;
4502 	}
4503 }
4504 
compareAndVerify(std::vector<PointSceneSpec::ScenePoint> & points,tcu::Surface & resultImage,std::vector<tcu::Vec4> & drawBuffer)4505 bool ConservativePointTestInstance::compareAndVerify (std::vector<PointSceneSpec::ScenePoint>& points, tcu::Surface& resultImage, std::vector<tcu::Vec4>& drawBuffer)
4506 {
4507 	DE_UNREF(drawBuffer);
4508 
4509 	switch (m_conservativeTestConfig.conservativeRasterizationMode)
4510 	{
4511 		case VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT:
4512 		{
4513 			return compareAndVerifyOverestimated(points, resultImage);
4514 		}
4515 		case VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT:
4516 		{
4517 			return compareAndVerifyUnderestimated(points, resultImage);
4518 		}
4519 
4520 		default:
4521 			TCU_THROW(InternalError, "Unknown conservative rasterization mode");
4522 	}
4523 }
4524 
compareAndVerifyOverestimated(std::vector<PointSceneSpec::ScenePoint> & points,tcu::Surface & resultImage)4525 bool ConservativePointTestInstance::compareAndVerifyOverestimated (std::vector<PointSceneSpec::ScenePoint>& points, tcu::Surface& resultImage)
4526 {
4527 	DE_UNREF(points);
4528 
4529 	const char*			iterationComments[]		= { "Edges and corners", "Partial coverage", "Edges and corners" };
4530 	const tcu::RGBA		backgroundColor			= tcu::RGBA(0, 0, 0, 255);
4531 	const tcu::RGBA		foregroundColor			= tcu::RGBA(255, 255, 255, 255);
4532 	const tcu::RGBA		unexpectedPixelColor	= tcu::RGBA(255, 0, 0, 255);
4533 	tcu::TestLog&		log						= m_context.getTestContext().getLog();
4534 	int					errX					= 0;
4535 	int					errY					= 0;
4536 	deUint32			errValue				= 0;
4537 	bool				result					= true;
4538 
4539 	log << tcu::TestLog::Message << "Points expected to be rasterized with white color" << tcu::TestLog::EndMessage;
4540 	log << tcu::TestLog::Message << "Testing " << iterationComments[getIteration()] << tcu::TestLog::EndMessage;
4541 
4542 	for (size_t renderAreaNdx = 0; result && renderAreaNdx < m_renderStart.size(); ++renderAreaNdx)
4543 	{
4544 		const int renderStart	= m_renderStart[renderAreaNdx];
4545 		const int renderEnd		= m_renderEnd[renderAreaNdx];
4546 
4547 		for (int y = renderStart; result && y < renderEnd; ++y)
4548 		for (int x = renderStart; result && x < renderEnd; ++x)
4549 		{
4550 			if (resultImage.getPixel(x,y).getPacked() != foregroundColor.getPacked())
4551 			{
4552 				result		= false;
4553 				errX		= x;
4554 				errY		= y;
4555 				errValue	= resultImage.getPixel(x, y).getPacked();
4556 
4557 				break;
4558 			}
4559 		}
4560 	}
4561 
4562 	if (!result)
4563 	{
4564 		tcu::Surface		referenceImage	(resultImage.getWidth(), resultImage.getHeight());
4565 		tcu::Surface		errorMask		(resultImage.getWidth(), resultImage.getHeight());
4566 		std::ostringstream	css;
4567 
4568 		for (int y = 0; y < resultImage.getHeight(); ++y)
4569 		for (int x = 0; x < resultImage.getWidth(); ++x)
4570 			referenceImage.setPixel(x, y, backgroundColor);
4571 
4572 		for (size_t renderAreaNdx = 0; renderAreaNdx < m_renderStart.size(); ++renderAreaNdx)
4573 		{
4574 			const int renderStart	= m_renderStart[renderAreaNdx];
4575 			const int renderEnd		= m_renderEnd[renderAreaNdx];
4576 
4577 			for (int y = renderStart; y < renderEnd; ++y)
4578 			for (int x = renderStart; x < renderEnd; ++x)
4579 				referenceImage.setPixel(x, y, foregroundColor);
4580 		}
4581 
4582 		for (int y = 0; y < errorMask.getHeight(); ++y)
4583 		for (int x = 0; x < errorMask.getWidth(); ++x)
4584 		{
4585 			if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
4586 				errorMask.setPixel(x, y, unexpectedPixelColor);
4587 			else
4588 				errorMask.setPixel(x, y, backgroundColor);
4589 		}
4590 
4591 		css << std::endl;
4592 		for (size_t renderAreaNdx = 0; renderAreaNdx < m_renderStart.size(); ++renderAreaNdx)
4593 		{
4594 			const int renderStart	= m_renderStart[renderAreaNdx];
4595 			const int renderEnd		= m_renderEnd[renderAreaNdx];
4596 
4597 			css << "[" << renderStart << "," << renderEnd << ") x [" << renderStart << "," << renderEnd << ")" << std::endl;
4598 		}
4599 
4600 		log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
4601 			<< tcu::TestLog::EndMessage;
4602 		log << tcu::TestLog::Message << "Expected area(s) to be filled:" << css.str()
4603 			<< tcu::TestLog::EndMessage;
4604 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4605 			<< tcu::TestLog::Image("Result",	"Result",		resultImage)
4606 			<< tcu::TestLog::Image("Reference",	"Reference",	referenceImage)
4607 			<< tcu::TestLog::Image("ErrorMask", "ErrorMask",	errorMask)
4608 			<< tcu::TestLog::EndImageSet;
4609 	}
4610 	else
4611 	{
4612 		log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
4613 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4614 			<< tcu::TestLog::Image("Result", "Result", resultImage)
4615 			<< tcu::TestLog::EndImageSet;
4616 	}
4617 
4618 	return result;
4619 }
4620 
compareAndVerifyUnderestimated(std::vector<PointSceneSpec::ScenePoint> & points,tcu::Surface & resultImage)4621 bool ConservativePointTestInstance::compareAndVerifyUnderestimated (std::vector<PointSceneSpec::ScenePoint>& points, tcu::Surface& resultImage)
4622 {
4623 	DE_UNREF(points);
4624 
4625 	const char*			iterationComments[]		= { "Full coverage", "Full coverage with subpixel", "Exact coverage" };
4626 	const tcu::RGBA		backgroundColor			= tcu::RGBA(0, 0, 0, 255);
4627 	const tcu::RGBA		foregroundColor			= tcu::RGBA(255, 255, 255, 255);
4628 	const tcu::RGBA		unexpectedPixelColor	= tcu::RGBA(255, 0, 0, 255);
4629 	tcu::TestLog&		log						= m_context.getTestContext().getLog();
4630 	int					errX					= 0;
4631 	int					errY					= 0;
4632 	deUint32			errValue				= 0;
4633 	bool				result					= true;
4634 	tcu::Surface		referenceImage			(resultImage.getWidth(), resultImage.getHeight());
4635 
4636 	log << tcu::TestLog::Message << "Points expected to be rasterized with white color" << tcu::TestLog::EndMessage;
4637 	log << tcu::TestLog::Message << "Testing " << iterationComments[getIteration()] << tcu::TestLog::EndMessage;
4638 
4639 	for (int y = 0; y < resultImage.getHeight(); ++y)
4640 	for (int x = 0; x < resultImage.getWidth(); ++x)
4641 		referenceImage.setPixel(x, y, backgroundColor);
4642 
4643 	for (size_t renderAreaNdx = 0; result && renderAreaNdx < m_renderStart.size(); ++renderAreaNdx)
4644 	{
4645 		const int renderStart	= m_renderStart[renderAreaNdx];
4646 		const int renderEnd		= m_renderEnd[renderAreaNdx];
4647 
4648 		for (int y = renderStart; y < renderEnd; ++y)
4649 		for (int x = renderStart; x < renderEnd; ++x)
4650 			referenceImage.setPixel(x, y, foregroundColor);
4651 	}
4652 
4653 	for (int y = 0; result && y < resultImage.getHeight(); ++y)
4654 	for (int x = 0; result && x < resultImage.getWidth(); ++x)
4655 	{
4656 		if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
4657 		{
4658 			result		= false;
4659 			errX		= x;
4660 			errY		= y;
4661 			errValue	= resultImage.getPixel(x, y).getPacked();
4662 
4663 			break;
4664 		}
4665 	}
4666 
4667 	if (!result)
4668 	{
4669 		tcu::Surface		errorMask	(resultImage.getWidth(), resultImage.getHeight());
4670 		std::ostringstream	css;
4671 
4672 		for (int y = 0; y < errorMask.getHeight(); ++y)
4673 		for (int x = 0; x < errorMask.getWidth(); ++x)
4674 		{
4675 			if (resultImage.getPixel(x, y).getPacked() != referenceImage.getPixel(x, y).getPacked())
4676 				errorMask.setPixel(x, y, unexpectedPixelColor);
4677 			else
4678 				errorMask.setPixel(x, y, backgroundColor);
4679 		}
4680 
4681 		css << std::endl;
4682 		for (size_t renderAreaNdx = 0; renderAreaNdx < m_renderStart.size(); ++renderAreaNdx)
4683 		{
4684 			const int renderStart	= m_renderStart[renderAreaNdx];
4685 			const int renderEnd		= m_renderEnd[renderAreaNdx];
4686 
4687 			css << "[" << renderStart << "," << renderEnd << ") x [" << renderStart << "," << renderEnd << ")" << std::endl;
4688 		}
4689 
4690 		log << tcu::TestLog::Message << "Invalid pixels found starting at " << errX << "," << errY << " value=0x" << std::hex << errValue
4691 			<< tcu::TestLog::EndMessage;
4692 		log << tcu::TestLog::Message << "Expected area(s) to be filled:" << css.str()
4693 			<< tcu::TestLog::EndMessage;
4694 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4695 			<< tcu::TestLog::Image("Result",	"Result",		resultImage)
4696 			<< tcu::TestLog::Image("Reference",	"Reference",	referenceImage)
4697 			<< tcu::TestLog::Image("ErrorMask", "ErrorMask",	errorMask)
4698 			<< tcu::TestLog::EndImageSet;
4699 	}
4700 	else
4701 	{
4702 		log << tcu::TestLog::Message << "No invalid pixels found." << tcu::TestLog::EndMessage;
4703 		log << tcu::TestLog::ImageSet("Verification result", "Result of rendering")
4704 			<< tcu::TestLog::Image("Result", "Result", resultImage)
4705 			<< tcu::TestLog::EndImageSet;
4706 	}
4707 
4708 	return result;
4709 }
4710 
initRasterizationConservativeStateCreateInfo(void)4711 const std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT> ConservativePointTestInstance::initRasterizationConservativeStateCreateInfo (void)
4712 {
4713 	const float															extraOverestimationSize	= getExtraOverestimationSize(m_conservativeTestConfig.extraOverestimationSize, m_conservativeRasterizationProperties);
4714 	std::vector<VkPipelineRasterizationConservativeStateCreateInfoEXT>	result;
4715 
4716 	result.reserve(getIterationCount());
4717 
4718 	for (int iteration = 0; iteration < getIterationCount(); ++iteration)
4719 	{
4720 		const VkPipelineRasterizationConservativeStateCreateInfoEXT	rasterizationConservativeStateCreateInfo	=
4721 		{
4722 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT,	//  VkStructureType											sType;
4723 			DE_NULL,																		//  const void*												pNext;
4724 			(VkPipelineRasterizationConservativeStateCreateFlagsEXT)0,						//  VkPipelineRasterizationConservativeStateCreateFlagsEXT	flags;
4725 			m_conservativeTestConfig.conservativeRasterizationMode,							//  VkConservativeRasterizationModeEXT						conservativeRasterizationMode;
4726 			extraOverestimationSize															//  float													extraPrimitiveOverestimationSize;
4727 		};
4728 
4729 		result.push_back(rasterizationConservativeStateCreateInfo);
4730 	}
4731 
4732 	return result;
4733 }
4734 
initRasterizationStateCreateInfo(void)4735 const std::vector<VkPipelineRasterizationStateCreateInfo> ConservativePointTestInstance::initRasterizationStateCreateInfo (void)
4736 {
4737 	std::vector<VkPipelineRasterizationStateCreateInfo>	result;
4738 
4739 	result.reserve(getIterationCount());
4740 
4741 	for (int iteration = 0; iteration < getIterationCount(); ++iteration)
4742 	{
4743 		const VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
4744 		{
4745 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		//  VkStructureType							sType;
4746 			&m_rasterizationConservativeStateCreateInfo[iteration],			//  const void*								pNext;
4747 			0,																//  VkPipelineRasterizationStateCreateFlags	flags;
4748 			false,															//  VkBool32								depthClampEnable;
4749 			false,															//  VkBool32								rasterizerDiscardEnable;
4750 			VK_POLYGON_MODE_FILL,											//  VkPolygonMode							polygonMode;
4751 			VK_CULL_MODE_NONE,												//  VkCullModeFlags							cullMode;
4752 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								//  VkFrontFace								frontFace;
4753 			VK_FALSE,														//  VkBool32								depthBiasEnable;
4754 			0.0f,															//  float									depthBiasConstantFactor;
4755 			0.0f,															//  float									depthBiasClamp;
4756 			0.0f,															//  float									depthBiasSlopeFactor;
4757 			0.0f,															//  float									lineWidth;
4758 		};
4759 
4760 		result.push_back(rasterizationStateCreateInfo);
4761 	}
4762 
4763 	return result;
4764 }
4765 
getRasterizationStateCreateInfo(void) const4766 const VkPipelineRasterizationStateCreateInfo* ConservativePointTestInstance::getRasterizationStateCreateInfo	(void) const
4767 {
4768 	return &m_rasterizationStateCreateInfo[getIteration()];
4769 }
4770 
getLineRasterizationStateCreateInfo(void)4771 const VkPipelineRasterizationLineStateCreateInfoEXT* ConservativePointTestInstance::getLineRasterizationStateCreateInfo	(void)
4772 {
4773 	return DE_NULL;
4774 }
4775 
4776 template <typename ConcreteTestInstance>
4777 class WidenessTestCase : public BaseRenderingTestCase
4778 {
4779 public:
WidenessTestCase(tcu::TestContext & context,const std::string & name,PrimitiveWideness wideness,PrimitiveStrictness strictness,bool isLineTest,VkSampleCountFlagBits sampleCount,LineStipple stipple,VkLineRasterizationModeEXT lineRasterizationMode,LineStippleFactorCase stippleFactor=LineStippleFactorCase::DEFAULT,deUint32 additionalRenderSize=0)4780 								WidenessTestCase	(tcu::TestContext&			context,
4781 													 const std::string&			name,
4782 													 PrimitiveWideness			wideness,
4783 													 PrimitiveStrictness		strictness,
4784 													 bool						isLineTest,
4785 													 VkSampleCountFlagBits		sampleCount,
4786 													 LineStipple				stipple,
4787 													 VkLineRasterizationModeEXT	lineRasterizationMode,
4788 													 LineStippleFactorCase		stippleFactor = LineStippleFactorCase::DEFAULT,
4789 													 deUint32					additionalRenderSize	= 0)
4790 									: BaseRenderingTestCase		(context, name, sampleCount)
4791 									, m_wideness				(wideness)
4792 									, m_strictness				(strictness)
4793 									, m_isLineTest				(isLineTest)
4794 									, m_stipple					(stipple)
4795 									, m_lineRasterizationMode	(lineRasterizationMode)
4796 									, m_stippleFactor			(stippleFactor)
4797 									, m_additionalRenderSize	(additionalRenderSize)
4798 								{}
4799 
createInstance(Context & context) const4800 	virtual TestInstance*		createInstance		(Context& context) const
4801 								{
4802 									return new ConcreteTestInstance(context, m_wideness, m_strictness, m_sampleCount, m_stipple, m_lineRasterizationMode, m_stippleFactor, m_additionalRenderSize);
4803 								}
4804 
checkSupport(Context & context) const4805 	virtual	void				checkSupport		(Context& context) const
4806 								{
4807 									if (m_isLineTest)
4808 									{
4809 										if (m_stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY)
4810 											context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state");
4811 
4812 										if (m_wideness == PRIMITIVEWIDENESS_WIDE)
4813 											context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_WIDE_LINES);
4814 
4815 										switch (m_lineRasterizationMode)
4816 										{
4817 											default:
4818 												TCU_THROW(InternalError, "Unknown line rasterization mode");
4819 
4820 											case VK_LINE_RASTERIZATION_MODE_EXT_LAST:
4821 											{
4822 												if (m_strictness == PRIMITIVESTRICTNESS_STRICT)
4823 													if (!context.getDeviceProperties().limits.strictLines)
4824 														TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
4825 
4826 												if (m_strictness == PRIMITIVESTRICTNESS_NONSTRICT)
4827 													if (context.getDeviceProperties().limits.strictLines)
4828 														TCU_THROW(NotSupportedError, "Nonstrict rasterization is not supported");
4829 
4830 												break;
4831 											}
4832 
4833 											case VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT:
4834 											{
4835 												if (!context.getDeviceProperties().limits.strictLines)
4836 													TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
4837 
4838 												if (getLineStippleEnable() &&
4839 													!context.getLineRasterizationFeaturesEXT().stippledRectangularLines)
4840 													TCU_THROW(NotSupportedError, "Stippled rectangular lines not supported");
4841 												break;
4842 											}
4843 
4844 											case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT:
4845 											{
4846 												if (!context.getLineRasterizationFeaturesEXT().rectangularLines)
4847 													TCU_THROW(NotSupportedError, "Rectangular lines not supported");
4848 
4849 												if (getLineStippleEnable() &&
4850 													!context.getLineRasterizationFeaturesEXT().stippledRectangularLines)
4851 													TCU_THROW(NotSupportedError, "Stippled rectangular lines not supported");
4852 												break;
4853 											}
4854 
4855 											case VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT:
4856 											{
4857 												if (!context.getLineRasterizationFeaturesEXT().bresenhamLines)
4858 													TCU_THROW(NotSupportedError, "Bresenham lines not supported");
4859 
4860 												if (getLineStippleEnable() &&
4861 													!context.getLineRasterizationFeaturesEXT().stippledBresenhamLines)
4862 													TCU_THROW(NotSupportedError, "Stippled Bresenham lines not supported");
4863 												break;
4864 											}
4865 
4866 											case VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT:
4867 											{
4868 												if (!context.getLineRasterizationFeaturesEXT().smoothLines)
4869 													TCU_THROW(NotSupportedError, "Smooth lines not supported");
4870 
4871 												if (getLineStippleEnable() &&
4872 													!context.getLineRasterizationFeaturesEXT().stippledSmoothLines)
4873 													TCU_THROW(NotSupportedError, "Stippled smooth lines not supported");
4874 												break;
4875 											}
4876 										}
4877 									}
4878 									else
4879 									{
4880 										if (m_wideness == PRIMITIVEWIDENESS_WIDE)
4881 											context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_LARGE_POINTS);
4882 									}
4883 								}
4884 
getLineStippleEnable(void) const4885 	bool					getLineStippleEnable	(void) const { return m_stipple != LINESTIPPLE_DISABLED; }
4886 
4887 protected:
4888 	const PrimitiveWideness				m_wideness;
4889 	const PrimitiveStrictness			m_strictness;
4890 	const bool							m_isLineTest;
4891 	const LineStipple					m_stipple;
4892 	const VkLineRasterizationModeEXT	m_lineRasterizationMode;
4893 	const LineStippleFactorCase			m_stippleFactor;
4894 	const deUint32						m_additionalRenderSize;
4895 };
4896 
4897 class LinesTestInstance : public BaseLineTestInstance
4898 {
4899 public:
LinesTestInstance(Context & context,PrimitiveWideness wideness,PrimitiveStrictness strictness,VkSampleCountFlagBits sampleCount,LineStipple stipple,VkLineRasterizationModeEXT lineRasterizationMode,LineStippleFactorCase stippleFactor,deUint32 additionalRenderSize=0)4900 						LinesTestInstance	(Context& context, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount, LineStipple stipple, VkLineRasterizationModeEXT lineRasterizationMode, LineStippleFactorCase stippleFactor, deUint32 additionalRenderSize = 0)
4901 							: BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_LIST, wideness, strictness, sampleCount, stipple, lineRasterizationMode, stippleFactor, additionalRenderSize)
4902 						{}
4903 
getWrongTopology(void) const4904 	VkPrimitiveTopology	getWrongTopology	(void) const override { return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; }
getRightTopology(void) const4905 	VkPrimitiveTopology	getRightTopology	(void) const override { return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; }
4906 	void				generateLines		(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) override;
4907 
4908 };
4909 
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)4910 void LinesTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
4911 {
4912 	outData.resize(8);
4913 
4914 	switch (iteration)
4915 	{
4916 		case 0:
4917 			// \note: these values are chosen arbitrarily
4918 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
4919 			outData[1] = tcu::Vec4(  0.5f,  0.2f, 0.0f, 1.0f);
4920 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
4921 			outData[3] = tcu::Vec4( -0.3f,  0.2f, 0.0f, 1.0f);
4922 			outData[4] = tcu::Vec4( -1.5f, -0.4f, 0.0f, 1.0f);
4923 			outData[5] = tcu::Vec4(  0.1f,  0.5f, 0.0f, 1.0f);
4924 			outData[6] = tcu::Vec4( 0.75f, -0.4f, 0.0f, 1.0f);
4925 			outData[7] = tcu::Vec4(  0.3f,  0.8f, 0.0f, 1.0f);
4926 			break;
4927 
4928 		case 1:
4929 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
4930 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
4931 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
4932 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
4933 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
4934 			outData[5] = tcu::Vec4(  0.18f,  -0.2f, 0.0f, 1.0f);
4935 			outData[6] = tcu::Vec4(   0.0f,   1.0f, 0.0f, 1.0f);
4936 			outData[7] = tcu::Vec4(   0.0f,  -1.0f, 0.0f, 1.0f);
4937 			break;
4938 
4939 		case 2:
4940 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
4941 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
4942 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
4943 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
4944 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
4945 			outData[5] = tcu::Vec4(  0.8f, -0.7f, 0.0f, 1.0f);
4946 			outData[6] = tcu::Vec4(  0.9f,  0.7f, 0.0f, 1.0f);
4947 			outData[7] = tcu::Vec4( -0.9f,  0.7f, 0.0f, 1.0f);
4948 			break;
4949 	}
4950 
4951 	outLines.resize(4);
4952 	outLines[0].positions[0] = outData[0];
4953 	outLines[0].positions[1] = outData[1];
4954 	outLines[1].positions[0] = outData[2];
4955 	outLines[1].positions[1] = outData[3];
4956 	outLines[2].positions[0] = outData[4];
4957 	outLines[2].positions[1] = outData[5];
4958 	outLines[3].positions[0] = outData[6];
4959 	outLines[3].positions[1] = outData[7];
4960 
4961 	// log
4962 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << getLineWidth() << ")" << tcu::TestLog::EndMessage;
4963 	for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
4964 	{
4965 		m_context.getTestContext().getLog()
4966 			<< tcu::TestLog::Message
4967 			<< "Line " << (lineNdx+1) << ":"
4968 			<< "\n\t" << outLines[lineNdx].positions[0]
4969 			<< "\n\t" << outLines[lineNdx].positions[1]
4970 			<< tcu::TestLog::EndMessage;
4971 	}
4972 }
4973 
4974 class LineStripTestInstance : public BaseLineTestInstance
4975 {
4976 public:
LineStripTestInstance(Context & context,PrimitiveWideness wideness,PrimitiveStrictness strictness,VkSampleCountFlagBits sampleCount,LineStipple stipple,VkLineRasterizationModeEXT lineRasterizationMode,LineStippleFactorCase stippleFactor,deUint32)4977 						LineStripTestInstance	(Context& context, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount, LineStipple stipple, VkLineRasterizationModeEXT lineRasterizationMode, LineStippleFactorCase stippleFactor, deUint32)
4978 							: BaseLineTestInstance(context, VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, wideness, strictness, sampleCount, stipple, lineRasterizationMode, stippleFactor)
4979 						{}
4980 
getWrongTopology(void) const4981 	VkPrimitiveTopology	getWrongTopology		(void) const override { return VK_PRIMITIVE_TOPOLOGY_LINE_LIST; }
getRightTopology(void) const4982 	VkPrimitiveTopology	getRightTopology		(void) const override { return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP; }
4983 	void				generateLines			(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) override;
4984 };
4985 
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)4986 void LineStripTestInstance::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
4987 {
4988 	outData.resize(4);
4989 
4990 	switch (iteration)
4991 	{
4992 		case 0:
4993 			// \note: these values are chosen arbitrarily
4994 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
4995 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
4996 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
4997 			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
4998 			break;
4999 
5000 		case 1:
5001 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
5002 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
5003 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
5004 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
5005 			break;
5006 
5007 		case 2:
5008 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
5009 			outData[1] = tcu::Vec4(  0.9f, -0.9f, 0.0f, 1.0f);
5010 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
5011 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
5012 			break;
5013 	}
5014 
5015 	outLines.resize(3);
5016 	outLines[0].positions[0] = outData[0];
5017 	outLines[0].positions[1] = outData[1];
5018 	outLines[1].positions[0] = outData[1];
5019 	outLines[1].positions[1] = outData[2];
5020 	outLines[2].positions[0] = outData[2];
5021 	outLines[2].positions[1] = outData[3];
5022 
5023 	// log
5024 	m_context.getTestContext().getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
5025 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
5026 	{
5027 		m_context.getTestContext().getLog()
5028 			<< tcu::TestLog::Message
5029 			<< "\t" << outData[vtxNdx]
5030 			<< tcu::TestLog::EndMessage;
5031 	}
5032 }
5033 
5034 class FillRuleTestInstance : public BaseRenderingTestInstance
5035 {
5036 public:
5037 	enum FillRuleCaseType
5038 	{
5039 		FILLRULECASE_BASIC = 0,
5040 		FILLRULECASE_REVERSED,
5041 		FILLRULECASE_CLIPPED_FULL,
5042 		FILLRULECASE_CLIPPED_PARTIAL,
5043 		FILLRULECASE_PROJECTED,
5044 
5045 		FILLRULECASE_LAST
5046 	};
5047 														FillRuleTestInstance			(Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount);
5048 	virtual tcu::TestStatus								iterate							(void);
5049 
5050 private:
5051 
5052 	virtual const VkPipelineColorBlendStateCreateInfo*	getColorBlendStateCreateInfo	(void) const;
5053 	int													getRenderSize					(FillRuleCaseType type) const;
5054 	int													getNumIterations				(FillRuleCaseType type) const;
5055 	void												generateTriangles				(int iteration, std::vector<tcu::Vec4>& outData) const;
5056 
5057 	const FillRuleCaseType								m_caseType;
5058 	int													m_iteration;
5059 	const int											m_iterationCount;
5060 	bool												m_allIterationsPassed;
5061 
5062 };
5063 
FillRuleTestInstance(Context & context,FillRuleCaseType type,VkSampleCountFlagBits sampleCount)5064 FillRuleTestInstance::FillRuleTestInstance (Context& context, FillRuleCaseType type, VkSampleCountFlagBits sampleCount)
5065 	: BaseRenderingTestInstance		(context, sampleCount, getRenderSize(type))
5066 	, m_caseType					(type)
5067 	, m_iteration					(0)
5068 	, m_iterationCount				(getNumIterations(type))
5069 	, m_allIterationsPassed			(true)
5070 {
5071 	DE_ASSERT(type < FILLRULECASE_LAST);
5072 }
5073 
iterate(void)5074 tcu::TestStatus FillRuleTestInstance::iterate (void)
5075 {
5076 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
5077 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), iterationDescription, iterationDescription);
5078 	tcu::IVec4								colorBits				= tcu::getTextureFormatBitDepth(getTextureFormat());
5079 	const int								thresholdRed			= 1 << (8 - colorBits[0]);
5080 	const int								thresholdGreen			= 1 << (8 - colorBits[1]);
5081 	const int								thresholdBlue			= 1 << (8 - colorBits[2]);
5082 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
5083 	std::vector<tcu::Vec4>					drawBuffer;
5084 
5085 	generateTriangles(m_iteration, drawBuffer);
5086 
5087 	// draw image
5088 	{
5089 		const std::vector<tcu::Vec4>	colorBuffer		(drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
5090 
5091 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
5092 
5093 		drawPrimitives(resultImage, drawBuffer, colorBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
5094 	}
5095 
5096 	// verify no overdraw
5097 	{
5098 		const tcu::RGBA	triangleColor	= tcu::RGBA(127, 127, 127, 255);
5099 		bool			overdraw		= false;
5100 
5101 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
5102 
5103 		for (int y = 0; y < resultImage.getHeight(); ++y)
5104 		for (int x = 0; x < resultImage.getWidth();  ++x)
5105 		{
5106 			const tcu::RGBA color = resultImage.getPixel(x, y);
5107 
5108 			// color values are greater than triangle color? Allow lower values for multisampled edges and background.
5109 			if ((color.getRed()   - triangleColor.getRed())   > thresholdRed   ||
5110 				(color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
5111 				(color.getBlue()  - triangleColor.getBlue())  > thresholdBlue)
5112 				overdraw = true;
5113 		}
5114 
5115 		// results
5116 		if (!overdraw)
5117 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
5118 		else
5119 		{
5120 			m_context.getTestContext().getLog()	<< tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
5121 			m_allIterationsPassed = false;
5122 		}
5123 	}
5124 
5125 	// verify no missing fragments in the full viewport case
5126 	if (m_caseType == FILLRULECASE_CLIPPED_FULL)
5127 	{
5128 		bool missingFragments = false;
5129 
5130 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
5131 
5132 		for (int y = 0; y < resultImage.getHeight(); ++y)
5133 		for (int x = 0; x < resultImage.getWidth();  ++x)
5134 		{
5135 			const tcu::RGBA color = resultImage.getPixel(x, y);
5136 
5137 			// black? (background)
5138 			if (color.getRed()   <= thresholdRed   ||
5139 				color.getGreen() <= thresholdGreen ||
5140 				color.getBlue()  <= thresholdBlue)
5141 				missingFragments = true;
5142 		}
5143 
5144 		// results
5145 		if (!missingFragments)
5146 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
5147 		else
5148 		{
5149 			m_context.getTestContext().getLog()	<< tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
5150 
5151 			m_allIterationsPassed = false;
5152 		}
5153 	}
5154 
5155 	m_context.getTestContext().getLog()	<< tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
5156 										<< tcu::TestLog::Image("Result", "Result", resultImage)
5157 										<< tcu::TestLog::EndImageSet;
5158 
5159 	// result
5160 	if (++m_iteration == m_iterationCount)
5161 	{
5162 		if (m_allIterationsPassed)
5163 			return tcu::TestStatus::pass("Pass");
5164 		else
5165 			return tcu::TestStatus::fail("Found invalid pixels");
5166 	}
5167 	else
5168 		return tcu::TestStatus::incomplete();
5169 }
5170 
getRenderSize(FillRuleCaseType type) const5171 int FillRuleTestInstance::getRenderSize (FillRuleCaseType type) const
5172 {
5173 	if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
5174 		return RESOLUTION_POT / 4;
5175 	else
5176 		return RESOLUTION_POT;
5177 }
5178 
getNumIterations(FillRuleCaseType type) const5179 int FillRuleTestInstance::getNumIterations (FillRuleCaseType type) const
5180 {
5181 	if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
5182 		return 15;
5183 	else
5184 		return 2;
5185 }
5186 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData) const5187 void FillRuleTestInstance::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
5188 {
5189 	switch (m_caseType)
5190 	{
5191 		case FILLRULECASE_BASIC:
5192 		case FILLRULECASE_REVERSED:
5193 		case FILLRULECASE_PROJECTED:
5194 		{
5195 			const int	numRows		= 4;
5196 			const int	numColumns	= 4;
5197 			const float	quadSide	= 0.15f;
5198 			de::Random	rnd			(0xabcd);
5199 
5200 			outData.resize(6 * numRows * numColumns);
5201 
5202 			for (int col = 0; col < numColumns; ++col)
5203 			for (int row = 0; row < numRows;    ++row)
5204 			{
5205 				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);
5206 				const float		rotation	= (float)(iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
5207 				const tcu::Vec2 sideH		= quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
5208 				const tcu::Vec2 sideV		= tcu::Vec2(sideH.y(), -sideH.x());
5209 				const tcu::Vec2 quad[4]		=
5210 				{
5211 					center + sideH + sideV,
5212 					center + sideH - sideV,
5213 					center - sideH - sideV,
5214 					center - sideH + sideV,
5215 				};
5216 
5217 				if (m_caseType == FILLRULECASE_BASIC)
5218 				{
5219 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
5220 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
5221 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
5222 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
5223 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
5224 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
5225 				}
5226 				else if (m_caseType == FILLRULECASE_REVERSED)
5227 				{
5228 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
5229 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
5230 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
5231 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
5232 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
5233 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
5234 				}
5235 				else if (m_caseType == FILLRULECASE_PROJECTED)
5236 				{
5237 					const float w0 = rnd.getFloat(0.1f, 4.0f);
5238 					const float w1 = rnd.getFloat(0.1f, 4.0f);
5239 					const float w2 = rnd.getFloat(0.1f, 4.0f);
5240 					const float w3 = rnd.getFloat(0.1f, 4.0f);
5241 
5242 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
5243 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
5244 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
5245 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
5246 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
5247 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
5248 				}
5249 				else
5250 					DE_ASSERT(DE_FALSE);
5251 			}
5252 
5253 			break;
5254 		}
5255 
5256 		case FILLRULECASE_CLIPPED_PARTIAL:
5257 		case FILLRULECASE_CLIPPED_FULL:
5258 		{
5259 			const float		quadSide	= (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
5260 			const tcu::Vec2 center		= (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
5261 			const float		rotation	= (float)(iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
5262 			const tcu::Vec2 sideH		= quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
5263 			const tcu::Vec2 sideV		= tcu::Vec2(sideH.y(), -sideH.x());
5264 			const tcu::Vec2 quad[4]		=
5265 			{
5266 				center + sideH + sideV,
5267 				center + sideH - sideV,
5268 				center - sideH - sideV,
5269 				center - sideH + sideV,
5270 			};
5271 
5272 			outData.resize(6);
5273 			outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
5274 			outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
5275 			outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
5276 			outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
5277 			outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
5278 			outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
5279 			break;
5280 		}
5281 
5282 		default:
5283 			DE_ASSERT(DE_FALSE);
5284 	}
5285 }
5286 
getColorBlendStateCreateInfo(void) const5287 const VkPipelineColorBlendStateCreateInfo* FillRuleTestInstance::getColorBlendStateCreateInfo (void) const
5288 {
5289 	static const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
5290 	{
5291 		true,														// VkBool32			blendEnable;
5292 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendColor;
5293 		VK_BLEND_FACTOR_ONE,										// VkBlend			destBlendColor;
5294 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpColor;
5295 		VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendAlpha;
5296 		VK_BLEND_FACTOR_ONE,										// VkBlend			destBlendAlpha;
5297 		VK_BLEND_OP_ADD,											// VkBlendOp		blendOpAlpha;
5298 		(VK_COLOR_COMPONENT_R_BIT |
5299 		 VK_COLOR_COMPONENT_G_BIT |
5300 		 VK_COLOR_COMPONENT_B_BIT |
5301 		 VK_COLOR_COMPONENT_A_BIT)									// VkChannelFlags	channelWriteMask;
5302 	};
5303 
5304 	static const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
5305 	{
5306 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
5307 		DE_NULL,													// const void*									pNext;
5308 		0,															// VkPipelineColorBlendStateCreateFlags			flags;
5309 		false,														// VkBool32										logicOpEnable;
5310 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
5311 		1u,															// deUint32										attachmentCount;
5312 		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
5313 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
5314 	};
5315 
5316 	return &colorBlendStateParams;
5317 }
5318 
5319 
5320 class FillRuleTestCase : public BaseRenderingTestCase
5321 {
5322 public:
FillRuleTestCase(tcu::TestContext & context,const std::string & name,FillRuleTestInstance::FillRuleCaseType type,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)5323 								FillRuleTestCase	(tcu::TestContext& context, const std::string& name, FillRuleTestInstance::FillRuleCaseType type, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
5324 									: BaseRenderingTestCase	(context, name, sampleCount)
5325 									, m_type				(type)
5326 								{}
5327 
createInstance(Context & context) const5328 	virtual TestInstance*		createInstance		(Context& context) const
5329 								{
5330 									return new FillRuleTestInstance(context, m_type, m_sampleCount);
5331 								}
5332 protected:
5333 	const FillRuleTestInstance::FillRuleCaseType m_type;
5334 };
5335 
5336 class CullingTestInstance : public BaseRenderingTestInstance
5337 {
5338 public:
CullingTestInstance(Context & context,VkCullModeFlags cullMode,VkPrimitiveTopology primitiveTopology,VkFrontFace frontFace,VkPolygonMode polygonMode)5339 													CullingTestInstance				(Context& context, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkPolygonMode polygonMode)
5340 														: BaseRenderingTestInstance		(context, VK_SAMPLE_COUNT_1_BIT, RESOLUTION_POT)
5341 														, m_cullMode					(cullMode)
5342 														, m_primitiveTopology			(primitiveTopology)
5343 														, m_frontFace					(frontFace)
5344 														, m_polygonMode					(polygonMode)
5345 														, m_multisampling				(true)
5346 													{}
5347 	virtual
5348 	const VkPipelineRasterizationStateCreateInfo*	getRasterizationStateCreateInfo (void) const;
5349 
5350 	tcu::TestStatus									iterate							(void);
5351 
5352 private:
5353 	void											generateVertices				(std::vector<tcu::Vec4>& outData) const;
5354 	void											extractTriangles				(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
5355 	void											extractLines					(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<LineSceneSpec::SceneLine>& outLines) const;
5356 	void											extractPoints					(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, std::vector<PointSceneSpec::ScenePoint>& outPoints) const;
5357 	bool											triangleOrder					(const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
5358 
5359 	const VkCullModeFlags							m_cullMode;
5360 	const VkPrimitiveTopology						m_primitiveTopology;
5361 	const VkFrontFace								m_frontFace;
5362 	const VkPolygonMode								m_polygonMode;
5363 	const bool										m_multisampling;
5364 };
5365 
5366 
iterate(void)5367 tcu::TestStatus CullingTestInstance::iterate (void)
5368 {
5369 	DE_ASSERT(m_polygonMode <= VK_POLYGON_MODE_POINT);
5370 
5371 	tcu::Surface									resultImage						(m_renderSize, m_renderSize);
5372 	std::vector<tcu::Vec4>							drawBuffer;
5373 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
5374 	std::vector<PointSceneSpec::ScenePoint>			points;
5375 	std::vector<LineSceneSpec::SceneLine>			lines;
5376 
5377 	const InstanceInterface&						vk				= m_context.getInstanceInterface();
5378 	const VkPhysicalDevice							physicalDevice	= m_context.getPhysicalDevice();
5379 	const VkPhysicalDeviceFeatures					deviceFeatures	= getPhysicalDeviceFeatures(vk, physicalDevice);
5380 
5381 	if (!(deviceFeatures.fillModeNonSolid) && (m_polygonMode == VK_POLYGON_MODE_LINE || m_polygonMode == VK_POLYGON_MODE_POINT))
5382 		TCU_THROW(NotSupportedError, "Wireframe fill modes are not supported");
5383 
5384 	// generate scene
5385 	generateVertices(drawBuffer);
5386 	extractTriangles(triangles, drawBuffer);
5387 
5388 	if (m_polygonMode == VK_POLYGON_MODE_LINE)
5389 		extractLines(triangles ,lines);
5390 	else if (m_polygonMode == VK_POLYGON_MODE_POINT)
5391 		extractPoints(triangles, points);
5392 
5393 	// draw image
5394 	{
5395 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting front face to " << m_frontFace << tcu::TestLog::EndMessage;
5396 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Setting cull face to " << m_cullMode << tcu::TestLog::EndMessage;
5397 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Drawing test pattern (" << m_primitiveTopology << ")" << tcu::TestLog::EndMessage;
5398 
5399 		drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
5400 	}
5401 
5402 	// compare
5403 	{
5404 		RasterizationArguments	args;
5405 		tcu::IVec4				colorBits	= tcu::getTextureFormatBitDepth(getTextureFormat());
5406 		bool					isCompareOk	= false;
5407 
5408 		args.numSamples		= m_multisampling ? 1 : 0;
5409 		args.subpixelBits	= m_subpixelBits;
5410 		args.redBits		= colorBits[0];
5411 		args.greenBits		= colorBits[1];
5412 		args.blueBits		= colorBits[2];
5413 
5414 		switch (m_polygonMode)
5415 		{
5416 			case VK_POLYGON_MODE_LINE:
5417 			{
5418 				LineSceneSpec scene;
5419 				scene.lineWidth = 0;
5420 				scene.lines.swap(lines);
5421 				isCompareOk = verifyLineGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
5422 				break;
5423 			}
5424 			case VK_POLYGON_MODE_POINT:
5425 			{
5426 				PointSceneSpec scene;
5427 				scene.points.swap(points);
5428 				isCompareOk = verifyPointGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog());
5429 				break;
5430 			}
5431 			default:
5432 			{
5433 				TriangleSceneSpec scene;
5434 				scene.triangles.swap(triangles);
5435 				isCompareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_context.getTestContext().getLog(), tcu::VERIFICATIONMODE_WEAK);
5436 				break;
5437 			}
5438 		}
5439 
5440 		if (isCompareOk)
5441 			return tcu::TestStatus::pass("Pass");
5442 		else
5443 			return tcu::TestStatus::fail("Incorrect rendering");
5444 	}
5445 }
5446 
generateVertices(std::vector<tcu::Vec4> & outData) const5447 void CullingTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
5448 {
5449 	de::Random rnd(543210);
5450 
5451 	outData.resize(6);
5452 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
5453 	{
5454 		outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
5455 		outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
5456 		outData[vtxNdx].z() = 0.0f;
5457 		outData[vtxNdx].w() = 1.0f;
5458 	}
5459 }
5460 
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices) const5461 void CullingTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
5462 {
5463 	const bool cullDirection = (m_cullMode == VK_CULL_MODE_FRONT_BIT) ^ (m_frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE);
5464 
5465 	// No triangles
5466 	if (m_cullMode == VK_CULL_MODE_FRONT_AND_BACK)
5467 		return;
5468 
5469 	switch (m_primitiveTopology)
5470 	{
5471 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
5472 		{
5473 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
5474 			{
5475 				const tcu::Vec4& v0 = vertices[vtxNdx + 0];
5476 				const tcu::Vec4& v1 = vertices[vtxNdx + 1];
5477 				const tcu::Vec4& v2 = vertices[vtxNdx + 2];
5478 
5479 				if (triangleOrder(v0, v1, v2) != cullDirection)
5480 				{
5481 					TriangleSceneSpec::SceneTriangle tri;
5482 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
5483 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
5484 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
5485 
5486 					outTriangles.push_back(tri);
5487 				}
5488 			}
5489 			break;
5490 		}
5491 
5492 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
5493 		{
5494 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
5495 			{
5496 				const tcu::Vec4& v0 = vertices[vtxNdx + 0];
5497 				const tcu::Vec4& v1 = vertices[vtxNdx + 1];
5498 				const tcu::Vec4& v2 = vertices[vtxNdx + 2];
5499 
5500 				if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
5501 				{
5502 					TriangleSceneSpec::SceneTriangle tri;
5503 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
5504 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
5505 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
5506 
5507 					outTriangles.push_back(tri);
5508 				}
5509 			}
5510 			break;
5511 		}
5512 
5513 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
5514 		{
5515 			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
5516 			{
5517 				const tcu::Vec4& v0 = vertices[0];
5518 				const tcu::Vec4& v1 = vertices[vtxNdx + 0];
5519 				const tcu::Vec4& v2 = vertices[vtxNdx + 1];
5520 
5521 				if (triangleOrder(v0, v1, v2) != cullDirection)
5522 				{
5523 					TriangleSceneSpec::SceneTriangle tri;
5524 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
5525 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
5526 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
5527 
5528 					outTriangles.push_back(tri);
5529 				}
5530 			}
5531 			break;
5532 		}
5533 
5534 		default:
5535 			DE_ASSERT(false);
5536 	}
5537 }
5538 
extractLines(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,std::vector<LineSceneSpec::SceneLine> & outLines) const5539 void CullingTestInstance::extractLines (std::vector<TriangleSceneSpec::SceneTriangle>&	outTriangles,
5540 										std::vector<LineSceneSpec::SceneLine>&			outLines) const
5541 {
5542 	for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
5543 	{
5544 		for (int vrtxNdx = 0; vrtxNdx < 2; ++vrtxNdx)
5545 		{
5546 			LineSceneSpec::SceneLine line;
5547 			line.positions[0] = outTriangles.at(triNdx).positions[vrtxNdx];
5548 			line.positions[1] = outTriangles.at(triNdx).positions[vrtxNdx + 1];
5549 
5550 			outLines.push_back(line);
5551 		}
5552 		LineSceneSpec::SceneLine line;
5553 		line.positions[0] = outTriangles.at(triNdx).positions[2];
5554 		line.positions[1] = outTriangles.at(triNdx).positions[0];
5555 		outLines.push_back(line);
5556 	}
5557 }
5558 
extractPoints(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,std::vector<PointSceneSpec::ScenePoint> & outPoints) const5559 void CullingTestInstance::extractPoints (std::vector<TriangleSceneSpec::SceneTriangle>	&outTriangles,
5560 										std::vector<PointSceneSpec::ScenePoint>			&outPoints) const
5561 {
5562 	for (int triNdx = 0; triNdx < (int)outTriangles.size(); ++triNdx)
5563 	{
5564 		for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
5565 		{
5566 			PointSceneSpec::ScenePoint point;
5567 			point.position = outTriangles.at(triNdx).positions[vrtxNdx];
5568 			point.pointSize = 1.0f;
5569 
5570 			outPoints.push_back(point);
5571 		}
5572 	}
5573 }
5574 
triangleOrder(const tcu::Vec4 & v0,const tcu::Vec4 & v1,const tcu::Vec4 & v2) const5575 bool CullingTestInstance::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
5576 {
5577 	const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
5578 	const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
5579 	const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
5580 
5581 	// cross
5582 	return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) > 0;
5583 }
5584 
5585 
getRasterizationStateCreateInfo(void) const5586 const VkPipelineRasterizationStateCreateInfo* CullingTestInstance::getRasterizationStateCreateInfo (void) const
5587 {
5588 	static VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
5589 	{
5590 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
5591 		DE_NULL,														// const void*								pNext;
5592 		0,																// VkPipelineRasterizationStateCreateFlags	flags;
5593 		false,															// VkBool32									depthClipEnable;
5594 		false,															// VkBool32									rasterizerDiscardEnable;
5595 		VK_POLYGON_MODE_FILL,											// VkFillMode								fillMode;
5596 		VK_CULL_MODE_NONE,												// VkCullMode								cullMode;
5597 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
5598 		VK_FALSE,														// VkBool32									depthBiasEnable;
5599 		0.0f,															// float									depthBias;
5600 		0.0f,															// float									depthBiasClamp;
5601 		0.0f,															// float									slopeScaledDepthBias;
5602 		getLineWidth(),													// float									lineWidth;
5603 	};
5604 
5605 	rasterizationStateCreateInfo.lineWidth		= getLineWidth();
5606 	rasterizationStateCreateInfo.cullMode		= m_cullMode;
5607 	rasterizationStateCreateInfo.frontFace		= m_frontFace;
5608 	rasterizationStateCreateInfo.polygonMode	= m_polygonMode;
5609 
5610 	return &rasterizationStateCreateInfo;
5611 }
5612 
5613 class CullingTestCase : public BaseRenderingTestCase
5614 {
5615 public:
CullingTestCase(tcu::TestContext & context,const std::string & name,VkCullModeFlags cullMode,VkPrimitiveTopology primitiveTopology,VkFrontFace frontFace,VkPolygonMode polygonMode,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)5616 								CullingTestCase		(tcu::TestContext& context, const std::string& name, VkCullModeFlags cullMode, VkPrimitiveTopology primitiveTopology, VkFrontFace frontFace, VkPolygonMode polygonMode, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
5617 									: BaseRenderingTestCase	(context, name, sampleCount)
5618 									, m_cullMode			(cullMode)
5619 									, m_primitiveTopology	(primitiveTopology)
5620 									, m_frontFace			(frontFace)
5621 									, m_polygonMode			(polygonMode)
5622 								{}
5623 
createInstance(Context & context) const5624 	virtual TestInstance*		createInstance		(Context& context) const
5625 								{
5626 									return new CullingTestInstance(context, m_cullMode, m_primitiveTopology, m_frontFace, m_polygonMode);
5627 								}
5628 	void						checkSupport		(Context& context) const;
5629 protected:
5630 	const VkCullModeFlags		m_cullMode;
5631 	const VkPrimitiveTopology	m_primitiveTopology;
5632 	const VkFrontFace			m_frontFace;
5633 	const VkPolygonMode			m_polygonMode;
5634 };
5635 
checkSupport(Context & context) const5636 void CullingTestCase::checkSupport (Context& context) const
5637 {
5638 #ifndef CTS_USES_VULKANSC
5639 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset"))
5640 	{
5641 		const VkPhysicalDevicePortabilitySubsetFeaturesKHR& subsetFeatures = context.getPortabilitySubsetFeatures();
5642 		if (m_polygonMode == VK_POLYGON_MODE_POINT && !subsetFeatures.pointPolygons)
5643 			TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Point polygons are not supported by this implementation");
5644 		if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN && !subsetFeatures.triangleFans)
5645 			TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
5646 	}
5647 #else
5648 	DE_UNREF(context);
5649 #endif // CTS_USES_VULKANSC
5650 }
5651 
5652 class DiscardTestInstance : public BaseRenderingTestInstance
5653 {
5654 public:
DiscardTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,deBool queryFragmentShaderInvocations)5655 															DiscardTestInstance					(Context& context, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations)
5656 																: BaseRenderingTestInstance			(context, VK_SAMPLE_COUNT_1_BIT, RESOLUTION_POT)
5657 																, m_primitiveTopology				(primitiveTopology)
5658 																, m_queryFragmentShaderInvocations	(queryFragmentShaderInvocations)
5659 															{}
5660 
5661 	virtual const VkPipelineRasterizationStateCreateInfo*	getRasterizationStateCreateInfo		(void) const;
5662 	tcu::TestStatus											iterate								(void);
5663 
5664 private:
5665 	void													generateVertices					(std::vector<tcu::Vec4>& outData) const;
5666 	void													extractTriangles					(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
5667 	void													extractLines						(std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const;
5668 	void													extractPoints						(std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const;
5669 	void													drawPrimitivesDiscard				(tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool);
5670 
5671 	const VkPrimitiveTopology								m_primitiveTopology;
5672 	const deBool											m_queryFragmentShaderInvocations;
5673 };
5674 
iterate(void)5675 tcu::TestStatus DiscardTestInstance::iterate (void)
5676 {
5677 	const DeviceInterface&							vkd			= m_context.getDeviceInterface();
5678 	const VkDevice									vkDevice	= m_context.getDevice();
5679 	deUint64										queryResult	= 0u;
5680 	tcu::Surface									resultImage	(m_renderSize, m_renderSize);
5681 	std::vector<tcu::Vec4>							drawBuffer;
5682 	std::vector<PointSceneSpec::ScenePoint>			points;
5683 	std::vector<LineSceneSpec::SceneLine>			lines;
5684 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
5685 
5686 	generateVertices(drawBuffer);
5687 
5688 	switch (m_primitiveTopology)
5689 	{
5690 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
5691 			extractPoints(points, drawBuffer);
5692 			break;
5693 
5694 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
5695 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
5696 			extractLines(lines, drawBuffer);
5697 			break;
5698 
5699 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
5700 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
5701 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
5702 			extractTriangles(triangles, drawBuffer);
5703 			break;
5704 
5705 		default:
5706 			DE_ASSERT(false);
5707 	}
5708 
5709 	const VkQueryPoolCreateInfo queryPoolCreateInfo =
5710 	{
5711 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,						// VkStructureType					sType
5712 		DE_NULL,														// const void*						pNext
5713 		(VkQueryPoolCreateFlags)0,										// VkQueryPoolCreateFlags			flags
5714 		VK_QUERY_TYPE_PIPELINE_STATISTICS ,								// VkQueryType						queryType
5715 		1u,																// deUint32							entryCount
5716 		VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT,	// VkQueryPipelineStatisticFlags	pipelineStatistics
5717 	};
5718 
5719 	if (m_queryFragmentShaderInvocations)
5720 	{
5721 		Move<VkQueryPool> queryPool	= createQueryPool(vkd, vkDevice, &queryPoolCreateInfo);
5722 
5723 		drawPrimitivesDiscard(resultImage, drawBuffer, m_primitiveTopology, queryPool);
5724 		vkd.getQueryPoolResults(vkDevice, *queryPool, 0u, 1u, sizeof(deUint64), &queryResult, 0u, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
5725 	}
5726 	else
5727 		BaseRenderingTestInstance::drawPrimitives(resultImage, drawBuffer, m_primitiveTopology);
5728 
5729 	// compare
5730 	{
5731 		tcu::IVec4						colorBits	= tcu::getTextureFormatBitDepth(getTextureFormat());
5732 
5733 		const RasterizationArguments	args		=
5734 		{
5735 			0,							// int	numSamples;
5736 			(int)m_subpixelBits,		// int	subpixelBits;
5737 			colorBits[0],				// int	redBits;
5738 			colorBits[1],				// int	greenBits;
5739 			colorBits[2]				// int	blueBits;
5740 		};
5741 
5742 		// Empty scene to compare to, primitives should be discarded before rasterization
5743 		TriangleSceneSpec				scene;
5744 
5745 		const bool						isCompareOk	= verifyTriangleGroupRasterization(resultImage,
5746 																					   scene,
5747 																					   args,
5748 																					   m_context.getTestContext().getLog(),
5749 																					   tcu::VERIFICATIONMODE_STRICT);
5750 
5751 		if (isCompareOk)
5752 		{
5753 			if (m_queryFragmentShaderInvocations && queryResult > 0u)
5754 				return tcu::TestStatus::fail("Fragment shader invocations occured");
5755 			else
5756 				return tcu::TestStatus::pass("Pass");
5757 		}
5758 		else
5759 			return tcu::TestStatus::fail("Incorrect rendering");
5760 	}
5761 }
5762 
generateVertices(std::vector<tcu::Vec4> & outData) const5763 void DiscardTestInstance::generateVertices (std::vector<tcu::Vec4>& outData) const
5764 {
5765 	de::Random rnd(12345);
5766 
5767 	outData.resize(6);
5768 
5769 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
5770 	{
5771 		outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
5772 		outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
5773 		outData[vtxNdx].z() = 0.0f;
5774 		outData[vtxNdx].w() = 1.0f;
5775 	}
5776 }
5777 
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices) const5778 void DiscardTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
5779 {
5780 	switch (m_primitiveTopology)
5781 	{
5782 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
5783 		{
5784 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
5785 			{
5786 				TriangleSceneSpec::SceneTriangle	tri;
5787 				const tcu::Vec4&					v0	= vertices[vtxNdx + 0];
5788 				const tcu::Vec4&					v1	= vertices[vtxNdx + 1];
5789 				const tcu::Vec4&					v2	= vertices[vtxNdx + 2];
5790 
5791 				tri.positions[0] = v0;
5792 				tri.positions[1] = v1;
5793 				tri.positions[2] = v2;
5794 
5795 				outTriangles.push_back(tri);
5796 			}
5797 
5798 			break;
5799 		}
5800 
5801 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
5802 		{
5803 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
5804 			{
5805 				TriangleSceneSpec::SceneTriangle	tri;
5806 				const tcu::Vec4&					v0	= vertices[vtxNdx + 0];
5807 				const tcu::Vec4&					v1	= vertices[vtxNdx + 1];
5808 				const tcu::Vec4&					v2	= vertices[vtxNdx + 2];
5809 
5810 				tri.positions[0] = v0;
5811 				tri.positions[1] = v1;
5812 				tri.positions[2] = v2;
5813 
5814 				outTriangles.push_back(tri);
5815 			}
5816 
5817 			break;
5818 		}
5819 
5820 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
5821 		{
5822 			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
5823 			{
5824 				TriangleSceneSpec::SceneTriangle	tri;
5825 				const tcu::Vec4&					v0	= vertices[0];
5826 				const tcu::Vec4&					v1	= vertices[vtxNdx + 0];
5827 				const tcu::Vec4&					v2	= vertices[vtxNdx + 1];
5828 
5829 				tri.positions[0] = v0;
5830 				tri.positions[1] = v1;
5831 				tri.positions[2] = v2;
5832 
5833 				outTriangles.push_back(tri);
5834 			}
5835 
5836 			break;
5837 		}
5838 
5839 		default:
5840 			DE_ASSERT(false);
5841 	}
5842 }
5843 
extractLines(std::vector<LineSceneSpec::SceneLine> & outLines,const std::vector<tcu::Vec4> & vertices) const5844 void DiscardTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices) const
5845 {
5846 	switch (m_primitiveTopology)
5847 	{
5848 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
5849 		{
5850 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
5851 			{
5852 				LineSceneSpec::SceneLine line;
5853 
5854 				line.positions[0] = vertices[vtxNdx + 0];
5855 				line.positions[1] = vertices[vtxNdx + 1];
5856 
5857 				outLines.push_back(line);
5858 			}
5859 
5860 			break;
5861 		}
5862 
5863 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
5864 		{
5865 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
5866 			{
5867 				LineSceneSpec::SceneLine line;
5868 
5869 				line.positions[0] = vertices[vtxNdx + 0];
5870 				line.positions[1] = vertices[vtxNdx + 1];
5871 
5872 				outLines.push_back(line);
5873 			}
5874 
5875 			break;
5876 		}
5877 
5878 		default:
5879 			DE_ASSERT(false);
5880 		}
5881 }
5882 
extractPoints(std::vector<PointSceneSpec::ScenePoint> & outPoints,const std::vector<tcu::Vec4> & vertices) const5883 void DiscardTestInstance::extractPoints (std::vector<PointSceneSpec::ScenePoint>& outPoints, const std::vector<tcu::Vec4>& vertices) const
5884 {
5885 	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
5886 	{
5887 		for (int vrtxNdx = 0; vrtxNdx < 3; ++vrtxNdx)
5888 		{
5889 			PointSceneSpec::ScenePoint point;
5890 
5891 			point.position	= vertices[vrtxNdx];
5892 			point.pointSize	= 1.0f;
5893 
5894 			outPoints.push_back(point);
5895 		}
5896 	}
5897 }
5898 
getRasterizationStateCreateInfo(void) const5899 const VkPipelineRasterizationStateCreateInfo* DiscardTestInstance::getRasterizationStateCreateInfo (void) const
5900 {
5901 	static const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
5902 	{
5903 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType;
5904 		NULL,														// const void*								pNext;
5905 		0,															// VkPipelineRasterizationStateCreateFlags	flags;
5906 		VK_FALSE,													// VkBool32									depthClipEnable;
5907 		VK_TRUE,													// VkBool32									rasterizerDiscardEnable;
5908 		VK_POLYGON_MODE_FILL,										// VkFillMode								fillMode;
5909 		VK_CULL_MODE_NONE,											// VkCullMode								cullMode;
5910 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace;
5911 		VK_FALSE,													// VkBool32									depthBiasEnable;
5912 		0.0f,														// float									depthBias;
5913 		0.0f,														// float									depthBiasClamp;
5914 		0.0f,														// float									slopeScaledDepthBias;
5915 		getLineWidth(),												// float									lineWidth;
5916 	};
5917 
5918 	return &rasterizationStateCreateInfo;
5919 }
5920 
drawPrimitivesDiscard(tcu::Surface & result,const std::vector<tcu::Vec4> & positionData,VkPrimitiveTopology primitiveTopology,Move<VkQueryPool> & queryPool)5921 void DiscardTestInstance::drawPrimitivesDiscard (tcu::Surface& result, const std::vector<tcu::Vec4>& positionData, VkPrimitiveTopology primitiveTopology, Move<VkQueryPool>& queryPool)
5922 {
5923 	const DeviceInterface&				vkd					= m_context.getDeviceInterface();
5924 	const VkDevice						vkDevice			= m_context.getDevice();
5925 	const VkPhysicalDeviceProperties	properties			= m_context.getDeviceProperties();
5926 	const VkQueue						queue				= m_context.getUniversalQueue();
5927 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
5928 	Allocator&							allocator			= m_context.getDefaultAllocator();
5929 
5930 	const size_t						attributeBatchSize	= positionData.size() * sizeof(tcu::Vec4);
5931 	const VkDeviceSize					vertexBufferOffset	= 0;
5932 	de::MovePtr<Allocation>				vertexBufferMemory;
5933 	Move<VkBuffer>						vertexBuffer;
5934 	Move<VkCommandBuffer>				commandBuffer;
5935 	Move<VkPipeline>					graphicsPipeline;
5936 
5937 	if (attributeBatchSize > properties.limits.maxVertexInputAttributeOffset)
5938 	{
5939 		std::stringstream message;
5940 		message << "Larger vertex input attribute offset is needed (" << attributeBatchSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
5941 		TCU_THROW(NotSupportedError, message.str().c_str());
5942 	}
5943 
5944 	// Create Graphics Pipeline
5945 	{
5946 		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
5947 		{
5948 			0u,										// deUint32					binding;
5949 			sizeof(tcu::Vec4),						// deUint32					strideInBytes;
5950 			VK_VERTEX_INPUT_RATE_VERTEX				// VkVertexInputStepRate	stepRate;
5951 		};
5952 
5953 		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[2]	=
5954 		{
5955 			{
5956 				0u,									// deUint32	location;
5957 				0u,									// deUint32	binding;
5958 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
5959 				0u									// deUint32	offsetInBytes;
5960 			},
5961 			{
5962 				1u,									// deUint32	location;
5963 				0u,									// deUint32	binding;
5964 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
5965 				(deUint32)attributeBatchSize		// deUint32	offsetInBytes;
5966 			}
5967 		};
5968 
5969 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
5970 		{
5971 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
5972 			DE_NULL,													// const void*								pNext;
5973 			0,															// VkPipelineVertexInputStateCreateFlags	flags;
5974 			1u,															// deUint32									bindingCount;
5975 			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
5976 			2u,															// deUint32									attributeCount;
5977 			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
5978 		};
5979 
5980 		const std::vector<VkViewport>				viewports							(1, makeViewport(tcu::UVec2(m_renderSize)));
5981 		const std::vector<VkRect2D>					scissors							(1, makeRect2D(tcu::UVec2(m_renderSize)));
5982 
5983 		const VkPipelineMultisampleStateCreateInfo	multisampleStateParams				=
5984 		{
5985 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
5986 			DE_NULL,													// const void*								pNext;
5987 			0u,															// VkPipelineMultisampleStateCreateFlags	flags;
5988 			m_sampleCount,												// VkSampleCountFlagBits					rasterizationSamples;
5989 			VK_FALSE,													// VkBool32									sampleShadingEnable;
5990 			0.0f,														// float									minSampleShading;
5991 			DE_NULL,													// const VkSampleMask*						pSampleMask;
5992 			VK_FALSE,													// VkBool32									alphaToCoverageEnable;
5993 			VK_FALSE													// VkBool32									alphaToOneEnable;
5994 		};
5995 
5996 		const VkPipelineRasterizationStateCreateInfo* rasterizationStateInfo = getRasterizationStateCreateInfo();
5997 
5998 		graphicsPipeline = makeGraphicsPipeline(vkd,								// const DeviceInterface&							vk
5999 												vkDevice,							// const VkDevice									device
6000 												*m_pipelineLayout,					// const VkPipelineLayout							pipelineLayout
6001 												*m_vertexShaderModule,				// const VkShaderModule								vertexShaderModule
6002 												DE_NULL,							// const VkShaderModule								tessellationControlShaderModule
6003 												DE_NULL,							// const VkShaderModule								tessellationEvalShaderModule
6004 												DE_NULL,							// const VkShaderModule								geometryShaderModule
6005 												rasterizationStateInfo->rasterizerDiscardEnable ? DE_NULL : *m_fragmentShaderModule,
6006 																					// const VkShaderModule								fragmentShaderModule
6007 												*m_renderPass,						// const VkRenderPass								renderPass
6008 												viewports,							// const std::vector<VkViewport>&					viewports
6009 												scissors,							// const std::vector<VkRect2D>&						scissors
6010 												primitiveTopology,					// const VkPrimitiveTopology						topology
6011 												0u,									// const deUint32									subpass
6012 												0u,									// const deUint32									patchControlPoints
6013 												&vertexInputStateParams,			// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
6014 												rasterizationStateInfo,				// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
6015 												&multisampleStateParams,			// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
6016 												DE_NULL,							// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo,
6017 												getColorBlendStateCreateInfo());	// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
6018 	}
6019 
6020 	// Create Vertex Buffer
6021 	{
6022 		const VkBufferCreateInfo					vertexBufferParams		=
6023 		{
6024 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType;
6025 			DE_NULL,								// const void*			pNext;
6026 			0u,										// VkBufferCreateFlags	flags;
6027 			attributeBatchSize * 2,					// VkDeviceSize			size;
6028 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,		// VkBufferUsageFlags	usage;
6029 			VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode;
6030 			1u,										// deUint32				queueFamilyCount;
6031 			&queueFamilyIndex						// const deUint32*		pQueueFamilyIndices;
6032 		};
6033 
6034 		const std::vector<tcu::Vec4>				colorData				(positionData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
6035 
6036 		vertexBuffer		= createBuffer(vkd, vkDevice, &vertexBufferParams);
6037 		vertexBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
6038 
6039 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
6040 
6041 		// Load vertices into vertex buffer
6042 		deMemcpy(vertexBufferMemory->getHostPtr(), positionData.data(), attributeBatchSize);
6043 		deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) + attributeBatchSize, colorData.data(), attributeBatchSize);
6044 		flushAlloc(vkd, vkDevice, *vertexBufferMemory);
6045 	}
6046 
6047 	// Create Command Buffer
6048 	commandBuffer = allocateCommandBuffer(vkd, vkDevice, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
6049 
6050 	// Begin Command Buffer
6051 	beginCommandBuffer(vkd, *commandBuffer);
6052 
6053 	addImageTransitionBarrier(*commandBuffer,									// VkCommandBuffer			commandBuffer
6054 							  *m_image,											// VkImage					image
6055 							  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags		srcStageMask
6056 							  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,				// VkPipelineStageFlags		dstStageMask
6057 							  0,												// VkAccessFlags			srcAccessMask
6058 							  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask
6059 							  VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
6060 							  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);		// VkImageLayout			newLayout;
6061 
6062 	if (m_multisampling)
6063 	{
6064 		addImageTransitionBarrier(*commandBuffer,								// VkCommandBuffer			commandBuffer
6065 								  *m_resolvedImage,								// VkImage					image
6066 								  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,			// VkPipelineStageFlags		srcStageMask
6067 								  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,			// VkPipelineStageFlags		dstStageMask
6068 								  0,											// VkAccessFlags			srcAccessMask
6069 								  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			dstAccessMask
6070 								  VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			oldLayout;
6071 								  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);	// VkImageLayout			newLayout;
6072 	}
6073 
6074 	// Reset query pool
6075 	vkd.cmdResetQueryPool(*commandBuffer, *queryPool, 0u, 1u);
6076 
6077 	// Begin render pass and start query
6078 	beginRenderPass(vkd, *commandBuffer, *m_renderPass, *m_frameBuffer, vk::makeRect2D(0, 0, m_renderSize, m_renderSize), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
6079 	vkd.cmdBeginQuery(*commandBuffer, *queryPool, 0u, (VkQueryControlFlags)0u);
6080 	vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
6081 	vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1, &m_descriptorSet.get(), 0u, DE_NULL);
6082 	vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
6083 	vkd.cmdDraw(*commandBuffer, (deUint32)positionData.size(), 1, 0, 0);
6084 	endRenderPass(vkd, *commandBuffer);
6085 	vkd.cmdEndQuery(*commandBuffer, *queryPool, 0u);
6086 
6087 	// Copy Image
6088 	copyImageToBuffer(vkd, *commandBuffer, m_multisampling ? *m_resolvedImage : *m_image, *m_resultBuffer, tcu::IVec2(m_renderSize, m_renderSize));
6089 
6090 	endCommandBuffer(vkd, *commandBuffer);
6091 
6092 	// Set Point Size
6093 	{
6094 		float pointSize = getPointSize();
6095 
6096 		deMemcpy(m_uniformBufferMemory->getHostPtr(), &pointSize, (size_t)m_uniformBufferSize);
6097 		flushAlloc(vkd, vkDevice, *m_uniformBufferMemory);
6098 	}
6099 
6100 	// Submit
6101 	submitCommandsAndWait(vkd, vkDevice, queue, commandBuffer.get());
6102 
6103 	invalidateAlloc(vkd, vkDevice, *m_resultBufferMemory);
6104 	tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderSize, m_renderSize, 1), m_resultBufferMemory->getHostPtr()));
6105 }
6106 
6107 class DiscardTestCase : public BaseRenderingTestCase
6108 {
6109 public:
DiscardTestCase(tcu::TestContext & context,const std::string & name,VkPrimitiveTopology primitiveTopology,deBool queryFragmentShaderInvocations,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)6110 								DiscardTestCase					(tcu::TestContext& context, const std::string& name, VkPrimitiveTopology primitiveTopology, deBool queryFragmentShaderInvocations, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
6111 									: BaseRenderingTestCase				(context, name, sampleCount)
6112 									, m_primitiveTopology				(primitiveTopology)
6113 									, m_queryFragmentShaderInvocations	(queryFragmentShaderInvocations)
6114 								{}
6115 
createInstance(Context & context) const6116 	virtual TestInstance*		createInstance		(Context& context) const
6117 								{
6118 									return new DiscardTestInstance (context, m_primitiveTopology, m_queryFragmentShaderInvocations);
6119 								}
6120 
checkSupport(Context & context) const6121 	virtual	void				checkSupport		(Context& context) const
6122 								{
6123 									if (m_queryFragmentShaderInvocations)
6124 										context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_PIPELINE_STATISTICS_QUERY);
6125 
6126 #ifndef CTS_USES_VULKANSC
6127 									if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
6128 											context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
6129 											!context.getPortabilitySubsetFeatures().triangleFans)
6130 										TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
6131 #endif // CTS_USES_VULKANSC
6132 								}
6133 
6134 protected:
6135 	const VkPrimitiveTopology	m_primitiveTopology;
6136 	const deBool				m_queryFragmentShaderInvocations;
6137 };
6138 
6139 class TriangleInterpolationTestInstance : public BaseRenderingTestInstance
6140 {
6141 public:
6142 
TriangleInterpolationTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,int flags,VkSampleCountFlagBits sampleCount)6143 								TriangleInterpolationTestInstance	(Context& context, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount)
6144 									: BaseRenderingTestInstance	(context, sampleCount, RESOLUTION_POT)
6145 									, m_primitiveTopology		(primitiveTopology)
6146 									, m_projective				((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
6147 									, m_iterationCount			(3)
6148 									, m_iteration				(0)
6149 									, m_allIterationsPassed		(true)
6150 									, m_flatshade				((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
6151 								{}
6152 
6153 	tcu::TestStatus				iterate								(void);
6154 
6155 
6156 private:
6157 	void						generateVertices					(int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
6158 	void						extractTriangles					(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
6159 
6160 
6161 	VkPrimitiveTopology			m_primitiveTopology;
6162 	const bool					m_projective;
6163 	const int					m_iterationCount;
6164 	int							m_iteration;
6165 	bool						m_allIterationsPassed;
6166 	const deBool				m_flatshade;
6167 };
6168 
iterate(void)6169 tcu::TestStatus TriangleInterpolationTestInstance::iterate (void)
6170 {
6171 	const std::string								iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
6172 	const tcu::ScopedLogSection						section					(m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
6173 	tcu::Surface									resultImage				(m_renderSize, m_renderSize);
6174 	std::vector<tcu::Vec4>							drawBuffer;
6175 	std::vector<tcu::Vec4>							colorBuffer;
6176 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
6177 
6178 	// generate scene
6179 	generateVertices(m_iteration, drawBuffer, colorBuffer);
6180 	extractTriangles(triangles, drawBuffer, colorBuffer);
6181 
6182 	// log
6183 	{
6184 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
6185 		for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
6186 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
6187 	}
6188 
6189 	// draw image
6190 	drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
6191 
6192 	// compare
6193 	{
6194 		RasterizationArguments	args;
6195 		TriangleSceneSpec		scene;
6196 		tcu::IVec4				colorBits	= tcu::getTextureFormatBitDepth(getTextureFormat());
6197 
6198 		args.numSamples		= m_multisampling ? 1 : 0;
6199 		args.subpixelBits	= m_subpixelBits;
6200 		args.redBits		= colorBits[0];
6201 		args.greenBits		= colorBits[1];
6202 		args.blueBits		= colorBits[2];
6203 
6204 		scene.triangles.swap(triangles);
6205 
6206 		if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog()))
6207 			m_allIterationsPassed = false;
6208 	}
6209 
6210 	// result
6211 	if (++m_iteration == m_iterationCount)
6212 	{
6213 		if (m_allIterationsPassed)
6214 			return tcu::TestStatus::pass("Pass");
6215 		else
6216 			return tcu::TestStatus::fail("Found invalid pixel values");
6217 	}
6218 	else
6219 		return tcu::TestStatus::incomplete();
6220 }
6221 
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const6222 void TriangleInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
6223 {
6224 	// use only red, green and blue
6225 	const tcu::Vec4 colors[] =
6226 	{
6227 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
6228 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
6229 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
6230 	};
6231 
6232 	de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
6233 
6234 	outVertices.resize(6);
6235 	outColors.resize(6);
6236 
6237 	for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
6238 	{
6239 		outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
6240 		outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
6241 		outVertices[vtxNdx].z() = 0.0f;
6242 
6243 		if (!m_projective)
6244 			outVertices[vtxNdx].w() = 1.0f;
6245 		else
6246 		{
6247 			const float w = rnd.getFloat(0.2f, 4.0f);
6248 
6249 			outVertices[vtxNdx].x() *= w;
6250 			outVertices[vtxNdx].y() *= w;
6251 			outVertices[vtxNdx].z() *= w;
6252 			outVertices[vtxNdx].w() = w;
6253 		}
6254 
6255 		outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
6256 	}
6257 }
6258 
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const6259 void TriangleInterpolationTestInstance::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
6260 {
6261 	switch (m_primitiveTopology)
6262 	{
6263 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
6264 		{
6265 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
6266 			{
6267 				TriangleSceneSpec::SceneTriangle tri;
6268 				tri.positions[0]	= vertices[vtxNdx + 0];
6269 				tri.positions[1]	= vertices[vtxNdx + 1];
6270 				tri.positions[2]	= vertices[vtxNdx + 2];
6271 				tri.sharedEdge[0]	= false;
6272 				tri.sharedEdge[1]	= false;
6273 				tri.sharedEdge[2]	= false;
6274 
6275 				if (m_flatshade)
6276 				{
6277 					tri.colors[0] = colors[vtxNdx];
6278 					tri.colors[1] = colors[vtxNdx];
6279 					tri.colors[2] = colors[vtxNdx];
6280 				}
6281 				else
6282 				{
6283 					tri.colors[0] = colors[vtxNdx + 0];
6284 					tri.colors[1] = colors[vtxNdx + 1];
6285 					tri.colors[2] = colors[vtxNdx + 2];
6286 				}
6287 
6288 				outTriangles.push_back(tri);
6289 			}
6290 			break;
6291 		}
6292 
6293 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
6294 		{
6295 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
6296 			{
6297 				TriangleSceneSpec::SceneTriangle tri;
6298 				tri.positions[0]	= vertices[vtxNdx + 0];
6299 				tri.positions[1]	= vertices[vtxNdx + 1];
6300 				tri.positions[2]	= vertices[vtxNdx + 2];
6301 				tri.sharedEdge[0]	= false;
6302 				tri.sharedEdge[1]	= false;
6303 				tri.sharedEdge[2]	= false;
6304 
6305 				if (m_flatshade)
6306 				{
6307 					tri.colors[0] = colors[vtxNdx];
6308 					tri.colors[1] = colors[vtxNdx];
6309 					tri.colors[2] = colors[vtxNdx];
6310 				}
6311 				else
6312 				{
6313 					tri.colors[0] = colors[vtxNdx + 0];
6314 					tri.colors[1] = colors[vtxNdx + 1];
6315 					tri.colors[2] = colors[vtxNdx + 2];
6316 				}
6317 
6318 				outTriangles.push_back(tri);
6319 			}
6320 			break;
6321 		}
6322 
6323 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
6324 		{
6325 			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
6326 			{
6327 				TriangleSceneSpec::SceneTriangle tri;
6328 				tri.positions[0]	= vertices[0];
6329 				tri.positions[1]	= vertices[vtxNdx + 0];
6330 				tri.positions[2]	= vertices[vtxNdx + 1];
6331 				tri.sharedEdge[0]	= false;
6332 				tri.sharedEdge[1]	= false;
6333 				tri.sharedEdge[2]	= false;
6334 
6335 				if (m_flatshade)
6336 				{
6337 					tri.colors[0] = colors[vtxNdx];
6338 					tri.colors[1] = colors[vtxNdx];
6339 					tri.colors[2] = colors[vtxNdx];
6340 				}
6341 				else
6342 				{
6343 					tri.colors[0] = colors[0];
6344 					tri.colors[1] = colors[vtxNdx + 0];
6345 					tri.colors[2] = colors[vtxNdx + 1];
6346 				}
6347 
6348 				outTriangles.push_back(tri);
6349 			}
6350 			break;
6351 		}
6352 
6353 		default:
6354 			DE_ASSERT(false);
6355 	}
6356 }
6357 
6358 class TriangleInterpolationTestCase : public BaseRenderingTestCase
6359 {
6360 public:
TriangleInterpolationTestCase(tcu::TestContext & context,const std::string & name,VkPrimitiveTopology primitiveTopology,int flags,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)6361 								TriangleInterpolationTestCase	(tcu::TestContext& context, const std::string& name, VkPrimitiveTopology primitiveTopology, int flags, VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT)
6362 									: BaseRenderingTestCase		(context, name, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
6363 									, m_primitiveTopology		(primitiveTopology)
6364 									, m_flags					(flags)
6365 								{}
6366 
createInstance(Context & context) const6367 	virtual TestInstance*		createInstance					(Context& context) const
6368 								{
6369 									return new TriangleInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_sampleCount);
6370 								}
6371 
checkSupport(Context & context) const6372 	virtual	void				checkSupport		(Context& context) const
6373 								{
6374 #ifndef CTS_USES_VULKANSC
6375 									if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
6376 										context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
6377 										!context.getPortabilitySubsetFeatures().triangleFans)
6378 									{
6379 										TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
6380 									}
6381 #else
6382 	DE_UNREF(context);
6383 #endif // CTS_USES_VULKANSC
6384 								}
6385 protected:
6386 	const VkPrimitiveTopology	m_primitiveTopology;
6387 	const int					m_flags;
6388 };
6389 
6390 class LineInterpolationTestInstance : public BaseRenderingTestInstance
6391 {
6392 public:
6393 							LineInterpolationTestInstance	(Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount);
6394 
6395 	virtual tcu::TestStatus	iterate							(void);
6396 
6397 private:
6398 	void					generateVertices				(int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
6399 	void					extractLines					(std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
6400 	virtual float			getLineWidth					(void) const;
6401 
6402 	VkPrimitiveTopology		m_primitiveTopology;
6403 	const bool				m_projective;
6404 	const int				m_iterationCount;
6405 	const PrimitiveWideness	m_primitiveWideness;
6406 
6407 	int						m_iteration;
6408 	bool					m_allIterationsPassed;
6409 	float					m_maxLineWidth;
6410 	std::vector<float>		m_lineWidths;
6411 	bool					m_flatshade;
6412 	PrimitiveStrictness		m_strictness;
6413 };
6414 
LineInterpolationTestInstance(Context & context,VkPrimitiveTopology primitiveTopology,int flags,PrimitiveWideness wideness,PrimitiveStrictness strictness,VkSampleCountFlagBits sampleCount)6415 LineInterpolationTestInstance::LineInterpolationTestInstance (Context& context, VkPrimitiveTopology primitiveTopology, int flags, PrimitiveWideness wideness, PrimitiveStrictness strictness, VkSampleCountFlagBits sampleCount)
6416 	: BaseRenderingTestInstance			(context, sampleCount)
6417 	, m_primitiveTopology				(primitiveTopology)
6418 	, m_projective						((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
6419 	, m_iterationCount					(3)
6420 	, m_primitiveWideness				(wideness)
6421 	, m_iteration						(0)
6422 	, m_allIterationsPassed				(true)
6423 	, m_maxLineWidth					(1.0f)
6424 	, m_flatshade						((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
6425 	, m_strictness						(strictness)
6426 {
6427 	DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
6428 
6429 	// create line widths
6430 	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
6431 	{
6432 		m_lineWidths.resize(m_iterationCount, 1.0f);
6433 	}
6434 	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
6435 	{
6436 		const float*	range = context.getDeviceProperties().limits.lineWidthRange;
6437 
6438 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
6439 
6440 		DE_ASSERT(range[1] > 1.0f);
6441 
6442 		// set hand picked sizes
6443 		m_lineWidths.push_back(5.0f);
6444 		m_lineWidths.push_back(10.0f);
6445 		m_lineWidths.push_back(range[1]);
6446 		DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
6447 
6448 		m_maxLineWidth = range[1];
6449 	}
6450 	else
6451 		DE_ASSERT(false);
6452 }
6453 
iterate(void)6454 tcu::TestStatus LineInterpolationTestInstance::iterate (void)
6455 {
6456 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
6457 	const tcu::ScopedLogSection				section					(m_context.getTestContext().getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
6458 	const float								lineWidth				= getLineWidth();
6459 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
6460 	std::vector<tcu::Vec4>					drawBuffer;
6461 	std::vector<tcu::Vec4>					colorBuffer;
6462 	std::vector<LineSceneSpec::SceneLine>	lines;
6463 
6464 	// supported?
6465 	if (lineWidth <= m_maxLineWidth)
6466 	{
6467 		// generate scene
6468 		generateVertices(m_iteration, drawBuffer, colorBuffer);
6469 		extractLines(lines, drawBuffer, colorBuffer);
6470 
6471 		// log
6472 		{
6473 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
6474 			for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
6475 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
6476 		}
6477 
6478 		// draw image
6479 		drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitiveTopology);
6480 
6481 		// compare
6482 		{
6483 			RasterizationArguments	args;
6484 			LineSceneSpec			scene;
6485 
6486 			tcu::IVec4				colorBits = tcu::getTextureFormatBitDepth(getTextureFormat());
6487 
6488 			args.numSamples		= m_multisampling ? 1 : 0;
6489 			args.subpixelBits	= m_subpixelBits;
6490 			args.redBits		= colorBits[0];
6491 			args.greenBits		= colorBits[1];
6492 			args.blueBits		= colorBits[2];
6493 
6494 			scene.lines.swap(lines);
6495 			scene.lineWidth = getLineWidth();
6496 
6497 			switch (m_strictness)
6498 			{
6499 				case PRIMITIVESTRICTNESS_STRICT:
6500 				{
6501 					if (!verifyTriangulatedLineGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog(), true))
6502 						m_allIterationsPassed = false;
6503 
6504 					break;
6505 				}
6506 
6507 				case PRIMITIVESTRICTNESS_NONSTRICT:
6508 				case PRIMITIVESTRICTNESS_IGNORE:
6509 				{
6510 					if (!verifyTriangulatedLineGroupInterpolation(resultImage, scene, args, m_context.getTestContext().getLog(), false, true))
6511 						m_allIterationsPassed = false;
6512 
6513 					break;
6514 				}
6515 
6516 				default:
6517 					TCU_THROW(InternalError, "Not implemented");
6518 			}
6519 		}
6520 	}
6521 	else
6522 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
6523 
6524 	// result
6525 	if (++m_iteration == m_iterationCount)
6526 	{
6527 		if (m_allIterationsPassed)
6528 			return tcu::TestStatus::pass("Pass");
6529 		else
6530 			return tcu::TestStatus::fail("Incorrect rasterization");
6531 	}
6532 	else
6533 		return tcu::TestStatus::incomplete();
6534 }
6535 
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const6536 void LineInterpolationTestInstance::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
6537 {
6538 	// use only red, green and blue
6539 	const tcu::Vec4 colors[] =
6540 	{
6541 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
6542 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
6543 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
6544 	};
6545 
6546 	de::Random rnd(123 + iteration * 1000 + (int)m_primitiveTopology);
6547 
6548 	outVertices.resize(6);
6549 	outColors.resize(6);
6550 
6551 	for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
6552 	{
6553 		outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
6554 		outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
6555 		outVertices[vtxNdx].z() = 0.0f;
6556 
6557 		if (!m_projective)
6558 			outVertices[vtxNdx].w() = 1.0f;
6559 		else
6560 		{
6561 			const float w = rnd.getFloat(0.2f, 4.0f);
6562 
6563 			outVertices[vtxNdx].x() *= w;
6564 			outVertices[vtxNdx].y() *= w;
6565 			outVertices[vtxNdx].z() *= w;
6566 			outVertices[vtxNdx].w() = w;
6567 		}
6568 
6569 		outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
6570 	}
6571 }
6572 
extractLines(std::vector<LineSceneSpec::SceneLine> & outLines,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const6573 void LineInterpolationTestInstance::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
6574 {
6575 	switch (m_primitiveTopology)
6576 	{
6577 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
6578 		{
6579 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
6580 			{
6581 				LineSceneSpec::SceneLine line;
6582 				line.positions[0] = vertices[vtxNdx + 0];
6583 				line.positions[1] = vertices[vtxNdx + 1];
6584 
6585 				if (m_flatshade)
6586 				{
6587 					line.colors[0] = colors[vtxNdx];
6588 					line.colors[1] = colors[vtxNdx];
6589 				}
6590 				else
6591 				{
6592 					line.colors[0] = colors[vtxNdx + 0];
6593 					line.colors[1] = colors[vtxNdx + 1];
6594 				}
6595 
6596 				outLines.push_back(line);
6597 			}
6598 			break;
6599 		}
6600 
6601 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
6602 		{
6603 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
6604 			{
6605 				LineSceneSpec::SceneLine line;
6606 				line.positions[0] = vertices[vtxNdx + 0];
6607 				line.positions[1] = vertices[vtxNdx + 1];
6608 
6609 				if (m_flatshade)
6610 				{
6611 					line.colors[0] = colors[vtxNdx];
6612 					line.colors[1] = colors[vtxNdx];
6613 				}
6614 				else
6615 				{
6616 					line.colors[0] = colors[vtxNdx + 0];
6617 					line.colors[1] = colors[vtxNdx + 1];
6618 				}
6619 
6620 				outLines.push_back(line);
6621 			}
6622 			break;
6623 		}
6624 
6625 		default:
6626 			DE_ASSERT(false);
6627 	}
6628 }
6629 
getLineWidth(void) const6630 float LineInterpolationTestInstance::getLineWidth (void) const
6631 {
6632 	return m_lineWidths[m_iteration];
6633 }
6634 
6635 class LineInterpolationTestCase : public BaseRenderingTestCase
6636 {
6637 public:
LineInterpolationTestCase(tcu::TestContext & context,const std::string & name,VkPrimitiveTopology primitiveTopology,int flags,PrimitiveWideness wideness,PrimitiveStrictness strictness,VkSampleCountFlagBits sampleCount=VK_SAMPLE_COUNT_1_BIT)6638 								LineInterpolationTestCase		(tcu::TestContext&		context,
6639 																 const std::string&		name,
6640 																 VkPrimitiveTopology	primitiveTopology,
6641 																 int					flags,
6642 																 PrimitiveWideness		wideness,
6643 																 PrimitiveStrictness	strictness,
6644 																 VkSampleCountFlagBits	sampleCount = VK_SAMPLE_COUNT_1_BIT)
6645 									: BaseRenderingTestCase		(context, name, sampleCount, (flags & INTERPOLATIONFLAGS_FLATSHADE) != 0)
6646 									, m_primitiveTopology		(primitiveTopology)
6647 									, m_flags					(flags)
6648 									, m_wideness				(wideness)
6649 									, m_strictness				(strictness)
6650 								{}
6651 
createInstance(Context & context) const6652 	virtual TestInstance*		createInstance					(Context& context) const
6653 								{
6654 									return new LineInterpolationTestInstance(context, m_primitiveTopology, m_flags, m_wideness, m_strictness, m_sampleCount);
6655 								}
6656 
checkSupport(Context & context) const6657 	virtual	void				checkSupport		(Context& context) const
6658 								{
6659 									if (m_strictness == PRIMITIVESTRICTNESS_STRICT &&
6660 										!context.getDeviceProperties().limits.strictLines)
6661 										TCU_THROW(NotSupportedError, "Strict rasterization is not supported");
6662 
6663 									if (m_wideness == PRIMITIVEWIDENESS_WIDE)
6664 										context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_WIDE_LINES);
6665 								}
6666 protected:
6667 	const VkPrimitiveTopology	m_primitiveTopology;
6668 	const int					m_flags;
6669 	const PrimitiveWideness		m_wideness;
6670 	const PrimitiveStrictness	m_strictness;
6671 };
6672 
6673 class StrideZeroCase : public vkt::TestCase
6674 {
6675 public:
6676 	struct Params
6677 	{
6678 		std::vector<tcu::Vec2>	bufferData;
6679 		deUint32				drawVertexCount;
6680 	};
6681 
StrideZeroCase(tcu::TestContext & testCtx,const std::string & name,const Params & params)6682 							StrideZeroCase		(tcu::TestContext& testCtx, const std::string& name, const Params& params)
6683 								: vkt::TestCase	(testCtx, name)
6684 								, m_params		(params)
6685 								{}
6686 
~StrideZeroCase(void)6687 	virtual					~StrideZeroCase		(void) {}
6688 
6689 	virtual void			initPrograms		(vk::SourceCollections& programCollection) const;
6690 	virtual TestInstance*	createInstance		(Context& context) const;
6691 	virtual void			checkSupport		(Context& context) const;
6692 
6693 	static constexpr vk::VkFormat				kColorFormat	= vk::VK_FORMAT_R8G8B8A8_UNORM;
6694 	static constexpr vk::VkFormatFeatureFlags	kColorFeatures	= (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
6695 	static constexpr vk::VkImageUsageFlags		kColorUsage		= (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
6696 
6697 	//	(-1,-1)
6698 	//		+-----+-----+
6699 	//		|     |     |
6700 	//		|  a  |  b  |	a = (-0.5, -0.5)
6701 	//		|     |     |	b = ( 0.5, -0.5)
6702 	//		+-----------+	c = (-0.5,  0.5)
6703 	//		|     |     |	d = ( 0.5,  0.5)
6704 	//		|  c  |  d  |
6705 	//		|     |     |
6706 	//		+-----+-----+
6707 	//					(1,1)
6708 	static constexpr deUint32					kImageDim		= 2u;
6709 	static const float							kCornerDelta;	// 0.5f;
6710 
6711 	static const tcu::Vec4						kClearColor;
6712 	static const tcu::Vec4						kDrawColor;
6713 
6714 private:
6715 	Params m_params;
6716 };
6717 
6718 const float		StrideZeroCase::kCornerDelta	= 0.5f;
6719 const tcu::Vec4	StrideZeroCase::kClearColor		(0.0f, 0.0f, 0.0f, 1.0f);
6720 const tcu::Vec4	StrideZeroCase::kDrawColor		(1.0f, 1.0f, 1.0f, 1.0f);
6721 
6722 class StrideZeroInstance : public vkt::TestInstance
6723 {
6724 public:
StrideZeroInstance(Context & context,const StrideZeroCase::Params & params)6725 								StrideZeroInstance	(Context& context, const StrideZeroCase::Params& params)
6726 									: vkt::TestInstance	(context)
6727 									, m_params			(params)
6728 									{}
6729 
~StrideZeroInstance(void)6730 	virtual						~StrideZeroInstance	(void) {}
6731 
6732 	virtual tcu::TestStatus		iterate				(void);
6733 
6734 private:
6735 	StrideZeroCase::Params m_params;
6736 };
6737 
initPrograms(vk::SourceCollections & programCollection) const6738 void StrideZeroCase::initPrograms (vk::SourceCollections& programCollection) const
6739 {
6740 	std::ostringstream vert;
6741 	std::ostringstream frag;
6742 
6743 	std::ostringstream drawColor;
6744 	drawColor
6745 		<< std::setprecision(2) << std::fixed
6746 		<< "vec4(" << kDrawColor.x() << ", " << kDrawColor.y() << ", " << kDrawColor.z() << ", " << kDrawColor.w() << ")";
6747 
6748 	vert
6749 		<< "#version 450\n"
6750 		<< "layout (location=0) in vec2 inPos;\n"
6751 		<< "void main() {\n"
6752 		<< "    gl_Position = vec4(inPos, 0.0, 1.0);\n"
6753 		<< "    gl_PointSize = 1.0;\n"
6754 		<< "}\n"
6755 		;
6756 
6757 	frag
6758 		<< "#version 450\n"
6759 		<< "layout (location=0) out vec4 outColor;\n"
6760 		<< "void main() {\n"
6761 		<< "    outColor = " << drawColor.str() << ";\n"
6762 		<< "}\n"
6763 		;
6764 
6765 	programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
6766 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
6767 }
6768 
createInstance(Context & context) const6769 TestInstance* StrideZeroCase::createInstance (Context& context) const
6770 {
6771 	return new StrideZeroInstance(context, m_params);
6772 }
6773 
checkSupport(Context & context) const6774 void StrideZeroCase::checkSupport (Context& context) const
6775 {
6776 	const auto properties = vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), kColorFormat);
6777 	if ((properties.optimalTilingFeatures & kColorFeatures) != kColorFeatures)
6778 		TCU_THROW(NotSupportedError, "Required image format not supported");
6779 }
6780 
6781 // Creates a vertex buffer with the given data but uses zero as the binding stride.
6782 // Then, tries to draw the requested number of points. Only the first point should ever be used.
iterate(void)6783 tcu::TestStatus StrideZeroInstance::iterate (void)
6784 {
6785 	const auto&		vkd			= m_context.getDeviceInterface();
6786 	const auto		device		= m_context.getDevice();
6787 	auto&			alloc		= m_context.getDefaultAllocator();
6788 	const auto		queue		= m_context.getUniversalQueue();
6789 	const auto		queueIndex	= m_context.getUniversalQueueFamilyIndex();
6790 	constexpr auto	kImageDim	= StrideZeroCase::kImageDim;
6791 	const auto		colorExtent	= vk::makeExtent3D(kImageDim, kImageDim, 1u);
6792 
6793 	// Prepare vertex buffer.
6794 	const auto					vertexBufferSize	= static_cast<vk::VkDeviceSize>(m_params.bufferData.size() * sizeof(decltype(m_params.bufferData)::value_type));
6795 	const auto					vertexBufferInfo	= vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
6796 	const vk::BufferWithMemory	vertexBuffer(		vkd, device, alloc, vertexBufferInfo, vk::MemoryRequirement::HostVisible);
6797 	auto&						vertexBufferAlloc	= vertexBuffer.getAllocation();
6798 	const vk::VkDeviceSize		vertexBufferOffset	= 0ull;
6799 	deMemcpy(vertexBufferAlloc.getHostPtr(), m_params.bufferData.data(), static_cast<size_t>(vertexBufferSize));
6800 	flushAlloc(vkd, device, vertexBufferAlloc);
6801 
6802 	// Prepare render image.
6803 	const vk::VkImageCreateInfo colorAttachmentInfo =
6804 	{
6805 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
6806 		nullptr,									//	const void*				pNext;
6807 		0u,											//	VkImageCreateFlags		flags;
6808 		vk::VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
6809 		StrideZeroCase::kColorFormat,				//	VkFormat				format;
6810 		colorExtent,								//	VkExtent3D				extent;
6811 		1u,											//	deUint32				mipLevels;
6812 		1u,											//	deUint32				arrayLayers;
6813 		vk::VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
6814 		vk::VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
6815 		StrideZeroCase::kColorUsage,				//	VkImageUsageFlags		usage;
6816 		vk::VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
6817 		1u,											//	deUint32				queueFamilyIndexCount;
6818 		&queueIndex,								//	const deUint32*			pQueueFamilyIndices;
6819 		vk::VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
6820 	};
6821 	const vk::ImageWithMemory colorAttachment(vkd, device, alloc, colorAttachmentInfo, vk::MemoryRequirement::Any);
6822 
6823 	const auto colorSubresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
6824 	const auto colorAttachmentView		= vk::makeImageView(vkd, device, colorAttachment.get(), vk::VK_IMAGE_VIEW_TYPE_2D, StrideZeroCase::kColorFormat, colorSubresourceRange);
6825 
6826 	const vk::VkVertexInputBindingDescription vertexBinding =
6827 	{
6828 		0u,									//	deUint32			binding;
6829 		0u,									//	deUint32			stride;		[IMPORTANT]
6830 		vk::VK_VERTEX_INPUT_RATE_VERTEX,	//	VkVertexInputRate	inputRate;
6831 	};
6832 
6833 	const vk::VkVertexInputAttributeDescription vertexAttribute =
6834 	{
6835 		0u,								//	deUint32	location;
6836 		0u,								//	deUint32	binding;
6837 		vk::VK_FORMAT_R32G32_SFLOAT,	//	VkFormat	format;
6838 		0u,								//	deUint32	offset;
6839 	};
6840 
6841 	const vk::VkPipelineVertexInputStateCreateInfo vertexInput =
6842 	{
6843 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
6844 		nullptr,														//	const void*									pNext;
6845 		0u,																//	VkPipelineVertexInputStateCreateFlags		flags;
6846 		1u,																//	deUint32									vertexBindingDescriptionCount;
6847 		&vertexBinding,													//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
6848 		1u,																//	deUint32									vertexAttributeDescriptionCount;
6849 		&vertexAttribute,												//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
6850 	};
6851 
6852 	const auto renderArea		= vk::makeRect2D(kImageDim, kImageDim);
6853 	const auto viewports		= std::vector<vk::VkViewport>(1, vk::makeViewport(kImageDim, kImageDim));
6854 	const auto scissors			= std::vector<vk::VkRect2D>(1, renderArea);
6855 	const auto pipelineLayout	= vk::makePipelineLayout(vkd, device);
6856 	const auto vertexShader		= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
6857 	const auto fragmentShader	= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
6858 	const auto renderPass		= vk::makeRenderPass(vkd, device, StrideZeroCase::kColorFormat);
6859 	const auto graphicsPipeline	= vk::makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
6860 		vertexShader.get(), DE_NULL, DE_NULL, DE_NULL, fragmentShader.get(),					// Shaders.
6861 		renderPass.get(), viewports, scissors, vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0u, 0u,	// Render pass, viewports, scissors, topology.
6862 		&vertexInput);																			// Vertex input state.
6863 	const auto framebuffer		= vk::makeFramebuffer(vkd, device, renderPass.get(), colorAttachmentView.get(), kImageDim, kImageDim);
6864 
6865 	const auto cmdPool		= vk::makeCommandPool(vkd, device, queueIndex);
6866 	const auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
6867 	const auto cmdBuffer	= cmdBufferPtr.get();
6868 
6869 	// Buffer used to verify results.
6870 	const auto					tcuFormat			= vk::mapVkFormat(StrideZeroCase::kColorFormat);
6871 	const auto					colorBufferSize		= static_cast<vk::VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * kImageDim * kImageDim;
6872 	const auto					colorBufferInfo		= vk::makeBufferCreateInfo(colorBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
6873 	const vk::BufferWithMemory	colorBuffer			(vkd, device, alloc, colorBufferInfo, vk::MemoryRequirement::HostVisible);
6874 	auto&						colorBufferAlloc	= colorBuffer.getAllocation();
6875 	void*						colorBufferPtr		= colorBufferAlloc.getHostPtr();
6876 	const auto					colorLayers			= vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
6877 	const auto					copyRegion			= vk::makeBufferImageCopy(colorExtent, colorLayers);
6878 
6879 	// Barriers from attachment to buffer and buffer to host.
6880 	const auto colorAttachmentBarrier	= vk::makeImageMemoryBarrier	(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorAttachment.get(), colorSubresourceRange);
6881 	const auto colorBufferBarrier		= vk::makeBufferMemoryBarrier	(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, colorBuffer.get(), 0ull, colorBufferSize);
6882 
6883 	vk::beginCommandBuffer(vkd, cmdBuffer);
6884 	vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea, StrideZeroCase::kClearColor);
6885 	vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
6886 	vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.get());
6887 	vkd.cmdDraw(cmdBuffer, m_params.drawVertexCount, 1u, 0u, 0u);
6888 	vk::endRenderPass(vkd, cmdBuffer);
6889 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &colorAttachmentBarrier);
6890 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorAttachment.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.get(), 1u, &copyRegion);
6891 	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &colorBufferBarrier, 0u, nullptr);
6892 	vk::endCommandBuffer(vkd, cmdBuffer);
6893 
6894 	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
6895 
6896 	// Invalidate color buffer alloc.
6897 	vk::invalidateAlloc(vkd, device, colorBufferAlloc);
6898 
6899 	// Check buffer.
6900 	const int							imageDimI	= static_cast<int>(kImageDim);
6901 	const tcu::ConstPixelBufferAccess	colorPixels	(tcuFormat, imageDimI, imageDimI, 1, colorBufferPtr);
6902 	tcu::TestStatus						testStatus	= tcu::TestStatus::pass("Pass");
6903 	auto&								log			= m_context.getTestContext().getLog();
6904 
6905 	for (int x = 0; x < imageDimI; ++x)
6906 	for (int y = 0; y < imageDimI; ++y)
6907 	{
6908 		// Only the top-left corner should have draw data.
6909 		const auto expectedColor	= ((x == 0 && y == 0) ? StrideZeroCase::kDrawColor : StrideZeroCase::kClearColor);
6910 		const auto imageColor		= colorPixels.getPixel(x, y);
6911 
6912 		if (expectedColor != imageColor)
6913 		{
6914 			log
6915 				<< tcu::TestLog::Message
6916 				<< "Unexpected color found in pixel (" << x << ", " << y << "): "
6917 				<< "expected (" << expectedColor.x() << ", " << expectedColor.y() << ", " << expectedColor.z() << ", " << expectedColor.w() << ") "
6918 				<< "and found (" << imageColor.x() << ", " << imageColor.y() << ", " << imageColor.z() << ", " << imageColor.w() << ")"
6919 				<< tcu::TestLog::EndMessage;
6920 
6921 			testStatus = tcu::TestStatus::fail("Failed; Check log for details");
6922 		}
6923 	}
6924 
6925 	return testStatus;
6926 }
6927 
6928 class CullAndPrimitiveIdCase : public vkt::TestCase
6929 {
6930 public:
CullAndPrimitiveIdCase(tcu::TestContext & testCtx,const std::string & name)6931 					CullAndPrimitiveIdCase		(tcu::TestContext& testCtx, const std::string& name)
6932 						: vkt::TestCase(testCtx, name)
6933 						{}
~CullAndPrimitiveIdCase(void)6934 					~CullAndPrimitiveIdCase		(void) {}
6935 	void			initPrograms				(vk::SourceCollections& programCollection) const override;
6936 	void			checkSupport				(Context& context) const override;
6937 	TestInstance*	createInstance				(Context& context) const override;
6938 
6939 	static constexpr uint32_t kCullAndPrimitiveIDWidth	= 64u;
6940 	static constexpr uint32_t kCullAndPrimitiveIDHeight	= 64u;
6941 };
6942 
6943 class CullAndPrimitiveIdInstance : public vkt::TestInstance
6944 {
6945 public:
CullAndPrimitiveIdInstance(Context & context)6946 						CullAndPrimitiveIdInstance	(Context& context) : vkt::TestInstance(context) {}
~CullAndPrimitiveIdInstance(void)6947 						~CullAndPrimitiveIdInstance	(void) {}
6948 
6949 	tcu::TestStatus		iterate						(void) override;
6950 };
6951 
createInstance(Context & context) const6952 TestInstance* CullAndPrimitiveIdCase::createInstance (Context& context) const
6953 {
6954 	return new CullAndPrimitiveIdInstance(context);
6955 }
6956 
checkSupport(Context & context) const6957 void CullAndPrimitiveIdCase::checkSupport (Context &context) const
6958 {
6959 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
6960 }
6961 
initPrograms(vk::SourceCollections & sources) const6962 void CullAndPrimitiveIdCase::initPrograms(vk::SourceCollections& sources) const
6963 {
6964 	// One triangle per image pixel, alternating clockwise and counter-clockwise.
6965 	std::ostringstream vert;
6966 	vert
6967 		<< "#version 450\n"
6968 		<< "void main ()\n"
6969 		<< "{\n"
6970 		<< "    const uint width = " << kCullAndPrimitiveIDWidth << ";\n"
6971 		<< "    const uint height = " << kCullAndPrimitiveIDHeight << ";\n"
6972 		<< "    const uint uVertexIndex = uint(gl_VertexIndex);\n"
6973 		<< "    const uint triangleId = uVertexIndex / 3u;\n"
6974 		<< "    const uint vertId = uVertexIndex % 3u;\n"
6975 		<< "    const uint rowId = triangleId / width;\n"
6976 		<< "    const uint colId = triangleId % width;\n"
6977 		<< "    const float fWidth = float(width);\n"
6978 		<< "    const float fHeight = float(height);\n"
6979 		<< "    const float xPixelCoord = (float(colId) + 0.5) / fWidth * 2.0 - 1.0;\n"
6980 		<< "    const float yPixelCoord = (float(rowId) + 0.5) / fHeight * 2.0 - 1.0;\n"
6981 		<< "    const float quarterPixelWidth = (2.0 / fWidth) / 4.0;\n"
6982 		<< "    const float quarterPixelHeight = (2.0 / fHeight) / 4.0;\n"
6983 		<< "    const vec2 bottomLeft = vec2(xPixelCoord - quarterPixelWidth, yPixelCoord + quarterPixelHeight);\n"
6984 		<< "    const vec2 bottomRight = vec2(xPixelCoord + quarterPixelWidth, yPixelCoord + quarterPixelHeight);\n"
6985 		<< "    const vec2 topCenter = vec2(xPixelCoord, yPixelCoord - quarterPixelHeight);\n"
6986 		<< "    const vec2 cwCoords[3] = vec2[](bottomLeft, topCenter, bottomRight);\n"
6987 		<< "    const vec2 ccwCoords[3] = vec2[](bottomLeft, bottomRight, topCenter);\n"
6988 		<< "    // Half the triangles will be culled.\n"
6989 		<< "    const bool counterClockWise = ((triangleId % 2u) == 0u);\n"
6990 		<< "    vec2 pointCoords;\n"
6991 		<< "    if (counterClockWise) { pointCoords = ccwCoords[vertId]; }\n"
6992 		<< "    else                  { pointCoords = cwCoords[vertId]; }\n"
6993 		<< "    gl_Position = vec4(pointCoords, 0.0, 1.0);\n"
6994 		<< "}\n"
6995 		;
6996 	sources.glslSources.add("vert") << glu::VertexSource(vert.str());
6997 
6998 	std::ostringstream frag;
6999 	frag
7000 		<< "#version 450\n"
7001 		<< "layout (location=0) out vec4 outColor;\n"
7002 		<< "\n"
7003 		<< "void main ()\n"
7004 		<< "{\n"
7005 		<< "    const uint primId = uint(gl_PrimitiveID);\n"
7006 		<< "    // Pixel color rotates every 3 pixels.\n"
7007 		<< "    const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
7008 		<< "    const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
7009 		<< "    const vec4 blue = vec4(0.0, 0.0, 1.0, 1.0);\n"
7010 		<< "    const vec4 colorPalette[3] = vec4[](red, green, blue);\n"
7011 		<< "    const uint colorIdx = primId % 3u;\n"
7012 		<< "    outColor = colorPalette[colorIdx];\n"
7013 		<< "}\n"
7014 		;
7015 	sources.glslSources.add("frag") << glu::FragmentSource(frag.str());
7016 }
7017 
iterate()7018 tcu::TestStatus CullAndPrimitiveIdInstance::iterate ()
7019 {
7020 	const auto&			vkd					= m_context.getDeviceInterface();
7021 	const auto			device				= m_context.getDevice();
7022 	auto&				alloc				= m_context.getDefaultAllocator();
7023 	const auto			qIndex				= m_context.getUniversalQueueFamilyIndex();
7024 	const auto			queue				= m_context.getUniversalQueue();
7025 	const auto			kWidth				= CullAndPrimitiveIdCase::kCullAndPrimitiveIDWidth;
7026 	const auto			kHeight				= CullAndPrimitiveIdCase::kCullAndPrimitiveIDHeight;
7027 	const auto			extent				= makeExtent3D(kWidth, kHeight, 1u);
7028 	const auto			triangleCount		= extent.width * extent.height * extent.depth;
7029 	const auto			vertexCount			= triangleCount * 3u;
7030 	const auto			format				= VK_FORMAT_R8G8B8A8_UNORM;
7031 	const auto			tcuFormat			= mapVkFormat(format);
7032 	const auto			colorUsage			= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
7033 	const auto			verifBufferUsage	= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
7034 	const tcu::Vec4		clearColor			(0.0f, 0.0f, 0.0f, 1.0f);
7035 
7036 	// Color attachment.
7037 	const VkImageCreateInfo colorBufferInfo =
7038 	{
7039 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
7040 		nullptr,								//	const void*				pNext;
7041 		0u,										//	VkImageCreateFlags		flags;
7042 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
7043 		format,									//	VkFormat				format;
7044 		extent,									//	VkExtent3D				extent;
7045 		1u,										//	uint32_t				mipLevels;
7046 		1u,										//	uint32_t				arrayLayers;
7047 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
7048 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
7049 		colorUsage,								//	VkImageUsageFlags		usage;
7050 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
7051 		0u,										//	uint32_t				queueFamilyIndexCount;
7052 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
7053 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
7054 	};
7055 	ImageWithMemory		colorBuffer		(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
7056 	const auto			colorSRR		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
7057 	const auto			colorSRL		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
7058 	const auto			colorBufferView	= makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, format, colorSRR);
7059 
7060 	// Verification buffer.
7061 	const auto			verifBufferSize		= static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * extent.width * extent.height;
7062 	const auto			verifBufferInfo		= makeBufferCreateInfo(verifBufferSize, verifBufferUsage);
7063 	BufferWithMemory	verifBuffer			(vkd, device, alloc, verifBufferInfo, MemoryRequirement::HostVisible);
7064 	auto&				verifBufferAlloc	= verifBuffer.getAllocation();
7065 	void*				verifBufferData		= verifBufferAlloc.getHostPtr();
7066 
7067 	// Render pass and framebuffer.
7068 	const auto renderPass	= makeRenderPass(vkd, device, format);
7069 	const auto framebuffer	= makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), extent.width, extent.height);
7070 
7071 	// Shader modules.
7072 	const auto&		binaries		= m_context.getBinaryCollection();
7073 	const auto		vertModule		= createShaderModule(vkd, device, binaries.get("vert"));
7074 	const auto		fragModule		= createShaderModule(vkd, device, binaries.get("frag"));
7075 
7076 	// Viewports and scissors.
7077 	const std::vector<VkViewport>	viewports	(1u, makeViewport(extent));
7078 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(extent));
7079 
7080 	// Vertex input and culling.
7081 	const VkPipelineVertexInputStateCreateInfo		inputState			= initVulkanStructure();
7082 	const VkPipelineRasterizationStateCreateInfo	rasterizationState	=
7083 	{
7084 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		//	VkStructureType							sType;
7085 		nullptr,														//	const void*								pNext;
7086 		0u,																//	VkPipelineRasterizationStateCreateFlags	flags;
7087 		VK_FALSE,														//	VkBool32								depthClampEnable;
7088 		VK_FALSE,														//	VkBool32								rasterizerDiscardEnable;
7089 		VK_POLYGON_MODE_FILL,											//	VkPolygonMode							polygonMode;
7090 		VK_CULL_MODE_BACK_BIT,											//	VkCullModeFlags							cullMode;
7091 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								//	VkFrontFace								frontFace;
7092 		VK_FALSE,														//	VkBool32								depthBiasEnable;
7093 		0.0f,															//	float									depthBiasConstantFactor;
7094 		0.0f,															//	float									depthBiasClamp;
7095 		0.0f,															//	float									depthBiasSlopeFactor;
7096 		1.0f,															//	float									lineWidth;
7097 	};
7098 
7099 	// Pipeline layout and graphics pipeline.
7100 	const auto pipelineLayout	= makePipelineLayout(vkd, device);
7101 	const auto pipeline			= makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
7102 									vertModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
7103 									renderPass.get(), viewports, scissors,
7104 									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u/*subpass*/, 0u/*patchControlPoints*/,
7105 									&inputState, &rasterizationState);
7106 
7107 	// Command pool and buffer.
7108 	const auto cmdPool		= makeCommandPool(vkd, device, qIndex);
7109 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
7110 	const auto cmdBuffer	= cmdBufferPtr.get();
7111 
7112 	beginCommandBuffer(vkd, cmdBuffer);
7113 
7114 	// Draw.
7115 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
7116 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
7117 	vkd.cmdDraw(cmdBuffer, vertexCount, 1u, 0u, 0u);
7118 	endRenderPass(vkd, cmdBuffer);
7119 
7120 	// Copy to verification buffer.
7121 	const auto copyRegion		= makeBufferImageCopy(extent, colorSRL);
7122 	const auto transfer2Host	= makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
7123 	const auto color2Transfer	= makeImageMemoryBarrier(
7124 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
7125 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
7126 		colorBuffer.get(), colorSRR);
7127 
7128 	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer);
7129 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u, &copyRegion);
7130 	cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &transfer2Host);
7131 
7132 	endCommandBuffer(vkd, cmdBuffer);
7133 
7134 	// Submit and validate result.
7135 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
7136 	invalidateAlloc(vkd, device, verifBufferAlloc);
7137 
7138 	const tcu::IVec3				iExtent			(static_cast<int>(extent.width), static_cast<int>(extent.height), static_cast<int>(extent.depth));
7139 	const tcu::PixelBufferAccess	verifAccess		(tcuFormat, iExtent, verifBufferData);
7140 	tcu::TextureLevel				referenceLevel	(tcuFormat, iExtent.x(), iExtent.y(), iExtent.z());
7141 	const auto						referenceAccess	= referenceLevel.getAccess();
7142 
7143 	// Compose reference image.
7144 	const tcu::Vec4					red				(1.0f, 0.0f, 0.0f, 1.0f);
7145 	const tcu::Vec4					green			(0.0f, 1.0f, 0.0f, 1.0f);
7146 	const tcu::Vec4					blue			(0.0f, 0.0f, 1.0f, 1.0f);
7147 	const std::vector<tcu::Vec4>	colorPalette	{ red, green, blue };
7148 
7149 	for (int y = 0; y < iExtent.y(); ++y)
7150 		for (int x = 0; x < iExtent.x(); ++x)
7151 		{
7152 			const auto pixelId = y*iExtent.x() + x;
7153 			const bool culled = (pixelId % 2 == 1);
7154 			const auto color = (culled ? clearColor : colorPalette[pixelId % 3]);
7155 			referenceAccess.setPixel(color, x, y);
7156 		}
7157 
7158 	// Compare.
7159 	{
7160 		auto& log = m_context.getTestContext().getLog();
7161 		if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, verifAccess, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::COMPARE_LOG_ON_ERROR))
7162 			TCU_FAIL("Failed; check log for details");
7163 	}
7164 
7165 	return tcu::TestStatus::pass("Pass");
7166 }
7167 
7168 struct PolygonModeLargePointsConfig
7169 {
7170 	const float	pointSize;
7171 	const bool	meshShader;
7172 	const bool	tessellationShaders;
7173 	const bool	geometryShader;
7174 	const bool	dynamicPolygonMode;
7175 	const bool	defaultSize;
7176 
PolygonModeLargePointsConfigvkt::rasterization::__anon512ddb930111::PolygonModeLargePointsConfig7177 	PolygonModeLargePointsConfig (float pointSize_, bool meshShader_, bool tessellationShaders_, bool geometryShader_, bool dynamicPolygonMode_, bool defaultSize_ = false)
7178 		: pointSize				(pointSize_)
7179 		, meshShader			(meshShader_)
7180 		, tessellationShaders	(tessellationShaders_)
7181 		, geometryShader		(geometryShader_)
7182 		, dynamicPolygonMode	(dynamicPolygonMode_)
7183 		, defaultSize			(defaultSize_)
7184 	{
7185 		if (meshShader)
7186 		{
7187 			DE_ASSERT(!tessellationShaders && !geometryShader);
7188 		}
7189 	}
7190 };
7191 
7192 class PolygonModeLargePointsCase : public vkt::TestCase
7193 {
7194 public:
PolygonModeLargePointsCase(tcu::TestContext & testCtx,const std::string & name,const PolygonModeLargePointsConfig & config)7195 					PolygonModeLargePointsCase	(tcu::TestContext& testCtx, const std::string& name, const PolygonModeLargePointsConfig& config)
7196 						: vkt::TestCase	(testCtx, name)
7197 						, m_config		(config)
7198 						{}
~PolygonModeLargePointsCase(void)7199 	virtual			~PolygonModeLargePointsCase	(void) {}
7200 
7201 	void			checkSupport				(Context& context) const override;
7202 	void			initPrograms				(vk::SourceCollections& programCollection) const override;
7203 	TestInstance*	createInstance				(Context& context) const override;
7204 
7205 	static const tcu::Vec4		geometryColor;
7206 	static constexpr uint32_t	kNumTriangles	= 2u;
7207 	static constexpr uint32_t	kNumPoints		= kNumTriangles * 3u;
7208 
7209 protected:
7210 	const PolygonModeLargePointsConfig	m_config;
7211 };
7212 
7213 const tcu::Vec4 PolygonModeLargePointsCase::geometryColor (0.0f, 0.0f, 1.0f, 1.0f);
7214 
7215 class PolygonModeLargePointsInstance : public vkt::TestInstance
7216 {
7217 public:
PolygonModeLargePointsInstance(Context & context,const PolygonModeLargePointsConfig & config)7218 						PolygonModeLargePointsInstance	(Context& context, const PolygonModeLargePointsConfig& config)
7219 							: vkt::TestInstance(context)
7220 							, m_config(config)
7221 							{}
~PolygonModeLargePointsInstance(void)7222 	virtual				~PolygonModeLargePointsInstance	(void) {}
7223 
7224 	tcu::TestStatus		iterate							(void) override;
7225 
7226 protected:
7227 	const PolygonModeLargePointsConfig	m_config;
7228 };
7229 
checkSupport(Context & context) const7230 void PolygonModeLargePointsCase::checkSupport (Context &context) const
7231 {
7232 #ifndef CTS_USES_VULKANSC
7233 	context.requireDeviceFunctionality("VK_KHR_maintenance5");
7234 #else
7235 	DE_ASSERT(false);
7236 #endif // CTS_USES_VULKANSC
7237 
7238 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FILL_MODE_NON_SOLID);
7239 
7240 #ifndef CTS_USES_VULKANSC
7241 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().pointPolygons)
7242 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Point polygons are not supported by this implementation");
7243 #else
7244 	DE_ASSERT(false);
7245 #endif // CTS_USES_VULKANSC
7246 
7247 	const auto& limits = context.getDeviceProperties().limits;
7248 	if (!limits.standardSampleLocations)
7249 		TCU_THROW(NotSupportedError, "standardSampleLocations not supported");
7250 
7251 	if (m_config.meshShader)
7252 		context.requireDeviceFunctionality("VK_EXT_mesh_shader");
7253 
7254 	if (m_config.tessellationShaders || m_config.geometryShader)
7255 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE);
7256 
7257 	if (m_config.tessellationShaders)
7258 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
7259 
7260 	if (m_config.geometryShader)
7261 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
7262 
7263 	if (m_config.pointSize != 1.0f)
7264 	{
7265 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_LARGE_POINTS);
7266 
7267 		const auto& validRange = limits.pointSizeRange;
7268 		if (validRange[0] > m_config.pointSize || validRange[1] < m_config.pointSize)
7269 		{
7270 			std::ostringstream msg;
7271 			msg << "Required point size " << m_config.pointSize << " outside valid range [" << validRange[0] << ", " << validRange[1] << "]";
7272 			TCU_THROW(NotSupportedError, msg.str());
7273 		}
7274 	}
7275 
7276 #ifndef CTS_USES_VULKANSC
7277 	if (m_config.dynamicPolygonMode)
7278 	{
7279 		const auto eds3Features = context.getExtendedDynamicState3FeaturesEXT();
7280 		if (!eds3Features.extendedDynamicState3PolygonMode)
7281 			TCU_THROW(NotSupportedError, "extendedDynamicState3PolygonMode not supported");
7282 	}
7283 #else
7284 	DE_ASSERT(false);
7285 #endif // CTS_USES_VULKANSC
7286 }
7287 
initPrograms(vk::SourceCollections & programCollection) const7288 void PolygonModeLargePointsCase::initPrograms (vk::SourceCollections &programCollection) const
7289 {
7290 	if (!m_config.meshShader)
7291 	{
7292 		std::ostringstream vert;
7293 		vert
7294 			<< "#version 460\n"
7295 			<< "layout (location=0) in vec4 inPosition;\n"
7296 			<< "out gl_PerVertex {\n"
7297 			<< "    vec4  gl_Position;\n"
7298 			<< "    float gl_PointSize;\n"
7299 			<< "};\n"
7300 			<< "void main (void) {\n"
7301 			<< "    gl_Position  = inPosition;\n";
7302 		if (!m_config.defaultSize)
7303 		{
7304 		vert
7305 			<< "    gl_PointSize = " << std::fixed << m_config.pointSize << ";\n";
7306 		}
7307 		vert
7308 			<< "}\n"
7309 			;
7310 		programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
7311 	}
7312 	else
7313 	{
7314 		std::ostringstream mesh;
7315 		mesh
7316 			<< "#version 450\n"
7317 			<< "#extension GL_EXT_mesh_shader : enable\n"
7318 			<< "\n"
7319 			<< "layout (local_size_x=" << kNumPoints << ", local_size_y=1, local_size_z=1) in;\n"
7320 			<< "layout (triangles) out;\n"
7321 			<< "layout (max_vertices=" << kNumPoints << ", max_primitives=" << kNumTriangles << ") out;\n"
7322 			<< "\n"
7323 			<< "out gl_MeshPerVertexEXT {\n"
7324 			<< "    vec4  gl_Position;\n"
7325 			<< "    float gl_PointSize;\n"
7326 			<< "} gl_MeshVerticesEXT[];\n"
7327 			<< "\n"
7328 			<< "layout (set=0, binding=0, std430) readonly buffer VertexData {\n"
7329 			<< "    vec4 vertices[];\n"
7330 			<< "} vertexBuffer;\n"
7331 			<< "\n"
7332 			<< "void main (void) {\n"
7333 			<< "    SetMeshOutputsEXT(" << kNumPoints << ", " << kNumTriangles << ");\n"
7334 			<< "    gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vertexBuffer.vertices[gl_LocalInvocationIndex];\n";
7335 		if (!m_config.defaultSize)
7336 		{
7337 		mesh
7338 			<< "    gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_PointSize = " << std::fixed << m_config.pointSize << ";\n";
7339 		}
7340 		mesh
7341 			<< "    if (gl_LocalInvocationIndex < " << kNumTriangles << ") {\n"
7342 			<< "        const uint baseIndex = gl_LocalInvocationIndex * 3u;\n"
7343 			<< "        gl_PrimitiveTriangleIndicesEXT[gl_LocalInvocationIndex] = uvec3(baseIndex, baseIndex + 1u, baseIndex + 2u);\n"
7344 			<< "    }\n"
7345 			<< "}\n"
7346 			;
7347 		const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
7348 		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
7349 	}
7350 
7351 	std::ostringstream frag;
7352 	frag
7353 		<< "#version 460\n"
7354 		<< "layout (location=0) out vec4 outColor;\n"
7355 		<< "void main (void) {\n"
7356 		<< "    outColor = vec4" << geometryColor << ";\n"
7357 		<< "}\n"
7358 		;
7359 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
7360 
7361 	if (m_config.tessellationShaders)
7362 	{
7363 		std::ostringstream tesc;
7364 		tesc
7365 			<< "#version 460\n"
7366 			<< "layout (vertices=3) out;\n"
7367 			<< "in gl_PerVertex {\n"
7368 			<< "    vec4  gl_Position;\n"
7369 			<< "    float gl_PointSize;\n"
7370 			<< "} gl_in[gl_MaxPatchVertices];\n"
7371 			<< "out gl_PerVertex {\n"
7372 			<< "    vec4  gl_Position;\n"
7373 			<< "    float gl_PointSize;\n"
7374 			<< "} gl_out[];\n"
7375 			<< "void main (void) {\n"
7376 			<< "  gl_TessLevelInner[0] = 1.0;\n"
7377 			<< "  gl_TessLevelInner[1] = 1.0;\n"
7378 			<< "  gl_TessLevelOuter[0] = 1.0;\n"
7379 			<< "  gl_TessLevelOuter[1] = 1.0;\n"
7380 			<< "  gl_TessLevelOuter[2] = 1.0;\n"
7381 			<< "  gl_TessLevelOuter[3] = 1.0;\n"
7382 			<< "  gl_out[gl_InvocationID].gl_Position  = gl_in[gl_InvocationID].gl_Position;\n";
7383 		if (!m_config.defaultSize)
7384 		{
7385 		tesc
7386 			<< "  gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n";
7387 		}
7388 		tesc
7389 			<< "}\n"
7390 			;
7391 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
7392 
7393 
7394 		std::ostringstream tese;
7395 		tese
7396 			<< "#version 460\n"
7397 			<< "layout (triangles, fractional_odd_spacing, cw) in;\n"
7398 			<< "in gl_PerVertex {\n"
7399 			<< "    vec4  gl_Position;\n"
7400 			<< "    float gl_PointSize;\n"
7401 			<< "} gl_in[gl_MaxPatchVertices];\n"
7402 			<< "out gl_PerVertex {\n"
7403 			<< "    vec4  gl_Position;\n"
7404 			<< "    float gl_PointSize;\n"
7405 			<< "};\n"
7406 			<< "void main (void) {\n"
7407 			<< "    gl_Position  = (gl_TessCoord.x * gl_in[0].gl_Position) +\n"
7408 			<< "                   (gl_TessCoord.y * gl_in[1].gl_Position) +\n"
7409 			<< "                   (gl_TessCoord.z * gl_in[2].gl_Position);\n";
7410 		if (!m_config.defaultSize)
7411 		{
7412 		tese
7413 			<< "    gl_PointSize = gl_in[0].gl_PointSize;\n";
7414 		}
7415 		tese
7416 			<< "}\n"
7417 			;
7418 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
7419 	}
7420 
7421 	if (m_config.geometryShader)
7422 	{
7423 		std::ostringstream geom;
7424 		geom
7425 			<< "#version 460\n"
7426 			<< "layout (triangles) in;\n"
7427 			<< "layout (triangle_strip, max_vertices=3) out;\n"
7428 			<< "in gl_PerVertex {\n"
7429 			<< "    vec4  gl_Position;\n"
7430 			<< "    float gl_PointSize;\n"
7431 			<< "} gl_in[3];\n"
7432 			<< "out gl_PerVertex {\n"
7433 			<< "    vec4  gl_Position;\n"
7434 			<< "    float gl_PointSize;\n"
7435 			<< "};\n"
7436 			<< "void main (void) {\n"
7437 			<< "    for (uint i = 0u; i < 3u; ++i) {\n"
7438 			<< "        gl_Position  = gl_in[i].gl_Position;\n";
7439 		if (!m_config.defaultSize)
7440 		{
7441 		geom
7442 			<< "        gl_PointSize = gl_in[i].gl_PointSize;\n";
7443 		}
7444 		geom
7445 			<< "        EmitVertex();\n"
7446 			<< "    }\n"
7447 			<< "}\n"
7448 			;
7449 		programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
7450 	}
7451 }
7452 
createInstance(Context & context) const7453 TestInstance* PolygonModeLargePointsCase::createInstance (Context& context) const
7454 {
7455 	return new PolygonModeLargePointsInstance(context, m_config);
7456 }
7457 
7458 /*
7459  * The test will create a 4x4 framebuffer and will draw a quad in the middle of it, roughly covering the 4 center pixels. Instead of
7460  * making the quad have the exact size to cover the whole center area, the quad will be slightly inside the 4 center pixels, with a
7461  * margin of 0.125 units (1/4 of a pixel in unnormalized coordinates). This means a point size of 1.0 will not reach the sampling
7462  * points at the pixel center of the edge pixels, but a point size of 2.0 will.
7463 */
7464 /*
7465     +----------+----------+----------+----------+
7466     |          |          |          |          |
7467     |          |          |          |          |
7468     |     x    |     x    |     x    |     x    |
7469     |          |          |          |          |
7470     |          |          |          |          |
7471     +----------+----------+----------+----------+
7472     |          |          |          |          |
7473     |          | +--------+--------+ |          |
7474     |     x    | |        |        | |     x    |
7475     |          | |        |        | |          |
7476     |          | |        |        | |          |
7477     +----------+-+--------+--------+-+----------+
7478     |          | |        |        | |          |
7479     |          | |        |        | |          |
7480     |     x    | |        |        | |     x    |
7481     |          | +--------+--------+ |          |
7482     |          |          |          |          |
7483     +----------+----------+----------+----------+
7484     |          |          |          |          |
7485     |          |          |          |          |
7486     |     x    |     x    |     x    |     x    |
7487     |          |          |          |          |
7488     |          |          |          |          |
7489     +----------+----------+----------+----------+
7490 */
iterate(void)7491 tcu::TestStatus PolygonModeLargePointsInstance::iterate (void)
7492 {
7493 	const auto&			vkd				= m_context.getDeviceInterface();
7494 	const auto			device			= m_context.getDevice();
7495 	auto&				alloc			= m_context.getDefaultAllocator();
7496 	const auto			queue			= m_context.getUniversalQueue();
7497 	const auto			qfIndex			= m_context.getUniversalQueueFamilyIndex();
7498 
7499 	const auto			colorFormat		= VK_FORMAT_R8G8B8A8_UNORM;
7500 	const auto			tcuFormat		= mapVkFormat(colorFormat);
7501 	const auto			colorExtent		= makeExtent3D(4u, 4u, 1u);
7502 	const tcu::IVec3	colorIExtent	(static_cast<int>(colorExtent.width), static_cast<int>(colorExtent.height), static_cast<int>(colorExtent.depth));
7503 	const auto			colorUsage		= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
7504 	const auto			colorSRR		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
7505 	const auto			colorSRL		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
7506 	const tcu::Vec4		clearColor		(0.0f, 0.0f, 0.0f, 1.0f);
7507 
7508 	// Color buffer.
7509 	const VkImageCreateInfo colorBufferCreateInfo =
7510 	{
7511 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
7512 		nullptr,								//	const void*				pNext;
7513 		0u,										//	VkImageCreateFlags		flags;
7514 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
7515 		colorFormat,							//	VkFormat				format;
7516 		colorExtent,							//	VkExtent3D				extent;
7517 		1u,										//	uint32_t				mipLevels;
7518 		1u,										//	uint32_t				arrayLayers;
7519 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
7520 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
7521 		colorUsage,								//	VkImageUsageFlags		usage;
7522 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
7523 		0u,										//	uint32_t				queueFamilyIndexCount;
7524 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
7525 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
7526 	};
7527 	ImageWithMemory colorBuffer (vkd, device, alloc, colorBufferCreateInfo, MemoryRequirement::Any);
7528 
7529 	const auto colorBufferView = makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR);
7530 
7531 	// Verification buffer.
7532 	const auto			pixelSize				= static_cast<VkDeviceSize>(tcuFormat.getPixelSize());
7533 	const auto			verificationBufferSize	= pixelSize * colorExtent.width * colorExtent.height * colorExtent.depth;
7534 	const auto			verificationBufferInfo	= makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
7535 	BufferWithMemory	verificationBuffer		(vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
7536 	auto&				verificationBufferAlloc	= verificationBuffer.getAllocation();
7537 
7538 	// Vertex buffer.
7539 	const float			insideMargin	= 0.125f;
7540 	const tcu::Vec4		topLeft			(-0.5f, -0.5f, 0.0f, 1.0f);
7541 	const tcu::Vec4		topRight		( 0.5f, -0.5f, 0.0f, 1.0f);
7542 	const tcu::Vec4		bottomLeft		(-0.5f,  0.5f, 0.0f, 1.0f);
7543 	const tcu::Vec4		bottomRight		( 0.5f,  0.5f, 0.0f, 1.0f);
7544 
7545 	const tcu::Vec4		actualTL		= topLeft + tcu::Vec4(insideMargin, insideMargin, 0.0f, 0.0f);
7546 	const tcu::Vec4		actualTR		= topRight + tcu::Vec4(-insideMargin, insideMargin, 0.0f, 0.0f);
7547 	const tcu::Vec4		actualBL		= bottomLeft + tcu::Vec4(insideMargin, -insideMargin, 0.0f, 0.0f);
7548 	const tcu::Vec4		actualBR		= bottomRight + tcu::Vec4(-insideMargin, -insideMargin, 0.0f, 0.0f);
7549 
7550 	const std::vector<tcu::Vec4> vertices
7551 	{
7552 		actualTL, actualTR, actualBL,
7553 		actualTR, actualBR, actualBL,
7554 	};
7555 
7556 	DE_ASSERT(de::sizeU32(vertices) == PolygonModeLargePointsCase::kNumPoints);
7557 
7558 	const auto			vertexBufferSize	= static_cast<VkDeviceSize>(de::dataSize(vertices));
7559 	const auto			vertexBufferUsage	= (m_config.meshShader ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
7560 	const auto			vertexBufferInfo	= makeBufferCreateInfo(vertexBufferSize, vertexBufferUsage);
7561 	BufferWithMemory	vertexBuffer		(vkd, device, alloc, vertexBufferInfo, MemoryRequirement::HostVisible);
7562 	auto&				vertexBufferAlloc	= vertexBuffer.getAllocation();
7563 	void*				vertexBufferData	= vertexBufferAlloc.getHostPtr();
7564 	const VkDeviceSize	vertexBufferOffset	= 0ull;
7565 
7566 	deMemcpy(vertexBufferData, vertices.data(), static_cast<size_t>(vertexBufferSize));
7567 	flushAlloc(vkd, device, vertexBufferAlloc);
7568 
7569 	// Pipeline layout.
7570 	DescriptorSetLayoutBuilder setLayoutBuilder;
7571 	if (m_config.meshShader)
7572 	{
7573 #ifndef CTS_USES_VULKANSC
7574 		setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_MESH_BIT_EXT);
7575 #else
7576 		DE_ASSERT(false);
7577 #endif // CTS_USES_VULKANSC
7578 	}
7579 	const auto setLayout		= setLayoutBuilder.build(vkd, device);
7580 	const auto pipelineLayout	= makePipelineLayout(vkd, device, setLayout.get());
7581 
7582 	// Descriptor pool and set if needed.
7583 	Move<VkDescriptorPool>	descriptorPool;
7584 	Move<VkDescriptorSet>	descriptorSet;
7585 	if (m_config.meshShader)
7586 	{
7587 		DescriptorPoolBuilder poolBuilder;
7588 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
7589 
7590 		descriptorPool	= poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
7591 		descriptorSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
7592 
7593 		DescriptorSetUpdateBuilder updateBuilder;
7594 		const auto vertexBufferDescInfo = makeDescriptorBufferInfo(vertexBuffer.get(), 0ull, vertexBufferSize);
7595 		updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &vertexBufferDescInfo);
7596 		updateBuilder.update(vkd, device);
7597 	}
7598 
7599 	// Render pass and framebuffer.
7600 	const auto renderPass	= makeRenderPass(vkd, device, colorFormat);
7601 	const auto framebuffer	= makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), colorExtent.width, colorExtent.height);
7602 
7603 	// Shader modules.
7604 	const auto&	binaries	= m_context.getBinaryCollection();
7605 	const auto	vertModule	= (!m_config.meshShader ? createShaderModule(vkd, device, binaries.get("vert")) : Move<VkShaderModule>());
7606 	const auto	meshModule	= (m_config.meshShader ? createShaderModule(vkd, device, binaries.get("mesh")) : Move<VkShaderModule>());
7607 	const auto	fragModule	= createShaderModule(vkd, device, binaries.get("frag"));
7608 	const auto	tescModule	= (m_config.tessellationShaders ? createShaderModule(vkd, device, binaries.get("tesc")) : Move<VkShaderModule>());
7609 	const auto	teseModule	= (m_config.tessellationShaders ? createShaderModule(vkd, device, binaries.get("tese")) : Move<VkShaderModule>());
7610 	const auto	geomModule	= (m_config.geometryShader ? createShaderModule(vkd, device, binaries.get("geom")) : Move<VkShaderModule>());
7611 
7612 	// Viewports and scissors.
7613 	const std::vector<VkViewport>	viewports	(1u, makeViewport(colorExtent));
7614 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(colorExtent));
7615 
7616 	// Rasterization state: key for the test. Rendering triangles as points.
7617 	const auto polygonMode = (m_config.dynamicPolygonMode ? VK_POLYGON_MODE_FILL : VK_POLYGON_MODE_POINT);
7618 	const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
7619 	{
7620 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
7621 		nullptr,													//	const void*								pNext;
7622 		0u,															//	VkPipelineRasterizationStateCreateFlags	flags;
7623 		VK_FALSE,													//	VkBool32								depthClampEnable;
7624 		VK_FALSE,													//	VkBool32								rasterizerDiscardEnable;
7625 		polygonMode,												//	VkPolygonMode							polygonMode;
7626 		VK_CULL_MODE_NONE,											//	VkCullModeFlags							cullMode;
7627 		VK_FRONT_FACE_CLOCKWISE,									//	VkFrontFace								frontFace;
7628 		VK_FALSE,													//	VkBool32								depthBiasEnable;
7629 		0.0f,														//	float									depthBiasConstantFactor;
7630 		0.0f,														//	float									depthBiasClamp;
7631 		0.0f,														//	float									depthBiasSlopeFactor;
7632 		1.0f,														//	float									lineWidth;
7633 	};
7634 
7635 	std::vector<VkDynamicState> dynamicStates;
7636 
7637 #ifndef CTS_USES_VULKANSC
7638 	if (m_config.dynamicPolygonMode)
7639 		dynamicStates.push_back(VK_DYNAMIC_STATE_POLYGON_MODE_EXT);
7640 #else
7641 	DE_ASSERT(false);
7642 #endif // CTS_USES_VULKANSC
7643 
7644 	const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
7645 	{
7646 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
7647 		nullptr,												//	const void*							pNext;
7648 		0u,														//	VkPipelineDynamicStateCreateFlags	flags;
7649 		de::sizeU32(dynamicStates),								//	uint32_t							dynamicStateCount;
7650 		de::dataOrNull(dynamicStates),							//	const VkDynamicState*				pDynamicStates;
7651 	};
7652 
7653 	const auto primitiveTopology	= (m_config.tessellationShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
7654 	const auto patchControlPoints	= (m_config.tessellationShaders ? 3u : 0u);
7655 
7656 	// Pipeline.
7657 	Move<VkPipeline> pipeline;
7658 
7659 	if (m_config.meshShader)
7660 	{
7661 #ifndef CTS_USES_VULKANSC
7662 		pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
7663 			VK_NULL_HANDLE, meshModule.get(), fragModule.get(),
7664 			renderPass.get(), viewports, scissors, 0u,
7665 			&rasterizationStateInfo, nullptr, nullptr, nullptr, &dynamicStateInfo);
7666 #else
7667 		DE_ASSERT(false);
7668 #endif // CTS_USES_VULKANSC
7669 	}
7670 	else
7671 	{
7672 		pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
7673 			vertModule.get(), tescModule.get(), teseModule.get(), geomModule.get(), fragModule.get(),
7674 			renderPass.get(), viewports, scissors, primitiveTopology, 0u, patchControlPoints,
7675 			nullptr, &rasterizationStateInfo, nullptr, nullptr, nullptr, &dynamicStateInfo);
7676 	}
7677 
7678 	// Command pool and buffer, render and verify results.
7679 	const auto cmdPool = makeCommandPool(vkd, device, qfIndex);
7680 	const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
7681 	const auto cmdBuffer = cmdBufferPtr.get();
7682 
7683 	beginCommandBuffer(vkd, cmdBuffer);
7684 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
7685 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
7686 
7687 	if (m_config.meshShader)
7688 		vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
7689 	else
7690 		vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
7691 
7692 	if (m_config.dynamicPolygonMode)
7693 	{
7694 #ifndef CTS_USES_VULKANSC
7695 		vkd.cmdSetPolygonModeEXT(cmdBuffer, VK_POLYGON_MODE_POINT);
7696 #else
7697 		DE_ASSERT(false);
7698 #endif // CTS_USES_VULKANSC
7699 	}
7700 
7701 	if (m_config.meshShader)
7702 #ifndef CTS_USES_VULKANSC
7703 		vkd.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
7704 #else
7705 		DE_ASSERT(false);
7706 #endif // CTS_USES_VULKANSC
7707 	else
7708 		vkd.cmdDraw(cmdBuffer, de::sizeU32(vertices), 1u, 0u, 0u);
7709 
7710 	endRenderPass(vkd, cmdBuffer);
7711 
7712 	// Copy image to verification buffer.
7713 	const auto preTransferBarrier = makeImageMemoryBarrier(
7714 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
7715 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
7716 		colorBuffer.get(), colorSRR);
7717 
7718 	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preTransferBarrier);
7719 
7720 	const auto copyRegion = makeBufferImageCopy(colorExtent, colorSRL);
7721 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
7722 
7723 	const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
7724 	cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &preHostBarrier);
7725 
7726 	endCommandBuffer(vkd, cmdBuffer);
7727 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
7728 
7729 	// Check results.
7730 	invalidateAlloc(vkd, device, verificationBufferAlloc);
7731 
7732 	const tcu::PixelBufferAccess	resultAccess	(tcuFormat, colorIExtent, verificationBufferAlloc.getHostPtr());
7733 	tcu::TextureLevel				referenceLevel	(tcuFormat, colorIExtent.x(), colorIExtent.y(), colorIExtent.z());
7734 	const tcu::PixelBufferAccess	referenceAccess	= referenceLevel.getAccess();
7735 	const tcu::Vec4					threshold		(0.0f, 0.0f, 0.0f, 0.0f);
7736 #ifndef CTS_USES_VULKANSC
7737 	const auto&						m5Properties	= m_context.getMaintenance5Properties();
7738 	// If testing default size means we are not setting the point size in shaders, and therefore we don't care about m5Properties.polygonModePointSize
7739 	// Default size is 1.0f, so we should only take the border into account
7740 	const bool						pointSizeUsed	= m_config.defaultSize ? false : m5Properties.polygonModePointSize;
7741 #else
7742 	const bool						pointSizeUsed	= false;
7743 #endif // CTS_USES_VULKANSC
7744 
7745 	// Prepare reference color image, which depends on VkPhysicalDeviceMaintenance5PropertiesKHR::polygonModePointSize.
7746 	DE_ASSERT(referenceAccess.getDepth() == 1);
7747 	for (int y = 0; y < referenceAccess.getHeight(); ++y)
7748 		for (int x = 0; x < referenceAccess.getWidth(); ++x)
7749 		{
7750 			const bool border	= (x == 0 || y == 0 || x == referenceAccess.getWidth() - 1 || y == referenceAccess.getHeight() - 1);
7751 			const auto color	= ((border && !pointSizeUsed) ? clearColor : PolygonModeLargePointsCase::geometryColor);
7752 			referenceAccess.setPixel(color, x, y);
7753 		}
7754 
7755 	if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Result", "", referenceAccess, resultAccess, threshold, tcu::COMPARE_LOG_ON_ERROR))
7756 		return tcu::TestStatus::fail("Color buffer contents do not match expected result -- check log for details");
7757 
7758 	return tcu::TestStatus::pass("Pass");
7759 }
7760 
7761 template <typename ConcreteTestInstance>
7762 class NonStrictLinesMaintenance5TestCase : public BaseRenderingTestCase
7763 {
7764 public:
NonStrictLinesMaintenance5TestCase(tcu::TestContext & context,const std::string & name,PrimitiveWideness wideness)7765 					NonStrictLinesMaintenance5TestCase	(tcu::TestContext&		context,
7766 														 const std::string&		name,
7767 														 PrimitiveWideness		wideness)
7768 						: BaseRenderingTestCase	(context, name, VK_SAMPLE_COUNT_1_BIT)
7769 						, m_wideness			(wideness) {}
createInstance(Context & context) const7770 	virtual auto	createInstance						(Context& context) const -> TestInstance* override
7771 														{
7772 															return new ConcreteTestInstance(context, m_wideness, 0);
7773 														}
checkSupport(Context & context) const7774 	virtual	auto	checkSupport						(Context& context) const -> void override
7775 														{
7776 															context.requireDeviceFunctionality("VK_KHR_maintenance5");
7777 
7778 															if (context.getDeviceProperties().limits.strictLines)
7779 																TCU_THROW(NotSupportedError, "Nonstrict rasterization is not supported");
7780 
7781 															if (m_wideness == PRIMITIVEWIDENESS_WIDE)
7782 																context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_WIDE_LINES);
7783 														}
7784 protected:
7785 	const PrimitiveWideness		m_wideness;
7786 
7787 	friend class NonStrictLinesMaintenance5TestInstance;
7788 	friend class NonStrictLineStripMaintenance5TestInstance;
7789 	static bool		compareAndVerify					(Context&								context,
7790 														 BaseLineTestInstance*					lineInstance,
7791 														 bool									isStrip,
7792 														 bool									isWide,
7793 														 std::vector<LineSceneSpec::SceneLine>&	lines,
7794 														 tcu::Surface&							resultImage,
7795 														 std::vector<tcu::Vec4>&				/* drawBuffer */);
7796 };
7797 
7798 template<class X>
compareAndVerify(Context & context,BaseLineTestInstance * lineInstance,bool isStrip,bool isWide,std::vector<LineSceneSpec::SceneLine> & lines,tcu::Surface & resultImage,std::vector<tcu::Vec4> &)7799 bool NonStrictLinesMaintenance5TestCase<X>::compareAndVerify (Context&									context,
7800 															  BaseLineTestInstance*						lineInstance,
7801 															  bool										isStrip,
7802 															  bool										isWide,
7803 															  std::vector<LineSceneSpec::SceneLine>&	lines,
7804 															  tcu::Surface&								resultImage,
7805 															  std::vector<tcu::Vec4>&)
7806 {
7807 	const tcu::IVec4		colorBits	= tcu::getTextureFormatBitDepth(lineInstance->getTextureFormat());
7808 
7809 	RasterizationArguments	args;
7810 	args.numSamples		= 0;
7811 	args.subpixelBits	= context.getDeviceProperties().limits.subPixelPrecisionBits;
7812 	args.redBits		= colorBits[0];
7813 	args.greenBits		= colorBits[1];
7814 	args.blueBits		= colorBits[2];
7815 
7816 	LineSceneSpec			scene;
7817 	scene.lines.swap(lines);
7818 	scene.lineWidth			= lineInstance->getLineWidth();
7819 	scene.stippleEnable		= false;
7820 	scene.stippleFactor		= 1;
7821 	scene.stipplePattern	= 0xFFFF;
7822 	scene.isStrip			= isStrip;
7823 	scene.isSmooth			= false;
7824 	scene.isRectangular		= false;
7825 	scene.verificationMode	= tcu::VERIFICATIONMODE_STRICT;
7826 
7827 	bool			result				= false;
7828 	const bool		strict				= false;
7829 	tcu::TestLog&	log					= context.getTestContext().getLog();
7830 	const bool		algoBresenhan		= verifyLineGroupRasterization(resultImage, scene, args, log);
7831 	const bool		algoParallelogram	= verifyRelaxedLineGroupRasterization(resultImage, scene, args, log, true, strict);
7832 
7833 #ifndef CTS_USES_VULKANSC
7834 	const VkPhysicalDeviceMaintenance5PropertiesKHR& p = context.getMaintenance5Properties();
7835 	if (isWide)
7836 	{
7837 		// nonStrictWideLinesUseParallelogram is a boolean value indicating whether non-strict lines
7838 		// with a width greater than 1.0 are rasterized as parallelograms or using Bresenham's algorithm.
7839 		result = p.nonStrictWideLinesUseParallelogram ? algoParallelogram : algoBresenhan;
7840 	}
7841 	else
7842 	{
7843 		// nonStrictSinglePixelWideLinesUseParallelogram is a boolean value indicating whether
7844 		// non-strict lines with a width of 1.0 are rasterized as parallelograms or using Bresenham's algorithm.
7845 		result = p.nonStrictSinglePixelWideLinesUseParallelogram ? algoParallelogram : algoBresenhan;
7846 	}
7847 #else
7848 	DE_UNREF(isWide);
7849 	DE_UNREF(algoBresenhan);
7850 	DE_UNREF(algoParallelogram);
7851 #endif
7852 
7853 	return result;
7854 }
7855 
7856 
7857 class NonStrictLinesMaintenance5TestInstance : public LinesTestInstance
7858 {
7859 public:
NonStrictLinesMaintenance5TestInstance(Context & context,PrimitiveWideness wideness,deUint32 additionalRenderSize)7860 					NonStrictLinesMaintenance5TestInstance (Context& context, PrimitiveWideness wideness, deUint32 additionalRenderSize)
7861 						: LinesTestInstance	(context, wideness, PRIMITIVESTRICTNESS_NONSTRICT, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST, LineStippleFactorCase::DEFAULT, additionalRenderSize)
7862 						, m_amIWide			(PRIMITIVEWIDENESS_WIDE == wideness)
7863 					{}
7864 protected:
compareAndVerify(std::vector<LineSceneSpec::SceneLine> & lines,tcu::Surface & resultImage,std::vector<tcu::Vec4> & drawBuffer)7865 	virtual bool	compareAndVerify						(std::vector<LineSceneSpec::SceneLine>&	lines,
7866 															 tcu::Surface&							resultImage,
7867 															 std::vector<tcu::Vec4>&				drawBuffer)
7868 					{
7869 						return NonStrictLinesMaintenance5TestCase<NonStrictLinesMaintenance5TestInstance>::compareAndVerify(
7870 							m_context, this, false, m_amIWide, lines, resultImage, drawBuffer);
7871 					}
7872 private:
7873 	const bool	m_amIWide;
7874 };
7875 
7876 class NonStrictLineStripMaintenance5TestInstance : public LineStripTestInstance
7877 {
7878 public:
NonStrictLineStripMaintenance5TestInstance(Context & context,PrimitiveWideness wideness,deUint32 additionalRenderSize)7879 					NonStrictLineStripMaintenance5TestInstance	(Context& context, PrimitiveWideness wideness, deUint32 additionalRenderSize)
7880 						: LineStripTestInstance	(context, wideness, PRIMITIVESTRICTNESS_NONSTRICT, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST, LineStippleFactorCase::DEFAULT, additionalRenderSize)
7881 						, m_amIWide				(PRIMITIVEWIDENESS_WIDE == wideness)
7882 					{}
7883 protected:
compareAndVerify(std::vector<LineSceneSpec::SceneLine> & lines,tcu::Surface & resultImage,std::vector<tcu::Vec4> & drawBuffer)7884 	virtual bool	compareAndVerify							(std::vector<LineSceneSpec::SceneLine>&	lines,
7885 																 tcu::Surface&							resultImage,
7886 																 std::vector<tcu::Vec4>&				drawBuffer)
7887 					{
7888 						return NonStrictLinesMaintenance5TestCase<NonStrictLineStripMaintenance5TestInstance>::compareAndVerify(
7889 							m_context, this, true, m_amIWide, lines, resultImage, drawBuffer);
7890 					}
7891 private:
7892 	const bool	m_amIWide;
7893 };
7894 
createRasterizationTests(tcu::TestCaseGroup * rasterizationTests)7895 void createRasterizationTests (tcu::TestCaseGroup* rasterizationTests)
7896 {
7897 	tcu::TestContext&	testCtx		=	rasterizationTests->getTestContext();
7898 
7899 	const struct
7900 	{
7901 		LineStippleFactorCase	stippleFactor;
7902 		const std::string		nameSuffix;
7903 	} stippleFactorCases[] =
7904 	{
7905 		{ LineStippleFactorCase::DEFAULT,	""},
7906 		//  and use zero as the line stipple factor
7907 		{ LineStippleFactorCase::ZERO,		"_factor_0"},
7908 		//  and use a large number as the line stipple factor
7909 		{ LineStippleFactorCase::LARGE,		"_factor_large"},
7910 	};
7911 
7912 	// .primitives
7913 	{
7914 		tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, "primitives");
7915 
7916 		rasterizationTests->addChild(primitives);
7917 
7918 		tcu::TestCaseGroup* const nostippleTests = new tcu::TestCaseGroup(testCtx, "no_stipple");
7919 		tcu::TestCaseGroup* const stippleStaticTests = new tcu::TestCaseGroup(testCtx, "static_stipple");
7920 		tcu::TestCaseGroup* const stippleDynamicTests = new tcu::TestCaseGroup(testCtx, "dynamic_stipple");
7921 #ifndef CTS_USES_VULKANSC
7922 		tcu::TestCaseGroup* const stippleDynamicTopoTests = new tcu::TestCaseGroup(testCtx, "dynamic_stipple_and_topology");
7923 #endif // CTS_USES_VULKANSC
7924 		tcu::TestCaseGroup* const strideZeroTests = new tcu::TestCaseGroup(testCtx, "stride_zero");
7925 
7926 		primitives->addChild(nostippleTests);
7927 		primitives->addChild(stippleStaticTests);
7928 		primitives->addChild(stippleDynamicTests);
7929 #ifndef CTS_USES_VULKANSC
7930 		primitives->addChild(stippleDynamicTopoTests);
7931 #endif // CTS_USES_VULKANSC
7932 		primitives->addChild(strideZeroTests);
7933 
7934 		// .stride_zero
7935 		{
7936 			{
7937 				StrideZeroCase::Params params;
7938 				params.bufferData.emplace_back(-StrideZeroCase::kCornerDelta, -StrideZeroCase::kCornerDelta);
7939 				params.drawVertexCount = 1u;
7940 				// Attempt to draw 1 point with stride 0
7941 				strideZeroTests->addChild(new StrideZeroCase(testCtx, "single_point", params));
7942 			}
7943 			{
7944 				StrideZeroCase::Params params;
7945 				params.bufferData.emplace_back(-StrideZeroCase::kCornerDelta, -StrideZeroCase::kCornerDelta);
7946 				params.bufferData.emplace_back( StrideZeroCase::kCornerDelta, -StrideZeroCase::kCornerDelta);
7947 				params.bufferData.emplace_back(-StrideZeroCase::kCornerDelta,  StrideZeroCase::kCornerDelta);
7948 				params.bufferData.emplace_back( StrideZeroCase::kCornerDelta,  StrideZeroCase::kCornerDelta);
7949 				params.drawVertexCount = static_cast<deUint32>(params.bufferData.size());
7950 				// Attempt to draw 4 points with stride 0 and 4 points in the buffer
7951 				strideZeroTests->addChild(new StrideZeroCase(testCtx, "four_points", params));
7952 			}
7953 			{
7954 				StrideZeroCase::Params params;
7955 				params.bufferData.emplace_back(-StrideZeroCase::kCornerDelta, -StrideZeroCase::kCornerDelta);
7956 				params.drawVertexCount = 100000u;
7957 				// Attempt to draw many points with stride 0 with one point in the buffer
7958 				strideZeroTests->addChild(new StrideZeroCase(testCtx, "many_points", params));
7959 			}
7960 		}
7961 
7962 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result
7963 		nostippleTests->addChild(new BaseTestCase<TrianglesTestInstance>		(testCtx, "triangles"));
7964 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, verify rasterization result
7965 		nostippleTests->addChild(new BaseTestCase<TriangleStripTestInstance>	(testCtx, "triangle_strip"));
7966 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, verify rasterization result
7967 		nostippleTests->addChild(new BaseTestCase<TriangleFanTestInstance>		(testCtx, "triangle_fan"));
7968 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result
7969 		nostippleTests->addChild(new WidenessTestCase<PointTestInstance>		(testCtx, "points", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, false, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
7970 
7971 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in strict mode, verify rasterization result
7972 		nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "strict_lines", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7973 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP in strict mode, verify rasterization result
7974 		nostippleTests->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "strict_line_strip", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7975 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in strict mode with wide lines, verify rasterization result
7976 		nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "strict_lines_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7977 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP in strict mode with wide lines, verify rasterization result
7978 		nostippleTests->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "strict_line_strip_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7979 
7980 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode, verify rasterization result
7981 		nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "non_strict_lines", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_NONSTRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7982 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP in nonstrict mode, verify rasterization result
7983 		nostippleTests->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "non_strict_line_strip", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_NONSTRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7984 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode with wide lines, verify rasterization result
7985 		nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "non_strict_lines_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_NONSTRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7986 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP in nonstrict mode with wide lines, verify rasterization result
7987 		nostippleTests->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "non_strict_line_strip_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_NONSTRICT, true, VK_SAMPLE_COUNT_1_BIT, LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
7988 
7989 		for (int i = 0; i < static_cast<int>(LINESTIPPLE_LAST); ++i) {
7990 
7991 			LineStipple stipple = (LineStipple)i;
7992 
7993 #ifdef CTS_USES_VULKANSC
7994 			if (stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY)
7995 				continue;
7996 #endif // CTS_USES_VULKANSC
7997 
7998 			tcu::TestCaseGroup *g	= (stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY)
7999 #ifndef CTS_USES_VULKANSC
8000 									? stippleDynamicTopoTests
8001 #else
8002 									? nullptr // Note this is actually unused, due to the continue statement above.
8003 #endif // CTS_USES_VULKANSC
8004 									: (stipple == LINESTIPPLE_DYNAMIC)
8005 									? stippleDynamicTests
8006 									: (stipple == LINESTIPPLE_STATIC)
8007 									? stippleStaticTests
8008 									: nostippleTests;
8009 
8010 			for (const auto& sfCase : stippleFactorCases)
8011 			{
8012 				if (sfCase.stippleFactor != LineStippleFactorCase::DEFAULT && stipple != LINESTIPPLE_DISABLED)
8013 					continue;
8014 
8015 				const auto& factor		= sfCase.stippleFactor;
8016 				const auto& suffix		= sfCase.nameSuffix;
8017 
8018 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result
8019 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "lines" + suffix,						PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT, factor, i == 0 ? RESOLUTION_NPOT : 0));
8020 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result
8021 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "line_strip" + suffix,						PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT, factor));
8022 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result
8023 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "lines_wide" + suffix,		PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT, factor));
8024 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result
8025 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "line_strip_wide" + suffix,		PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT, factor));
8026 
8027 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result
8028 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "rectangular_lines" + suffix,						PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT, factor));
8029 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result
8030 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "rectangular_line_strip" + suffix,						PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT, factor));
8031 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result
8032 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "rectangular_lines_wide" + suffix,		PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT, factor));
8033 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result
8034 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "rectangular_line_strip_wide" + suffix,		PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT, factor));
8035 
8036 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result
8037 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "bresenham_lines" + suffix,						PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT, factor));
8038 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result
8039 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "bresenham_line_strip" + suffix,						PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT, factor));
8040 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result
8041 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "bresenham_lines_wide" + suffix,		PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT, factor));
8042 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result
8043 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "bresenham_line_strip_wide" + suffix,		PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT, factor));
8044 
8045 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result
8046 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "smooth_lines" + suffix,						PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT, factor));
8047 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result
8048 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "smooth_line_strip" + suffix,						PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT, factor));
8049 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result
8050 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "smooth_lines_wide" + suffix,		PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT, factor));
8051 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result
8052 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "smooth_line_strip_wide" + suffix,		PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, VK_SAMPLE_COUNT_1_BIT, stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT, factor));
8053 			}
8054 		}
8055 	}
8056 
8057 	// .primitive_size
8058 	{
8059 		tcu::TestCaseGroup* const primitiveSize = new tcu::TestCaseGroup(testCtx, "primitive_size");
8060 		rasterizationTests->addChild(primitiveSize);
8061 
8062 		// .points
8063 		{
8064 			tcu::TestCaseGroup* const points = new tcu::TestCaseGroup(testCtx, "points");
8065 
8066 			static const struct TestCombinations
8067 			{
8068 				const deUint32	renderSize;
8069 				const float		pointSize;
8070 			} testCombinations[] =
8071 			{
8072 				{ 1024,		128.0f		},
8073 				{ 1024,		256.0f		},
8074 				{ 1024,		512.0f		},
8075 				{ 2048,		1024.0f		},
8076 				{ 4096,		2048.0f		},
8077 				{ 8192,		4096.0f		},
8078 				{ 9216,		8192.0f		},
8079 				{ 10240,	10000.0f	}
8080 			};
8081 
8082 			for (size_t testCombNdx = 0; testCombNdx < DE_LENGTH_OF_ARRAY(testCombinations); testCombNdx++)
8083 			{
8084 				std::string	testCaseName	= "point_size_" + de::toString(testCombinations[testCombNdx].pointSize);
8085 				deUint32	renderSize		= testCombinations[testCombNdx].renderSize;
8086 				float		pointSize		= testCombinations[testCombNdx].pointSize;
8087 
8088 				points->addChild(new PointSizeTestCase<PointSizeTestInstance>	(testCtx, testCaseName, renderSize, pointSize));
8089 			}
8090 
8091 			primitiveSize->addChild(points);
8092 		}
8093 
8094 		// .default_size
8095 		{
8096 			// Default size
8097 			tcu::TestCaseGroup* const defaultSize	= new tcu::TestCaseGroup(testCtx, "default_size");
8098 
8099 			// .points
8100 			{
8101 				tcu::TestCaseGroup* const points						= new tcu::TestCaseGroup(testCtx, "points", "Default point size");
8102 				static const VkShaderStageFlags vertexStageBits			= VK_SHADER_STAGE_VERTEX_BIT;
8103 				static const VkShaderStageFlags tessellationStageBits	= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
8104 				static const VkShaderStageFlags geometryStageBits		= VK_SHADER_STAGE_GEOMETRY_BIT;
8105 				static const struct PointDefaultSizeCombination
8106 				{
8107 					const VkShaderStageFlags stageFlags;
8108 					const std::string stageName;
8109 				} pointDefaultSizeCombinations[] =
8110 				{
8111 					{ vertexStageBits, "vertex" },
8112 					{ vertexStageBits | tessellationStageBits, "tessellation" },
8113 					{ vertexStageBits | geometryStageBits, "geometry" },
8114 					{ vertexStageBits | tessellationStageBits | geometryStageBits, "all" },
8115 				};
8116 
8117 				for (size_t testCombNdx = 0u; testCombNdx < DE_LENGTH_OF_ARRAY(pointDefaultSizeCombinations); testCombNdx++)
8118 				{
8119 					const std::string			testCaseName		= pointDefaultSizeCombinations[testCombNdx].stageName;
8120 					const VkShaderStageFlags	testStageFlags		= pointDefaultSizeCombinations[testCombNdx].stageFlags;
8121 					const deUint32				renderSize			= 3u;	// Odd number so only the center pixel is rendered
8122 
8123 					points->addChild(new PointDefaultSizeTestCase(testCtx, testCaseName, renderSize, testStageFlags));
8124 				}
8125 
8126 				defaultSize->addChild(points);
8127 			}
8128 
8129 #ifndef CTS_USES_VULKANSC
8130 			// .polygons_as_points
8131 			{
8132 				tcu::TestCaseGroup* const polygonsAsPoints = new tcu::TestCaseGroup(testCtx, "polygon_as_points", "Default point size for polygons as points");
8133 				for (int k = 0; k < 2; ++k)
8134 				{
8135 					for (int j = 0; j < 2; ++j)
8136 					{
8137 						for (int i = 0; i < 2; ++i)
8138 						{
8139 							for (int m = 0; m < 2; ++m)
8140 							{
8141 								const bool	meshShader		= (m > 0);
8142 								const bool	tessellation	= (i > 0);
8143 								const bool	geometryShader	= (j > 0);
8144 								const bool	dynamicPolyMode	= (k > 0);
8145 
8146 								if (meshShader && (tessellation || geometryShader))
8147 									continue;
8148 
8149 								std::string	testName		(meshShader ? "mesh" : "vert");
8150 
8151 								if (tessellation)
8152 									testName += "_tess";
8153 
8154 								if (geometryShader)
8155 									testName += "_geom";
8156 
8157 								testName += (dynamicPolyMode ? "_dynamic_polygon_mode" : "_static_polygon_mode");
8158 
8159 								PolygonModeLargePointsConfig config(1.0f, meshShader, tessellation, geometryShader, dynamicPolyMode, true);
8160 								polygonsAsPoints->addChild(new PolygonModeLargePointsCase(testCtx, testName, config));
8161 							}
8162 						}
8163 					}
8164 				}
8165 
8166 				defaultSize->addChild(polygonsAsPoints);
8167 			}
8168 #endif
8169 
8170 			primitiveSize->addChild(defaultSize);
8171 		}
8172 	}
8173 
8174 #ifndef CTS_USES_VULKANSC
8175 	// .polygon_as_large_points
8176 	{
8177 		de::MovePtr<tcu::TestCaseGroup> polygonModeLargePointsGroup (new tcu::TestCaseGroup(testCtx, "polygon_as_large_points", "Test polygons rendered as large points"));
8178 
8179 		for (int k = 0; k < 2; ++k)
8180 			for (int j = 0; j < 2; ++j)
8181 				for (int i = 0; i < 2; ++i)
8182 					for (int m = 0; m < 2; ++m)
8183 					{
8184 						const bool	meshShader		= (m > 0);
8185 						const bool	tessellation	= (i > 0);
8186 						const bool	geometryShader	= (j > 0);
8187 						const bool	dynamicPolyMode	= (k > 0);
8188 
8189 						if (meshShader && (tessellation || geometryShader))
8190 							continue;
8191 
8192 						std::string	testName		(meshShader ? "mesh" : "vert");
8193 
8194 						if (tessellation)
8195 							testName += "_tess";
8196 
8197 						if (geometryShader)
8198 							testName += "_geom";
8199 
8200 						testName += (dynamicPolyMode ? "_dynamic_polygon_mode" : "_static_polygon_mode");
8201 
8202 						PolygonModeLargePointsConfig config(2.0f, meshShader, tessellation, geometryShader, dynamicPolyMode);
8203 						polygonModeLargePointsGroup->addChild(new PolygonModeLargePointsCase(testCtx, testName, config));
8204 					}
8205 
8206 		rasterizationTests->addChild(polygonModeLargePointsGroup.release());
8207 	}
8208 #endif // CTS_USES_VULKANSC
8209 
8210 	// .fill_rules
8211 	{
8212 		tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, "fill_rules");
8213 
8214 		rasterizationTests->addChild(fillRules);
8215 
8216 		fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad",	FillRuleTestInstance::FILLRULECASE_BASIC));
8217 		fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad_reverse",	FillRuleTestInstance::FILLRULECASE_REVERSED));
8218 		fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_full",	FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL));
8219 		fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_partly",	FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL));
8220 		fillRules->addChild(new FillRuleTestCase(testCtx,	"projected",	FillRuleTestInstance::FILLRULECASE_PROJECTED));
8221 	}
8222 
8223 	// .culling
8224 	{
8225 		static const struct CullMode
8226 		{
8227 			VkCullModeFlags	mode;
8228 			const char*		prefix;
8229 		} cullModes[] =
8230 		{
8231 			{ VK_CULL_MODE_FRONT_BIT,				"front_"	},
8232 			{ VK_CULL_MODE_BACK_BIT,				"back_"		},
8233 			{ VK_CULL_MODE_FRONT_AND_BACK,			"both_"		},
8234 		};
8235 		static const struct PrimitiveType
8236 		{
8237 			VkPrimitiveTopology	type;
8238 			const char*			name;
8239 		} primitiveTypes[] =
8240 		{
8241 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,			"triangles"			},
8242 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,			"triangle_strip"	},
8243 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,			"triangle_fan"		},
8244 		};
8245 		static const struct FrontFaceOrder
8246 		{
8247 			VkFrontFace	mode;
8248 			const char*	postfix;
8249 		} frontOrders[] =
8250 		{
8251 			{ VK_FRONT_FACE_COUNTER_CLOCKWISE,	""			},
8252 			{ VK_FRONT_FACE_CLOCKWISE,			"_reverse"	},
8253 		};
8254 
8255 		static const struct PolygonMode
8256 		{
8257 			VkPolygonMode	mode;
8258 			const char*		name;
8259 		} polygonModes[] =
8260 		{
8261 			{ VK_POLYGON_MODE_FILL,		""		},
8262 			{ VK_POLYGON_MODE_LINE,		"_line"		},
8263 			{ VK_POLYGON_MODE_POINT,	"_point"	}
8264 		};
8265 
8266 		tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(testCtx, "culling");
8267 
8268 		rasterizationTests->addChild(culling);
8269 
8270 		for (int cullModeNdx	= 0; cullModeNdx	< DE_LENGTH_OF_ARRAY(cullModes);		++cullModeNdx)
8271 		for (int primitiveNdx	= 0; primitiveNdx	< DE_LENGTH_OF_ARRAY(primitiveTypes);	++primitiveNdx)
8272 		for (int frontOrderNdx	= 0; frontOrderNdx	< DE_LENGTH_OF_ARRAY(frontOrders);		++frontOrderNdx)
8273 		for (int polygonModeNdx = 0; polygonModeNdx	< DE_LENGTH_OF_ARRAY(polygonModes);		++polygonModeNdx)
8274 		{
8275 			if (!(cullModes[cullModeNdx].mode == VK_CULL_MODE_FRONT_AND_BACK && polygonModes[polygonModeNdx].mode != VK_POLYGON_MODE_FILL))
8276 			{
8277 				const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix + polygonModes[polygonModeNdx].name;
8278 				// Test primitive culling.
8279 				culling->addChild(new CullingTestCase(testCtx, name, cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode, polygonModes[polygonModeNdx].mode));
8280 			}
8281 		}
8282 
8283 		// Cull some triangles and check primitive ID works
8284 		culling->addChild(new CullAndPrimitiveIdCase(testCtx, "primitive_id"));
8285 	}
8286 
8287 	// .discard
8288 	{
8289 		static const struct PrimitiveType
8290 		{
8291 			VkPrimitiveTopology	type;
8292 			const char*			name;
8293 		} primitiveTypes[] =
8294 		{
8295 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	"triangle_list"		},
8296 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	"triangle_strip"	},
8297 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,	"triangle_fan"		},
8298 			{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		"line_list"			},
8299 			{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		"line_strip"		},
8300 			{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST,		"point_list"		}
8301 		};
8302 
8303 		static const struct queryPipeline
8304 		{
8305 			deBool			useQuery;
8306 			const char*		name;
8307 		} queryPipeline[] =
8308 		{
8309 			{ DE_FALSE,	"query_pipeline_false"	},
8310 			{ DE_TRUE,	"query_pipeline_true"	},
8311 		};
8312 
8313 		tcu::TestCaseGroup* const discard = new tcu::TestCaseGroup(testCtx, "discard", "Rasterizer discard");
8314 
8315 		for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
8316 		{
8317 			tcu::TestCaseGroup* const primitive = new tcu::TestCaseGroup(testCtx, primitiveTypes[primitiveNdx].name);
8318 
8319 			for (int useQueryNdx = 0; useQueryNdx < DE_LENGTH_OF_ARRAY(queryPipeline); useQueryNdx++)
8320 			{
8321 				const std::string name = std::string(queryPipeline[useQueryNdx].name);
8322 				// Test primitive discarding.
8323 				primitive->addChild(new DiscardTestCase(testCtx, name, primitiveTypes[primitiveNdx].type, queryPipeline[useQueryNdx].useQuery));
8324 			}
8325 
8326 			discard->addChild(primitive);
8327 		}
8328 
8329 		rasterizationTests->addChild(discard);
8330 	}
8331 
8332 	// .conservative
8333 	{
8334 		typedef struct
8335 		{
8336 			float			size;
8337 			const char*		name;
8338 		} overestimateSizes;
8339 
8340 		const overestimateSizes overestimateNormalSizes[]	=
8341 		{
8342 			{ 0.00f,			"0_00" },
8343 			{ 0.25f,			"0_25" },
8344 			{ 0.50f,			"0_50" },
8345 			{ 0.75f,			"0_75" },
8346 			{ 1.00f,			"1_00" },
8347 			{ 2.00f,			"2_00" },
8348 			{ 4.00f,			"4_00" },
8349 			{ -TCU_INFINITY,	"min" },
8350 			{ TCU_INFINITY,		"max" },
8351 		};
8352 		const overestimateSizes overestimateDegenerate[]	=
8353 		{
8354 			{ 0.00f,			"0_00" },
8355 			{ 0.25f,			"0_25" },
8356 			{ -TCU_INFINITY,	"min" },
8357 			{ TCU_INFINITY,		"max" },
8358 		};
8359 		const overestimateSizes underestimateLineWidths[]	=
8360 		{
8361 			{ 0.50f,			"0_50" },
8362 			{ 1.00f,			"1_00" },
8363 			{ 1.50f,			"1_50" },
8364 		};
8365 		const overestimateSizes underestimatePointSizes[]	=
8366 		{
8367 			{ 1.00f,			"1_00" },
8368 			{ 1.50f,			"1_50" },
8369 			{ 2.00f,			"2_00" },
8370 			{ 3.00f,			"3_00" },
8371 			{ 4.00f,			"4_00" },
8372 			{ 8.00f,			"8_00" },
8373 		};
8374 		const struct PrimitiveType
8375 		{
8376 			VkPrimitiveTopology	type;
8377 			const char*			name;
8378 		}
8379 		primitiveTypes[] =
8380 		{
8381 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	"triangles"		},
8382 			{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		"lines"			},
8383 			{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST,		"points"		}
8384 		};
8385 		const VkSampleCountFlagBits samples[] =
8386 		{
8387 			VK_SAMPLE_COUNT_1_BIT,
8388 			VK_SAMPLE_COUNT_2_BIT,
8389 			VK_SAMPLE_COUNT_4_BIT,
8390 			VK_SAMPLE_COUNT_8_BIT,
8391 			VK_SAMPLE_COUNT_16_BIT,
8392 			VK_SAMPLE_COUNT_32_BIT,
8393 			VK_SAMPLE_COUNT_64_BIT
8394 		};
8395 
8396 		tcu::TestCaseGroup* const conservative = new tcu::TestCaseGroup(testCtx, "conservative", "Conservative rasterization tests");
8397 
8398 		rasterizationTests->addChild(conservative);
8399 
8400 		{
8401 			tcu::TestCaseGroup* const overestimate = new tcu::TestCaseGroup(testCtx, "overestimate", "Overestimate tests");
8402 
8403 			conservative->addChild(overestimate);
8404 
8405 			for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
8406 			{
8407 				const std::string samplesGroupName = "samples_" + de::toString(samples[samplesNdx]);
8408 
8409 				tcu::TestCaseGroup* const samplesGroup = new tcu::TestCaseGroup(testCtx, samplesGroupName.c_str(), "Samples tests");
8410 
8411 				overestimate->addChild(samplesGroup);
8412 
8413 				for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveTypeNdx)
8414 				{
8415 					tcu::TestCaseGroup* const primitiveGroup = new tcu::TestCaseGroup(testCtx, primitiveTypes[primitiveTypeNdx].name, "Primitive tests");
8416 
8417 					samplesGroup->addChild(primitiveGroup);
8418 
8419 					{
8420 						tcu::TestCaseGroup* const normal = new tcu::TestCaseGroup(testCtx, "normal", "Normal conservative rasterization tests");
8421 
8422 						primitiveGroup->addChild(normal);
8423 
8424 						for (int overestimateSizesNdx = 0; overestimateSizesNdx < DE_LENGTH_OF_ARRAY(overestimateNormalSizes); ++overestimateSizesNdx)
8425 						{
8426 							const ConservativeTestConfig	config	=
8427 							{
8428 								VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT,	//  VkConservativeRasterizationModeEXT	conservativeRasterizationMode;
8429 								overestimateNormalSizes[overestimateSizesNdx].size,		//  float								extraOverestimationSize;
8430 								primitiveTypes[primitiveTypeNdx].type,					//  VkPrimitiveTopology					primitiveTopology;
8431 								false,													//  bool								degeneratePrimitives;
8432 								1.0f,													//  float								lineWidth;
8433 								RESOLUTION_POT,											//  deUint32							resolution;
8434 							};
8435 
8436 							// Overestimate tests, verify rasterization result
8437 
8438 							if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
8439 								normal->addChild(new ConservativeTestCase<ConservativeTraingleTestInstance>	(testCtx,
8440 																											 overestimateNormalSizes[overestimateSizesNdx].name,
8441 																											 config,
8442 																											 samples[samplesNdx]));
8443 
8444 							if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_LINE_LIST)
8445 								normal->addChild(new ConservativeTestCase<ConservativeLineTestInstance>		(testCtx,
8446 																											 overestimateNormalSizes[overestimateSizesNdx].name,
8447 																											 config,
8448 																											 samples[samplesNdx]));
8449 
8450 							if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
8451 								normal->addChild(new ConservativeTestCase<ConservativePointTestInstance>	(testCtx,
8452 																											 overestimateNormalSizes[overestimateSizesNdx].name,
8453 																											 config,
8454 																											 samples[samplesNdx]));
8455 						}
8456 					}
8457 
8458 					{
8459 						tcu::TestCaseGroup* const degenerate = new tcu::TestCaseGroup(testCtx, "degenerate", "Degenerate primitives conservative rasterization tests");
8460 
8461 						primitiveGroup->addChild(degenerate);
8462 
8463 						for (int overestimateSizesNdx = 0; overestimateSizesNdx < DE_LENGTH_OF_ARRAY(overestimateDegenerate); ++overestimateSizesNdx)
8464 						{
8465 							const ConservativeTestConfig	config	=
8466 							{
8467 								VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT,	//  VkConservativeRasterizationModeEXT	conservativeRasterizationMode;
8468 								overestimateDegenerate[overestimateSizesNdx].size,		//  float								extraOverestimationSize;
8469 								primitiveTypes[primitiveTypeNdx].type,					//  VkPrimitiveTopology					primitiveTopology;
8470 								true,													//  bool								degeneratePrimitives;
8471 								1.0f,													//  float								lineWidth;
8472 								64u,													//  deUint32							resolution;
8473 							};
8474 
8475 							// Overestimate triangle test, verify rasterization result
8476 
8477 							if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
8478 								degenerate->addChild(new ConservativeTestCase<ConservativeTraingleTestInstance>	(testCtx,
8479 																												 overestimateDegenerate[overestimateSizesNdx].name,
8480 																												 config,
8481 																												 samples[samplesNdx]));
8482 
8483 							if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_LINE_LIST)
8484 								degenerate->addChild(new ConservativeTestCase<ConservativeLineTestInstance>		(testCtx,
8485 																												 overestimateDegenerate[overestimateSizesNdx].name,
8486 																												 config,
8487 																												 samples[samplesNdx]));
8488 						}
8489 					}
8490 				}
8491 			}
8492 		}
8493 
8494 		{
8495 			tcu::TestCaseGroup* const underestimate = new tcu::TestCaseGroup(testCtx, "underestimate", "Underestimate tests");
8496 
8497 			conservative->addChild(underestimate);
8498 
8499 			for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); ++samplesNdx)
8500 			{
8501 				const std::string samplesGroupName = "samples_" + de::toString(samples[samplesNdx]);
8502 
8503 				tcu::TestCaseGroup* const samplesGroup = new tcu::TestCaseGroup(testCtx, samplesGroupName.c_str(), "Samples tests");
8504 
8505 				underestimate->addChild(samplesGroup);
8506 
8507 				for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveTypeNdx)
8508 				{
8509 					tcu::TestCaseGroup* const primitiveGroup = new tcu::TestCaseGroup(testCtx, primitiveTypes[primitiveTypeNdx].name, "Primitive tests");
8510 
8511 					samplesGroup->addChild(primitiveGroup);
8512 
8513 					{
8514 						tcu::TestCaseGroup* const normal = new tcu::TestCaseGroup(testCtx, "normal", "Normal conservative rasterization tests");
8515 
8516 						primitiveGroup->addChild(normal);
8517 
8518 						ConservativeTestConfig	config	=
8519 						{
8520 							VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT,	//  VkConservativeRasterizationModeEXT	conservativeRasterizationMode;
8521 							0.0f,													//  float								extraOverestimationSize;
8522 							primitiveTypes[primitiveTypeNdx].type,					//  VkPrimitiveTopology					primitiveTopology;
8523 							false,													//  bool								degeneratePrimitives;
8524 							1.0f,													//  float								lineWidth;
8525 							64u,													//  deUint32							resolution;
8526 						};
8527 
8528 						// Underestimate test, verify rasterization result
8529 
8530 						if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
8531 							normal->addChild(new ConservativeTestCase<ConservativeTraingleTestInstance>	(testCtx,
8532 																										 "test",
8533 																										 config,
8534 																										 samples[samplesNdx]));
8535 
8536 						if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_LINE_LIST)
8537 						{
8538 							for (int underestimateWidthNdx = 0; underestimateWidthNdx < DE_LENGTH_OF_ARRAY(underestimateLineWidths); ++underestimateWidthNdx)
8539 							{
8540 								config.lineWidth = underestimateLineWidths[underestimateWidthNdx].size;
8541 								normal->addChild(new ConservativeTestCase<ConservativeLineTestInstance>		(testCtx,
8542 																											 underestimateLineWidths[underestimateWidthNdx].name,
8543 																											 config,
8544 																											 samples[samplesNdx]));
8545 							}
8546 						}
8547 
8548 						if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
8549 						{
8550 							for (int underestimatePointSizeNdx = 0; underestimatePointSizeNdx < DE_LENGTH_OF_ARRAY(underestimatePointSizes); ++underestimatePointSizeNdx)
8551 							{
8552 								config.lineWidth = underestimatePointSizes[underestimatePointSizeNdx].size;
8553 								normal->addChild(new ConservativeTestCase<ConservativePointTestInstance>	(testCtx,
8554 																											 underestimatePointSizes[underestimatePointSizeNdx].name,
8555 																											 config,
8556 																											 samples[samplesNdx]));
8557 							}
8558 						}
8559 					}
8560 
8561 					{	// Degenerate primitives conservative rasterization tests
8562 						tcu::TestCaseGroup* const degenerate = new tcu::TestCaseGroup(testCtx, "degenerate");
8563 
8564 						primitiveGroup->addChild(degenerate);
8565 
8566 						ConservativeTestConfig	config	=
8567 						{
8568 							VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT,	//  VkConservativeRasterizationModeEXT	conservativeRasterizationMode;
8569 							0.0f,													//  float								extraOverestimationSize;
8570 							primitiveTypes[primitiveTypeNdx].type,					//  VkPrimitiveTopology					primitiveTopology;
8571 							true,													//  bool								degeneratePrimitives;
8572 							1.0f,													//  float								lineWidth;
8573 							64u,													//  deUint32							resolution;
8574 						};
8575 
8576 						if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
8577 							// Underestimate triangle test, verify rasterization result
8578 							degenerate->addChild(new ConservativeTestCase<ConservativeTraingleTestInstance>	(testCtx,
8579 																											 "test", config,
8580 																											 samples[samplesNdx]));
8581 
8582 						if (primitiveTypes[primitiveTypeNdx].type == VK_PRIMITIVE_TOPOLOGY_LINE_LIST)
8583 						{
8584 							for (int underestimateWidthNdx = 0; underestimateWidthNdx < DE_LENGTH_OF_ARRAY(underestimateLineWidths); ++underestimateWidthNdx)
8585 							{
8586 								config.lineWidth = underestimateLineWidths[underestimateWidthNdx].size;
8587 								// Underestimate line test, verify rasterization result
8588 								degenerate->addChild(new ConservativeTestCase<ConservativeLineTestInstance>		(testCtx,
8589 																												 underestimateLineWidths[underestimateWidthNdx].name,
8590 																												 config,
8591 																												 samples[samplesNdx]));
8592 							}
8593 						}
8594 					}
8595 				}
8596 			}
8597 		}
8598 	}
8599 
8600 	// .interpolation
8601 	{
8602 		tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, "interpolation", "Test interpolation");
8603 
8604 		rasterizationTests->addChild(interpolation);
8605 
8606 		// .basic
8607 		{
8608 			tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(testCtx, "basic", "Non-projective interpolation");
8609 
8610 			interpolation->addChild(basic);
8611 
8612 			// Verify triangle interpolation
8613 			basic->addChild(new TriangleInterpolationTestCase		(testCtx, "triangles", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_NONE));
8614 			// Verify triangle strip interpolation
8615 			basic->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_strip", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_NONE));
8616 			// Verify triangle fan interpolation
8617 			basic->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_fan", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,		INTERPOLATIONFLAGS_NONE));
8618 			// Verify line interpolation
8619 			basic->addChild(new LineInterpolationTestCase			(testCtx, "lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE));
8620 			// Verify line strip interpolation
8621 			basic->addChild(new LineInterpolationTestCase			(testCtx, "line_strip", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE));
8622 			// Verify wide line interpolation
8623 			basic->addChild(new LineInterpolationTestCase			(testCtx, "lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE));
8624 			// Verify wide line strip interpolation
8625 			basic->addChild(new LineInterpolationTestCase			(testCtx, "line_strip_wide", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE));
8626 
8627 			// Verify strict line interpolation
8628 			basic->addChild(new LineInterpolationTestCase			(testCtx, "strict_lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,	INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT));
8629 			// Verify strict line strip interpolation
8630 			basic->addChild(new LineInterpolationTestCase			(testCtx, "strict_line_strip", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,	INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT));
8631 			// Verify strict wide line interpolation
8632 			basic->addChild(new LineInterpolationTestCase			(testCtx, "strict_lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,	INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT));
8633 			// Verify strict wide line strip interpolation
8634 			basic->addChild(new LineInterpolationTestCase			(testCtx, "strict_line_strip_wide", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,	INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT));
8635 
8636 			// Verify non-strict line interpolation
8637 			basic->addChild(new LineInterpolationTestCase			(testCtx, "non_strict_lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,	INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_NONSTRICT));
8638 			// Verify non-strict line strip interpolation
8639 			basic->addChild(new LineInterpolationTestCase			(testCtx, "non_strict_line_strip", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,	INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_NONSTRICT));
8640 			// Verify non-strict wide line interpolation
8641 			basic->addChild(new LineInterpolationTestCase			(testCtx, "non_strict_lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,	INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_NONSTRICT));
8642 			// Verify non-strict wide line strip interpolation
8643 			basic->addChild(new LineInterpolationTestCase			(testCtx, "non_strict_line_strip_wide", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,	INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_NONSTRICT));
8644 		}
8645 
8646 		// .projected
8647 		{
8648 			tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(testCtx, "projected", "Projective interpolation");
8649 
8650 			interpolation->addChild(projected);
8651 
8652 			// Verify triangle interpolation
8653 			projected->addChild(new TriangleInterpolationTestCase	(testCtx, "triangles", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_PROJECTED));
8654 			// Verify triangle strip interpolation
8655 			projected->addChild(new TriangleInterpolationTestCase	(testCtx, "triangle_strip", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_PROJECTED));
8656 			// Verify triangle fan interpolation
8657 			projected->addChild(new TriangleInterpolationTestCase	(testCtx, "triangle_fan", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,		INTERPOLATIONFLAGS_PROJECTED));
8658 			// Verify line interpolation
8659 			projected->addChild(new LineInterpolationTestCase		(testCtx, "lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE));
8660 			// Verify line strip interpolation
8661 			projected->addChild(new LineInterpolationTestCase		(testCtx, "line_strip", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE));
8662 			// Verify wide line interpolation
8663 			projected->addChild(new LineInterpolationTestCase		(testCtx, "lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE));
8664 			// Verify wide line strip interpolation
8665 			projected->addChild(new LineInterpolationTestCase		(testCtx, "line_strip_wide", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE));
8666 
8667 			// Verify strict line interpolation
8668 			projected->addChild(new LineInterpolationTestCase		(testCtx, "strict_lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT));
8669 			// Verify strict line strip interpolation
8670 			projected->addChild(new LineInterpolationTestCase		(testCtx, "strict_line_strip", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT));
8671 			// Verify strict wide line interpolation
8672 			projected->addChild(new LineInterpolationTestCase		(testCtx, "strict_lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT));
8673 			// Verify strict wide line strip interpolation
8674 			projected->addChild(new LineInterpolationTestCase		(testCtx, "strict_line_strip_wide", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT));
8675 
8676 			// Verify non-strict line interpolation
8677 			projected->addChild(new LineInterpolationTestCase		(testCtx, "non_strict_lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_NONSTRICT));
8678 			// Verify non-strict line strip interpolation
8679 			projected->addChild(new LineInterpolationTestCase		(testCtx, "non_strict_line_strip", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_NONSTRICT));
8680 			// Verify non-strict wide line interpolation
8681 			projected->addChild(new LineInterpolationTestCase		(testCtx, "non_strict_lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_NONSTRICT));
8682 			// Verify non-strict wide line strip interpolation
8683 			projected->addChild(new LineInterpolationTestCase		(testCtx, "non_strict_line_strip_wide", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_NONSTRICT));
8684 		}
8685 	}
8686 
8687 	// .flatshading
8688 	{
8689 		tcu::TestCaseGroup* const flatshading = new tcu::TestCaseGroup(testCtx, "flatshading", "Test flatshading");
8690 
8691 		rasterizationTests->addChild(flatshading);
8692 
8693 		// Verify triangle flatshading
8694 		flatshading->addChild(new TriangleInterpolationTestCase		(testCtx, "triangles", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_FLATSHADE));
8695 		// Verify triangle strip flatshading
8696 		flatshading->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_strip", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_FLATSHADE));
8697 		// Verify triangle fan flatshading
8698 		flatshading->addChild(new TriangleInterpolationTestCase		(testCtx, "triangle_fan", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,		INTERPOLATIONFLAGS_FLATSHADE));
8699 		// Verify line flatshading
8700 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE));
8701 		// Verify line strip flatshading
8702 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "line_strip", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE));
8703 		// Verify wide line flatshading
8704 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE));
8705 		// Verify wide line strip flatshading
8706 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "line_strip_wide", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE));
8707 
8708 		// Verify strict line flatshading
8709 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "strict_lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT));
8710 		// Verify strict line strip flatshading
8711 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "strict_line_strip", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT));
8712 		// Verify strict wide line flatshading
8713 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "strict_lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT));
8714 		// Verify strict wide line strip flatshading
8715 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "strict_line_strip_wide", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT));
8716 
8717 		// Verify non-strict line flatshading
8718 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "non_strict_lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_NONSTRICT));
8719 		// Verify non-strict line strip flatshading
8720 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "non_strict_line_strip", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_NONSTRICT));
8721 		// Verify non-strict wide line flatshading
8722 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "non_strict_lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_NONSTRICT));
8723 		// Verify non-strict wide line strip flatshading
8724 		flatshading->addChild(new LineInterpolationTestCase			(testCtx, "non_strict_line_strip_wide", VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_NONSTRICT));
8725 	}
8726 
8727 	const VkSampleCountFlagBits samples[] =
8728 	{
8729 		VK_SAMPLE_COUNT_2_BIT,
8730 		VK_SAMPLE_COUNT_4_BIT,
8731 		VK_SAMPLE_COUNT_8_BIT,
8732 		VK_SAMPLE_COUNT_16_BIT,
8733 		VK_SAMPLE_COUNT_32_BIT,
8734 		VK_SAMPLE_COUNT_64_BIT
8735 	};
8736 
8737 	for (int samplesNdx = 0; samplesNdx < DE_LENGTH_OF_ARRAY(samples); samplesNdx++)
8738 	{
8739 		std::ostringstream caseName;
8740 
8741 		caseName << "_multisample_" << (2 << samplesNdx) << "_bit";
8742 
8743 		// .primitives
8744 		{
8745 			tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(testCtx, ("primitives" + caseName.str()).c_str(), "Primitive rasterization");
8746 
8747 			rasterizationTests->addChild(primitives);
8748 
8749 			tcu::TestCaseGroup* const nostippleTests = new tcu::TestCaseGroup(testCtx, "no_stipple", "No stipple");
8750 			tcu::TestCaseGroup* const stippleStaticTests = new tcu::TestCaseGroup(testCtx, "static_stipple", "Line stipple static");
8751 			tcu::TestCaseGroup* const stippleDynamicTests = new tcu::TestCaseGroup(testCtx, "dynamic_stipple", "Line stipple dynamic");
8752 
8753 			primitives->addChild(nostippleTests);
8754 			primitives->addChild(stippleStaticTests);
8755 			primitives->addChild(stippleDynamicTests);
8756 
8757 			// Render primitives as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, verify rasterization result
8758 			nostippleTests->addChild(new BaseTestCase<TrianglesTestInstance>		(testCtx, "triangles", samples[samplesNdx]));
8759 			// Render primitives as VK_PRIMITIVE_TOPOLOGY_POINT_LIST, verify rasterization result
8760 			nostippleTests->addChild(new WidenessTestCase<PointTestInstance>		(testCtx, "points", PRIMITIVEWIDENESS_WIDE,	PRIMITIVESTRICTNESS_IGNORE,	false, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
8761 
8762 			// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in strict mode, verify rasterization result
8763 			nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "strict_lines", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT,	true, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
8764 			// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in strict mode with wide lines, verify rasterization result
8765 			nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "strict_lines_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT,	true, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
8766 
8767 			// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode, verify rasterization result
8768 			nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "non_strict_lines", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_NONSTRICT,	true, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
8769 			// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode with wide lines, verify rasterization result
8770 			nostippleTests->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "non_strict_lines_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_NONSTRICT,	true, samples[samplesNdx], LINESTIPPLE_DISABLED, VK_LINE_RASTERIZATION_MODE_EXT_LAST));
8771 
8772 			for (int i = 0; i < static_cast<int>(LINESTIPPLE_LAST); ++i) {
8773 
8774 				LineStipple stipple = (LineStipple)i;
8775 
8776 				// These variants are not needed for multisample cases.
8777 				if (stipple == LINESTIPPLE_DYNAMIC_WITH_TOPOLOGY)
8778 					continue;
8779 
8780 				tcu::TestCaseGroup *g	= (stipple == LINESTIPPLE_DYNAMIC)
8781 										? stippleDynamicTests
8782 										: (stipple == LINESTIPPLE_STATIC)
8783 										? stippleStaticTests
8784 										: nostippleTests;
8785 
8786 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result
8787 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "lines", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT, LineStippleFactorCase::DEFAULT, i == 0 ? RESOLUTION_NPOT : 0));
8788 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result
8789 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "line_strip", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
8790 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result
8791 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "lines_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
8792 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result
8793 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "line_strip_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT));
8794 
8795 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result
8796 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "rectangular_lines", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
8797 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result
8798 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "rectangular_line_strip", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
8799 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result
8800 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "rectangular_lines_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
8801 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result
8802 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "rectangular_line_strip_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT));
8803 
8804 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result
8805 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "bresenham_lines", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
8806 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result
8807 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "bresenham_line_strip", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
8808 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result
8809 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "bresenham_lines_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
8810 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result
8811 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "bresenham_line_strip_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT));
8812 
8813 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST, verify rasterization result
8814 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "smooth_lines", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
8815 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, verify rasterization result
8816 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "smooth_line_strip", PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
8817 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST with wide lines, verify rasterization result
8818 				g->addChild(new WidenessTestCase<LinesTestInstance>		(testCtx, "smooth_lines_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
8819 				// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP with wide lines, verify rasterization result
8820 				g->addChild(new WidenessTestCase<LineStripTestInstance>	(testCtx, "smooth_line_strip_wide", PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE, true, samples[samplesNdx], stipple, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT));
8821 			}
8822 		}
8823 
8824 		// .fill_rules
8825 		{
8826 			tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(testCtx, ("fill_rules" + caseName.str()).c_str(), "Primitive fill rules");
8827 
8828 			rasterizationTests->addChild(fillRules);
8829 
8830 			// Verify fill rules
8831 			fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad", FillRuleTestInstance::FILLRULECASE_BASIC,			samples[samplesNdx]));
8832 			// Verify fill rules
8833 			fillRules->addChild(new FillRuleTestCase(testCtx,	"basic_quad_reverse", FillRuleTestInstance::FILLRULECASE_REVERSED,		samples[samplesNdx]));
8834 			// Verify fill rules
8835 			fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_full", FillRuleTestInstance::FILLRULECASE_CLIPPED_FULL,	samples[samplesNdx]));
8836 			// Verify fill rules
8837 			fillRules->addChild(new FillRuleTestCase(testCtx,	"clipped_partly", FillRuleTestInstance::FILLRULECASE_CLIPPED_PARTIAL,	samples[samplesNdx]));
8838 			// Verify fill rules
8839 			fillRules->addChild(new FillRuleTestCase(testCtx,	"projected", FillRuleTestInstance::FILLRULECASE_PROJECTED,		samples[samplesNdx]));
8840 		}
8841 
8842 		// .interpolation
8843 		{
8844 			tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(testCtx, ("interpolation" + caseName.str()).c_str(), "Test interpolation");
8845 
8846 			rasterizationTests->addChild(interpolation);
8847 
8848 			// Verify triangle interpolation
8849 			interpolation->addChild(new TriangleInterpolationTestCase		(testCtx, "triangles", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	INTERPOLATIONFLAGS_NONE,															samples[samplesNdx]));
8850 			// Verify line interpolation
8851 			interpolation->addChild(new LineInterpolationTestCase			(testCtx, "lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_IGNORE,	samples[samplesNdx]));
8852 			// Verify wide line interpolation
8853 			interpolation->addChild(new LineInterpolationTestCase			(testCtx, "lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_IGNORE,	samples[samplesNdx]));
8854 
8855 			// Verify strict line interpolation
8856 			interpolation->addChild(new LineInterpolationTestCase			(testCtx, "strict_lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_STRICT,	samples[samplesNdx]));
8857 			// Verify strict wide line interpolation
8858 			interpolation->addChild(new LineInterpolationTestCase			(testCtx, "strict_lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_STRICT,	samples[samplesNdx]));
8859 
8860 			// Verify non-strict line interpolation
8861 			interpolation->addChild(new LineInterpolationTestCase			(testCtx, "non_strict_lines", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	PRIMITIVESTRICTNESS_NONSTRICT,	samples[samplesNdx]));
8862 			// Verify non-strict wide line interpolation
8863 			interpolation->addChild(new LineInterpolationTestCase			(testCtx, "non_strict_lines_wide", VK_PRIMITIVE_TOPOLOGY_LINE_LIST,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		PRIMITIVESTRICTNESS_NONSTRICT,	samples[samplesNdx]));
8864 		}
8865 	}
8866 
8867 	// .provoking_vertex
8868 #ifndef CTS_USES_VULKANSC
8869 	{
8870 		rasterizationTests->addChild(createProvokingVertexTests(testCtx));
8871 	}
8872 #endif
8873 
8874 	// .line_continuity
8875 #ifndef CTS_USES_VULKANSC
8876 	{
8877 		tcu::TestCaseGroup* const	lineContinuity	= new tcu::TestCaseGroup(testCtx, "line_continuity", "Test line continuity");
8878 		static const char			dataDir[]		= "rasterization/line_continuity";
8879 
8880 		struct Case
8881 		{
8882 			std::string	name;
8883 			bool		requireFillModeNonSolid;
8884 		};
8885 
8886 		static const Case cases[] =
8887 		{
8888 			// Test line strip drawing produces continuous lines
8889 			{	"line-strip",false	},
8890 			// Test triangles drawn with lines are continuous
8891 			{	"polygon-mode-lines",true	}
8892 		};
8893 
8894 		rasterizationTests->addChild(lineContinuity);
8895 
8896 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
8897 		{
8898 			const std::string			fileName	= cases[i].name + ".amber";
8899 			cts_amber::AmberTestCase*	testCase	= cts_amber::createAmberTestCase(testCtx, cases[i].name.c_str(), dataDir, fileName);
8900 
8901 			if (cases[i].requireFillModeNonSolid)
8902 			{
8903 				testCase->addRequirement("Features.fillModeNonSolid");
8904 			}
8905 
8906 			lineContinuity->addChild(testCase);
8907 		}
8908 	}
8909 #endif
8910 
8911 	// .depth bias
8912 #ifndef CTS_USES_VULKANSC
8913 	{
8914 		tcu::TestCaseGroup* const	depthBias	= new tcu::TestCaseGroup(testCtx, "depth_bias");
8915 		static const char			dataDir[]	= "rasterization/depth_bias";
8916 
8917 		static const struct
8918 		{
8919 			std::string name;
8920 			vk::VkFormat format;
8921 		} cases [] =
8922 		{
8923 			// Test depth bias with format D16_UNORM
8924 			{"d16_unorm",						vk::VK_FORMAT_D16_UNORM},
8925 			// Test depth bias with format D32_SFLOAT
8926 			{"d32_sfloat",						vk::VK_FORMAT_D32_SFLOAT},
8927 			// Test depth bias with format D24_UNORM_S8_UINT
8928 			{"d24_unorm",						vk::VK_FORMAT_D24_UNORM_S8_UINT},
8929 			// Test depth bias constant 1 and -1 with format D16_UNORM
8930 			{"d16_unorm_constant_one",			vk::VK_FORMAT_D16_UNORM},
8931 			// Test depth bias constant 1 and -1 with format D32_SFLOAT
8932 			{"d32_sfloat_constant_one",			vk::VK_FORMAT_D32_SFLOAT},
8933 			// Test depth bias constant 1 and -1 with format D24_UNORM_S8_UINT
8934 			{"d24_unorm_constant_one",			vk::VK_FORMAT_D24_UNORM_S8_UINT},
8935 			// Test depth bias slope with format D16_UNORM
8936 			{"d16_unorm_slope",					vk::VK_FORMAT_D16_UNORM},
8937 			// Test depth bias constant 1 and -1 with format D16_UNORM
8938 			{"d16_unorm_constant_one_less",		vk::VK_FORMAT_D16_UNORM},
8939 			// Test depth bias constant 1 and -1 with format D16_UNORM
8940 			{"d16_unorm_constant_one_greater",	vk::VK_FORMAT_D16_UNORM},
8941 			// Test depth bias constant 1 and -1 with format D24_UNORM_S8_UINT
8942 			{"d24_unorm_constant_one_less",		vk::VK_FORMAT_D24_UNORM_S8_UINT},
8943 			// Test depth bias constant 1 and -1 with format D24_UNORM_S8_UINT
8944 			{"d24_unorm_constant_one_greater",	vk::VK_FORMAT_D24_UNORM_S8_UINT},
8945 			// Test depth bias constant 1 and -1 with format D32_SFLOAT
8946 			{"d32_sfloat_constant_one_less",	vk::VK_FORMAT_D32_SFLOAT},
8947 			// Test depth bias constant 1 and -1 with format D32_SFLOAT
8948 			{"d32_sfloat_constant_one_greater",	vk::VK_FORMAT_D32_SFLOAT},
8949 		};
8950 
8951 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
8952 		{
8953 			const VkImageCreateInfo vkImageCreateInfo = {
8954 				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// sType
8955 				nullptr,										// pNext
8956 				0,												// flags
8957 				VK_IMAGE_TYPE_2D,								// imageType
8958 				cases[i].format,								// format
8959 				{250, 250, 1},									// extent
8960 				1,												// mipLevels
8961 				1,												// arrayLayers
8962 				VK_SAMPLE_COUNT_1_BIT,							// samples
8963 				VK_IMAGE_TILING_OPTIMAL,						// tiling
8964 				VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,	// usage
8965 				VK_SHARING_MODE_EXCLUSIVE,						// sharingMode
8966 				0,												// queueFamilyIndexCount
8967 				nullptr,										// pQueueFamilyIndices
8968 				VK_IMAGE_LAYOUT_UNDEFINED,						// initialLayout
8969 			};
8970 
8971 			std::vector<std::string>		requirements = std::vector<std::string>(0);
8972 			std::vector<VkImageCreateInfo>	imageRequirements;
8973 			imageRequirements.push_back(vkImageCreateInfo);
8974 			const std::string			fileName	= cases[i].name + ".amber";
8975 			cts_amber::AmberTestCase*	testCase	= cts_amber::createAmberTestCase(testCtx, cases[i].name.c_str(), dataDir, fileName, requirements, imageRequirements);
8976 
8977 			depthBias->addChild(testCase);
8978 		}
8979 
8980 		rasterizationTests->addChild(depthBias);
8981 	}
8982 #endif // CTS_USES_VULKANSC
8983 
8984 #ifndef CTS_USES_VULKANSC
8985 	// Depth bias control.
8986 	rasterizationTests->addChild(createDepthBiasControlTests(testCtx));
8987 #endif // CTS_USES_VULKANSC
8988 
8989 	// Fragment shader side effects.
8990 	{
8991 		rasterizationTests->addChild(createFragSideEffectsTests(testCtx));
8992 	}
8993 
8994 #ifndef CTS_USES_VULKANSC
8995 	// Rasterization order attachment access tests
8996 	{
8997 		rasterizationTests->addChild(createRasterizationOrderAttachmentAccessTests(testCtx));
8998 	}
8999 
9000 	// Tile Storage tests
9001 	{
9002 		rasterizationTests->addChild(createShaderTileImageTests(testCtx));
9003 	}
9004 #endif // CTS_USES_VULKANSC
9005 
9006 #ifndef CTS_USES_VULKANSC
9007 	// .maintenance5
9008 	{
9009 		//NonStrictLineStripMaintenance5TestInstance
9010 		tcu::TestCaseGroup* const maintenance5tests = new tcu::TestCaseGroup(testCtx, "maintenance5", "Primitive rasterization");
9011 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode, verify rasterization result
9012 		maintenance5tests->addChild(new NonStrictLinesMaintenance5TestCase<NonStrictLinesMaintenance5TestInstance>(testCtx, "non_strict_lines_narrow", PRIMITIVEWIDENESS_NARROW));
9013 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_LIST in nonstrict mode, verify rasterization result
9014 		maintenance5tests->addChild(new NonStrictLinesMaintenance5TestCase<NonStrictLinesMaintenance5TestInstance>(testCtx, "non_strict_lines_wide", PRIMITIVEWIDENESS_WIDE));
9015 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP in nonstrict mode, verify rasterization result
9016 		maintenance5tests->addChild(new NonStrictLinesMaintenance5TestCase<NonStrictLineStripMaintenance5TestInstance>(testCtx, "non_strict_line_strip_narrow", PRIMITIVEWIDENESS_NARROW));
9017 		// Render primitives as VK_PRIMITIVE_TOPOLOGY_LINE_STRIP in nonstrict mode, verify rasterization result
9018 		maintenance5tests->addChild(new NonStrictLinesMaintenance5TestCase<NonStrictLineStripMaintenance5TestInstance>(testCtx, "non_strict_line_strip_wide", PRIMITIVEWIDENESS_WIDE));
9019 		rasterizationTests->addChild(maintenance5tests);
9020 	}
9021 #endif // CTS_USES_VULKANSC
9022 }
9023 
9024 } // anonymous
9025 
createTests(tcu::TestContext & testCtx,const std::string & name)9026 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx, const std::string& name)
9027 {
9028 	return createTestGroup(testCtx, name.c_str(), createRasterizationTests);
9029 }
9030 
9031 } // rasterization
9032 } // vkt
9033