1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci * Copyright (c) 2016 The Khronos Group Inc.
7e5c31af7Sopenharmony_ci *
8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
11e5c31af7Sopenharmony_ci *
12e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
13e5c31af7Sopenharmony_ci *
14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
18e5c31af7Sopenharmony_ci * limitations under the License.
19e5c31af7Sopenharmony_ci *
20e5c31af7Sopenharmony_ci *//*!
21e5c31af7Sopenharmony_ci * \file
22e5c31af7Sopenharmony_ci * \brief Tessellation Utilities
23e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
24e5c31af7Sopenharmony_ci
25e5c31af7Sopenharmony_ci#include "vktTessellationUtil.hpp"
26e5c31af7Sopenharmony_ci#include "vkTypeUtil.hpp"
27e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp"
28e5c31af7Sopenharmony_ci#include "deMath.h"
29e5c31af7Sopenharmony_ci
30e5c31af7Sopenharmony_cinamespace vkt
31e5c31af7Sopenharmony_ci{
32e5c31af7Sopenharmony_cinamespace tessellation
33e5c31af7Sopenharmony_ci{
34e5c31af7Sopenharmony_ci
35e5c31af7Sopenharmony_ciusing namespace vk;
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ciVkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage, const deUint32 numArrayLayers)
38e5c31af7Sopenharmony_ci{
39e5c31af7Sopenharmony_ci	const VkImageCreateInfo imageInfo =
40e5c31af7Sopenharmony_ci	{
41e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType          sType;
42e5c31af7Sopenharmony_ci		DE_NULL,									// const void*              pNext;
43e5c31af7Sopenharmony_ci		(VkImageCreateFlags)0,						// VkImageCreateFlags       flags;
44e5c31af7Sopenharmony_ci		VK_IMAGE_TYPE_2D,							// VkImageType              imageType;
45e5c31af7Sopenharmony_ci		format,										// VkFormat                 format;
46e5c31af7Sopenharmony_ci		makeExtent3D(size.x(), size.y(), 1),		// VkExtent3D               extent;
47e5c31af7Sopenharmony_ci		1u,											// uint32_t                 mipLevels;
48e5c31af7Sopenharmony_ci		numArrayLayers,								// uint32_t                 arrayLayers;
49e5c31af7Sopenharmony_ci		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits    samples;
50e5c31af7Sopenharmony_ci		VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling            tiling;
51e5c31af7Sopenharmony_ci		usage,										// VkImageUsageFlags        usage;
52e5c31af7Sopenharmony_ci		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode            sharingMode;
53e5c31af7Sopenharmony_ci		0u,											// uint32_t                 queueFamilyIndexCount;
54e5c31af7Sopenharmony_ci		DE_NULL,									// const uint32_t*          pQueueFamilyIndices;
55e5c31af7Sopenharmony_ci		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout            initialLayout;
56e5c31af7Sopenharmony_ci	};
57e5c31af7Sopenharmony_ci	return imageInfo;
58e5c31af7Sopenharmony_ci}
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ciMove<VkRenderPass> makeRenderPassWithoutAttachments (const DeviceInterface&	vk,
61e5c31af7Sopenharmony_ci													 const VkDevice			device)
62e5c31af7Sopenharmony_ci{
63e5c31af7Sopenharmony_ci	const VkAttachmentReference unusedAttachment =
64e5c31af7Sopenharmony_ci	{
65e5c31af7Sopenharmony_ci		VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
66e5c31af7Sopenharmony_ci		VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
67e5c31af7Sopenharmony_ci	};
68e5c31af7Sopenharmony_ci
69e5c31af7Sopenharmony_ci	const VkSubpassDescription subpassDescription =
70e5c31af7Sopenharmony_ci	{
71e5c31af7Sopenharmony_ci		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
72e5c31af7Sopenharmony_ci		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
73e5c31af7Sopenharmony_ci		0u,													// deUint32							inputAttachmentCount;
74e5c31af7Sopenharmony_ci		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
75e5c31af7Sopenharmony_ci		0u,													// deUint32							colorAttachmentCount;
76e5c31af7Sopenharmony_ci		DE_NULL,											// const VkAttachmentReference*		pColorAttachments;
77e5c31af7Sopenharmony_ci		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
78e5c31af7Sopenharmony_ci		&unusedAttachment,									// const VkAttachmentReference*		pDepthStencilAttachment;
79e5c31af7Sopenharmony_ci		0u,													// deUint32							preserveAttachmentCount;
80e5c31af7Sopenharmony_ci		DE_NULL												// const deUint32*					pPreserveAttachments;
81e5c31af7Sopenharmony_ci	};
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_ci	const VkRenderPassCreateInfo renderPassInfo =
84e5c31af7Sopenharmony_ci	{
85e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
86e5c31af7Sopenharmony_ci		DE_NULL,											// const void*						pNext;
87e5c31af7Sopenharmony_ci		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
88e5c31af7Sopenharmony_ci		0u,													// deUint32							attachmentCount;
89e5c31af7Sopenharmony_ci		DE_NULL,											// const VkAttachmentDescription*	pAttachments;
90e5c31af7Sopenharmony_ci		1u,													// deUint32							subpassCount;
91e5c31af7Sopenharmony_ci		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
92e5c31af7Sopenharmony_ci		0u,													// deUint32							dependencyCount;
93e5c31af7Sopenharmony_ci		DE_NULL												// const VkSubpassDependency*		pDependencies;
94e5c31af7Sopenharmony_ci	};
95e5c31af7Sopenharmony_ci
96e5c31af7Sopenharmony_ci	return createRenderPass(vk, device, &renderPassInfo);
97e5c31af7Sopenharmony_ci}
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_ciGraphicsPipelineBuilder& GraphicsPipelineBuilder::setShader (const DeviceInterface&			vk,
100e5c31af7Sopenharmony_ci															 const VkDevice					device,
101e5c31af7Sopenharmony_ci															 const VkShaderStageFlagBits	stage,
102e5c31af7Sopenharmony_ci															 const ProgramBinary&			binary,
103e5c31af7Sopenharmony_ci															 const VkSpecializationInfo*	specInfo)
104e5c31af7Sopenharmony_ci{
105e5c31af7Sopenharmony_ci	VkShaderModule module;
106e5c31af7Sopenharmony_ci	switch (stage)
107e5c31af7Sopenharmony_ci	{
108e5c31af7Sopenharmony_ci		case (VK_SHADER_STAGE_VERTEX_BIT):
109e5c31af7Sopenharmony_ci			DE_ASSERT(m_vertexShaderModule.get() == DE_NULL);
110e5c31af7Sopenharmony_ci			m_vertexShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
111e5c31af7Sopenharmony_ci			module = *m_vertexShaderModule;
112e5c31af7Sopenharmony_ci			break;
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_ci		case (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT):
115e5c31af7Sopenharmony_ci			DE_ASSERT(m_tessControlShaderModule.get() == DE_NULL);
116e5c31af7Sopenharmony_ci			m_tessControlShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
117e5c31af7Sopenharmony_ci			module = *m_tessControlShaderModule;
118e5c31af7Sopenharmony_ci			break;
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ci		case (VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT):
121e5c31af7Sopenharmony_ci			DE_ASSERT(m_tessEvaluationShaderModule.get() == DE_NULL);
122e5c31af7Sopenharmony_ci			m_tessEvaluationShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
123e5c31af7Sopenharmony_ci			module = *m_tessEvaluationShaderModule;
124e5c31af7Sopenharmony_ci			break;
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_ci		case (VK_SHADER_STAGE_GEOMETRY_BIT):
127e5c31af7Sopenharmony_ci			DE_ASSERT(m_geometryShaderModule.get() == DE_NULL);
128e5c31af7Sopenharmony_ci			m_geometryShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
129e5c31af7Sopenharmony_ci			module = *m_geometryShaderModule;
130e5c31af7Sopenharmony_ci			break;
131e5c31af7Sopenharmony_ci
132e5c31af7Sopenharmony_ci		case (VK_SHADER_STAGE_FRAGMENT_BIT):
133e5c31af7Sopenharmony_ci			DE_ASSERT(m_fragmentShaderModule.get() == DE_NULL);
134e5c31af7Sopenharmony_ci			m_fragmentShaderModule = createShaderModule(vk, device, binary, (VkShaderModuleCreateFlags)0);
135e5c31af7Sopenharmony_ci			module = *m_fragmentShaderModule;
136e5c31af7Sopenharmony_ci			break;
137e5c31af7Sopenharmony_ci
138e5c31af7Sopenharmony_ci		default:
139e5c31af7Sopenharmony_ci			DE_FATAL("Invalid shader stage");
140e5c31af7Sopenharmony_ci			return *this;
141e5c31af7Sopenharmony_ci	}
142e5c31af7Sopenharmony_ci
143e5c31af7Sopenharmony_ci	const VkPipelineShaderStageCreateInfo pipelineShaderStageInfo =
144e5c31af7Sopenharmony_ci	{
145e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType						sType;
146e5c31af7Sopenharmony_ci		DE_NULL,												// const void*							pNext;
147e5c31af7Sopenharmony_ci		(VkPipelineShaderStageCreateFlags)0,					// VkPipelineShaderStageCreateFlags		flags;
148e5c31af7Sopenharmony_ci		stage,													// VkShaderStageFlagBits				stage;
149e5c31af7Sopenharmony_ci		module,													// VkShaderModule						module;
150e5c31af7Sopenharmony_ci		"main",													// const char*							pName;
151e5c31af7Sopenharmony_ci		specInfo,												// const VkSpecializationInfo*			pSpecializationInfo;
152e5c31af7Sopenharmony_ci	};
153e5c31af7Sopenharmony_ci
154e5c31af7Sopenharmony_ci	m_shaderStageFlags |= stage;
155e5c31af7Sopenharmony_ci	m_shaderStages.push_back(pipelineShaderStageInfo);
156e5c31af7Sopenharmony_ci
157e5c31af7Sopenharmony_ci	return *this;
158e5c31af7Sopenharmony_ci}
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_ciGraphicsPipelineBuilder& GraphicsPipelineBuilder::setVertexInputSingleAttribute (const VkFormat vertexFormat, const deUint32 stride)
161e5c31af7Sopenharmony_ci{
162e5c31af7Sopenharmony_ci	const VkVertexInputBindingDescription bindingDesc =
163e5c31af7Sopenharmony_ci	{
164e5c31af7Sopenharmony_ci		0u,									// uint32_t				binding;
165e5c31af7Sopenharmony_ci		stride,								// uint32_t				stride;
166e5c31af7Sopenharmony_ci		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
167e5c31af7Sopenharmony_ci	};
168e5c31af7Sopenharmony_ci	const VkVertexInputAttributeDescription attributeDesc =
169e5c31af7Sopenharmony_ci	{
170e5c31af7Sopenharmony_ci		0u,									// uint32_t			location;
171e5c31af7Sopenharmony_ci		0u,									// uint32_t			binding;
172e5c31af7Sopenharmony_ci		vertexFormat,						// VkFormat			format;
173e5c31af7Sopenharmony_ci		0u,									// uint32_t			offset;
174e5c31af7Sopenharmony_ci	};
175e5c31af7Sopenharmony_ci
176e5c31af7Sopenharmony_ci	m_vertexInputBindings.clear();
177e5c31af7Sopenharmony_ci	m_vertexInputBindings.push_back(bindingDesc);
178e5c31af7Sopenharmony_ci
179e5c31af7Sopenharmony_ci	m_vertexInputAttributes.clear();
180e5c31af7Sopenharmony_ci	m_vertexInputAttributes.push_back(attributeDesc);
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_ci	return *this;
183e5c31af7Sopenharmony_ci}
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_citemplate<typename T>
186e5c31af7Sopenharmony_ciinline const T* dataPointer (const std::vector<T>& vec)
187e5c31af7Sopenharmony_ci{
188e5c31af7Sopenharmony_ci	return (vec.size() != 0 ? &vec[0] : DE_NULL);
189e5c31af7Sopenharmony_ci}
190e5c31af7Sopenharmony_ci
191e5c31af7Sopenharmony_ciMove<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface&	vk,
192e5c31af7Sopenharmony_ci												 const VkDevice			device,
193e5c31af7Sopenharmony_ci												 const VkPipelineLayout	pipelineLayout,
194e5c31af7Sopenharmony_ci												 const VkRenderPass		renderPass)
195e5c31af7Sopenharmony_ci{
196e5c31af7Sopenharmony_ci	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
197e5c31af7Sopenharmony_ci	{
198e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
199e5c31af7Sopenharmony_ci		DE_NULL,														// const void*                                 pNext;
200e5c31af7Sopenharmony_ci		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
201e5c31af7Sopenharmony_ci		static_cast<deUint32>(m_vertexInputBindings.size()),			// uint32_t                                    vertexBindingDescriptionCount;
202e5c31af7Sopenharmony_ci		dataPointer(m_vertexInputBindings),								// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
203e5c31af7Sopenharmony_ci		static_cast<deUint32>(m_vertexInputAttributes.size()),			// uint32_t                                    vertexAttributeDescriptionCount;
204e5c31af7Sopenharmony_ci		dataPointer(m_vertexInputAttributes),							// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
205e5c31af7Sopenharmony_ci	};
206e5c31af7Sopenharmony_ci
207e5c31af7Sopenharmony_ci	const VkPrimitiveTopology topology = (m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
208e5c31af7Sopenharmony_ci																										 : m_primitiveTopology;
209e5c31af7Sopenharmony_ci	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
210e5c31af7Sopenharmony_ci	{
211e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
212e5c31af7Sopenharmony_ci		DE_NULL,														// const void*                                 pNext;
213e5c31af7Sopenharmony_ci		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
214e5c31af7Sopenharmony_ci		topology,														// VkPrimitiveTopology                         topology;
215e5c31af7Sopenharmony_ci		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
216e5c31af7Sopenharmony_ci	};
217e5c31af7Sopenharmony_ci
218e5c31af7Sopenharmony_ci	const VkPipelineTessellationDomainOriginStateCreateInfo tessellationDomainOriginStateInfo =
219e5c31af7Sopenharmony_ci	{
220e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO,
221e5c31af7Sopenharmony_ci		DE_NULL,
222e5c31af7Sopenharmony_ci		(!m_tessellationDomainOrigin ? VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT : *m_tessellationDomainOrigin)
223e5c31af7Sopenharmony_ci	};
224e5c31af7Sopenharmony_ci	const VkPipelineTessellationStateCreateInfo pipelineTessellationStateInfo =
225e5c31af7Sopenharmony_ci	{
226e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType                             sType;
227e5c31af7Sopenharmony_ci		(!m_tessellationDomainOrigin ? DE_NULL : &tessellationDomainOriginStateInfo),
228e5c31af7Sopenharmony_ci		(VkPipelineTessellationStateCreateFlags)0,						// VkPipelineTessellationStateCreateFlags      flags;
229e5c31af7Sopenharmony_ci		m_patchControlPoints,											// uint32_t                                    patchControlPoints;
230e5c31af7Sopenharmony_ci	};
231e5c31af7Sopenharmony_ci
232e5c31af7Sopenharmony_ci	const VkViewport	viewport	= makeViewport(m_renderSize);
233e5c31af7Sopenharmony_ci	const VkRect2D		scissor		= makeRect2D(m_renderSize);
234e5c31af7Sopenharmony_ci
235e5c31af7Sopenharmony_ci	const bool haveRenderSize = m_renderSize.x() > 0 && m_renderSize.y() > 0;
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ci	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
238e5c31af7Sopenharmony_ci	{
239e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType                             sType;
240e5c31af7Sopenharmony_ci		DE_NULL,												// const void*                                 pNext;
241e5c31af7Sopenharmony_ci		(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewportStateCreateFlags          flags;
242e5c31af7Sopenharmony_ci		1u,														// uint32_t                                    viewportCount;
243e5c31af7Sopenharmony_ci		haveRenderSize ? &viewport : DE_NULL,					// const VkViewport*                           pViewports;
244e5c31af7Sopenharmony_ci		1u,														// uint32_t                                    scissorCount;
245e5c31af7Sopenharmony_ci		haveRenderSize ? &scissor : DE_NULL,					// const VkRect2D*                             pScissors;
246e5c31af7Sopenharmony_ci	};
247e5c31af7Sopenharmony_ci
248e5c31af7Sopenharmony_ci	const bool isRasterizationDisabled = ((m_shaderStageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) == 0);
249e5c31af7Sopenharmony_ci	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
250e5c31af7Sopenharmony_ci	{
251e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
252e5c31af7Sopenharmony_ci		DE_NULL,														// const void*                              pNext;
253e5c31af7Sopenharmony_ci		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
254e5c31af7Sopenharmony_ci		VK_FALSE,														// VkBool32                                 depthClampEnable;
255e5c31af7Sopenharmony_ci		isRasterizationDisabled,										// VkBool32                                 rasterizerDiscardEnable;
256e5c31af7Sopenharmony_ci		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
257e5c31af7Sopenharmony_ci		m_cullModeFlags,												// VkCullModeFlags							cullMode;
258e5c31af7Sopenharmony_ci		m_frontFace,													// VkFrontFace								frontFace;
259e5c31af7Sopenharmony_ci		VK_FALSE,														// VkBool32									depthBiasEnable;
260e5c31af7Sopenharmony_ci		0.0f,															// float									depthBiasConstantFactor;
261e5c31af7Sopenharmony_ci		0.0f,															// float									depthBiasClamp;
262e5c31af7Sopenharmony_ci		0.0f,															// float									depthBiasSlopeFactor;
263e5c31af7Sopenharmony_ci		1.0f,															// float									lineWidth;
264e5c31af7Sopenharmony_ci	};
265e5c31af7Sopenharmony_ci
266e5c31af7Sopenharmony_ci	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
267e5c31af7Sopenharmony_ci	{
268e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
269e5c31af7Sopenharmony_ci		DE_NULL,													// const void*								pNext;
270e5c31af7Sopenharmony_ci		(VkPipelineMultisampleStateCreateFlags)0,					// VkPipelineMultisampleStateCreateFlags	flags;
271e5c31af7Sopenharmony_ci		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
272e5c31af7Sopenharmony_ci		VK_FALSE,													// VkBool32									sampleShadingEnable;
273e5c31af7Sopenharmony_ci		0.0f,														// float									minSampleShading;
274e5c31af7Sopenharmony_ci		DE_NULL,													// const VkSampleMask*						pSampleMask;
275e5c31af7Sopenharmony_ci		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
276e5c31af7Sopenharmony_ci		VK_FALSE													// VkBool32									alphaToOneEnable;
277e5c31af7Sopenharmony_ci	};
278e5c31af7Sopenharmony_ci
279e5c31af7Sopenharmony_ci	const VkStencilOpState stencilOpState = makeStencilOpState(
280e5c31af7Sopenharmony_ci		VK_STENCIL_OP_KEEP,		// stencil fail
281e5c31af7Sopenharmony_ci		VK_STENCIL_OP_KEEP,		// depth & stencil pass
282e5c31af7Sopenharmony_ci		VK_STENCIL_OP_KEEP,		// depth only fail
283e5c31af7Sopenharmony_ci		VK_COMPARE_OP_NEVER,	// compare op
284e5c31af7Sopenharmony_ci		0u,						// compare mask
285e5c31af7Sopenharmony_ci		0u,						// write mask
286e5c31af7Sopenharmony_ci		0u);					// reference
287e5c31af7Sopenharmony_ci
288e5c31af7Sopenharmony_ci	const VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
289e5c31af7Sopenharmony_ci	{
290e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
291e5c31af7Sopenharmony_ci		DE_NULL,													// const void*								pNext;
292e5c31af7Sopenharmony_ci		(VkPipelineDepthStencilStateCreateFlags)0,					// VkPipelineDepthStencilStateCreateFlags	flags;
293e5c31af7Sopenharmony_ci		VK_FALSE,													// VkBool32									depthTestEnable;
294e5c31af7Sopenharmony_ci		VK_FALSE,													// VkBool32									depthWriteEnable;
295e5c31af7Sopenharmony_ci		VK_COMPARE_OP_LESS,											// VkCompareOp								depthCompareOp;
296e5c31af7Sopenharmony_ci		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
297e5c31af7Sopenharmony_ci		VK_FALSE,													// VkBool32									stencilTestEnable;
298e5c31af7Sopenharmony_ci		stencilOpState,												// VkStencilOpState							front;
299e5c31af7Sopenharmony_ci		stencilOpState,												// VkStencilOpState							back;
300e5c31af7Sopenharmony_ci		0.0f,														// float									minDepthBounds;
301e5c31af7Sopenharmony_ci		1.0f,														// float									maxDepthBounds;
302e5c31af7Sopenharmony_ci	};
303e5c31af7Sopenharmony_ci
304e5c31af7Sopenharmony_ci	const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
305e5c31af7Sopenharmony_ci	const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
306e5c31af7Sopenharmony_ci	{
307e5c31af7Sopenharmony_ci		m_blendEnable,						// VkBool32					blendEnable;
308e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcColorBlendFactor;
309e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstColorBlendFactor;
310e5c31af7Sopenharmony_ci		VK_BLEND_OP_ADD,					// VkBlendOp				colorBlendOp;
311e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_SRC_ALPHA,			// VkBlendFactor			srcAlphaBlendFactor;
312e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_ONE,				// VkBlendFactor			dstAlphaBlendFactor;
313e5c31af7Sopenharmony_ci		VK_BLEND_OP_ADD,					// VkBlendOp				alphaBlendOp;
314e5c31af7Sopenharmony_ci		colorComponentsAll,					// VkColorComponentFlags	colorWriteMask;
315e5c31af7Sopenharmony_ci	};
316e5c31af7Sopenharmony_ci
317e5c31af7Sopenharmony_ci	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
318e5c31af7Sopenharmony_ci	{
319e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
320e5c31af7Sopenharmony_ci		DE_NULL,													// const void*									pNext;
321e5c31af7Sopenharmony_ci		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
322e5c31af7Sopenharmony_ci		VK_FALSE,													// VkBool32										logicOpEnable;
323e5c31af7Sopenharmony_ci		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
324e5c31af7Sopenharmony_ci		1u,															// deUint32										attachmentCount;
325e5c31af7Sopenharmony_ci		&pipelineColorBlendAttachmentState,							// const VkPipelineColorBlendAttachmentState*	pAttachments;
326e5c31af7Sopenharmony_ci		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConstants[4];
327e5c31af7Sopenharmony_ci	};
328e5c31af7Sopenharmony_ci
329e5c31af7Sopenharmony_ci	std::vector<VkDynamicState> dynamicStates;
330e5c31af7Sopenharmony_ci	if (!haveRenderSize && !isRasterizationDisabled)
331e5c31af7Sopenharmony_ci	{
332e5c31af7Sopenharmony_ci		dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
333e5c31af7Sopenharmony_ci		dynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
334e5c31af7Sopenharmony_ci	}
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci	const VkPipelineDynamicStateCreateInfo pipelineDynamicStateInfo =
337e5c31af7Sopenharmony_ci	{
338e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	// VkStructureType						sType;
339e5c31af7Sopenharmony_ci		DE_NULL,												// const void*							pNext;
340e5c31af7Sopenharmony_ci		0,														// VkPipelineDynamicStateCreateFlags	flags;
341e5c31af7Sopenharmony_ci		static_cast<deUint32>(dynamicStates.size()),			// uint32_t								dynamicStateCount;
342e5c31af7Sopenharmony_ci		(dynamicStates.empty() ? DE_NULL : &dynamicStates[0]),	// const VkDynamicState*				pDynamicStates;
343e5c31af7Sopenharmony_ci	};
344e5c31af7Sopenharmony_ci
345e5c31af7Sopenharmony_ci	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
346e5c31af7Sopenharmony_ci	{
347e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,						// VkStructureType									sType;
348e5c31af7Sopenharmony_ci		DE_NULL,																// const void*										pNext;
349e5c31af7Sopenharmony_ci		(VkPipelineCreateFlags)0,												// VkPipelineCreateFlags							flags;
350e5c31af7Sopenharmony_ci		static_cast<deUint32>(m_shaderStages.size()),							// deUint32											stageCount;
351e5c31af7Sopenharmony_ci		&m_shaderStages[0],														// const VkPipelineShaderStageCreateInfo*			pStages;
352e5c31af7Sopenharmony_ci		&vertexInputStateInfo,													// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
353e5c31af7Sopenharmony_ci		&pipelineInputAssemblyStateInfo,										// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
354e5c31af7Sopenharmony_ci		(m_shaderStageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &pipelineTessellationStateInfo : DE_NULL), // const VkPipelineTessellationStateCreateInfo*		pTessellationState;
355e5c31af7Sopenharmony_ci		(isRasterizationDisabled ? DE_NULL : &pipelineViewportStateInfo),		// const VkPipelineViewportStateCreateInfo*			pViewportState;
356e5c31af7Sopenharmony_ci		&pipelineRasterizationStateInfo,										// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
357e5c31af7Sopenharmony_ci		(isRasterizationDisabled ? DE_NULL : &pipelineMultisampleStateInfo),	// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
358e5c31af7Sopenharmony_ci		(isRasterizationDisabled ? DE_NULL : &pipelineDepthStencilStateInfo),	// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
359e5c31af7Sopenharmony_ci		(isRasterizationDisabled ? DE_NULL : &pipelineColorBlendStateInfo),		// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
360e5c31af7Sopenharmony_ci		(dynamicStates.empty() ? DE_NULL : &pipelineDynamicStateInfo),			// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
361e5c31af7Sopenharmony_ci		pipelineLayout,															// VkPipelineLayout									layout;
362e5c31af7Sopenharmony_ci		renderPass,																// VkRenderPass										renderPass;
363e5c31af7Sopenharmony_ci		0u,																		// deUint32											subpass;
364e5c31af7Sopenharmony_ci		DE_NULL,																// VkPipeline										basePipelineHandle;
365e5c31af7Sopenharmony_ci		0,																		// deInt32											basePipelineIndex;
366e5c31af7Sopenharmony_ci	};
367e5c31af7Sopenharmony_ci
368e5c31af7Sopenharmony_ci	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
369e5c31af7Sopenharmony_ci}
370e5c31af7Sopenharmony_ci
371e5c31af7Sopenharmony_cifloat getClampedTessLevel (const SpacingMode mode, const float tessLevel)
372e5c31af7Sopenharmony_ci{
373e5c31af7Sopenharmony_ci	switch (mode)
374e5c31af7Sopenharmony_ci	{
375e5c31af7Sopenharmony_ci		case SPACINGMODE_EQUAL:				return de::max(1.0f, tessLevel);
376e5c31af7Sopenharmony_ci		case SPACINGMODE_FRACTIONAL_ODD:	return de::max(1.0f, tessLevel);
377e5c31af7Sopenharmony_ci		case SPACINGMODE_FRACTIONAL_EVEN:	return de::max(2.0f, tessLevel);
378e5c31af7Sopenharmony_ci		default:
379e5c31af7Sopenharmony_ci			DE_ASSERT(false);
380e5c31af7Sopenharmony_ci			return 0.0f;
381e5c31af7Sopenharmony_ci	}
382e5c31af7Sopenharmony_ci}
383e5c31af7Sopenharmony_ci
384e5c31af7Sopenharmony_ciint getRoundedTessLevel (const SpacingMode mode, const float clampedTessLevel)
385e5c31af7Sopenharmony_ci{
386e5c31af7Sopenharmony_ci	static const int minimumMaxTessGenLevel = 64;	//!< Minimum maxTessellationGenerationLevel defined by the spec.
387e5c31af7Sopenharmony_ci
388e5c31af7Sopenharmony_ci	int result = (int)deFloatCeil(clampedTessLevel);
389e5c31af7Sopenharmony_ci
390e5c31af7Sopenharmony_ci	switch (mode)
391e5c31af7Sopenharmony_ci	{
392e5c31af7Sopenharmony_ci		case SPACINGMODE_EQUAL:											break;
393e5c31af7Sopenharmony_ci		case SPACINGMODE_FRACTIONAL_ODD:	result += 1 - result % 2;	break;
394e5c31af7Sopenharmony_ci		case SPACINGMODE_FRACTIONAL_EVEN:	result += result % 2;		break;
395e5c31af7Sopenharmony_ci		default:
396e5c31af7Sopenharmony_ci			DE_ASSERT(false);
397e5c31af7Sopenharmony_ci	}
398e5c31af7Sopenharmony_ci	DE_ASSERT(de::inRange<int>(result, 1, minimumMaxTessGenLevel));
399e5c31af7Sopenharmony_ci	DE_UNREF(minimumMaxTessGenLevel);
400e5c31af7Sopenharmony_ci
401e5c31af7Sopenharmony_ci	return result;
402e5c31af7Sopenharmony_ci}
403e5c31af7Sopenharmony_ci
404e5c31af7Sopenharmony_ciint getClampedRoundedTessLevel (const SpacingMode mode, const float tessLevel)
405e5c31af7Sopenharmony_ci{
406e5c31af7Sopenharmony_ci	return getRoundedTessLevel(mode, getClampedTessLevel(mode, tessLevel));
407e5c31af7Sopenharmony_ci}
408e5c31af7Sopenharmony_ci
409e5c31af7Sopenharmony_civoid getClampedRoundedTriangleTessLevels (const SpacingMode	spacingMode,
410e5c31af7Sopenharmony_ci										  const float*		innerSrc,
411e5c31af7Sopenharmony_ci										  const float*		outerSrc,
412e5c31af7Sopenharmony_ci										  int*				innerDst,
413e5c31af7Sopenharmony_ci										  int*				outerDst)
414e5c31af7Sopenharmony_ci{
415e5c31af7Sopenharmony_ci	innerDst[0] = getClampedRoundedTessLevel(spacingMode, innerSrc[0]);
416e5c31af7Sopenharmony_ci	for (int i = 0; i < 3; i++)
417e5c31af7Sopenharmony_ci		outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]);
418e5c31af7Sopenharmony_ci}
419e5c31af7Sopenharmony_ci
420e5c31af7Sopenharmony_civoid getClampedRoundedQuadTessLevels (const SpacingMode spacingMode,
421e5c31af7Sopenharmony_ci									  const float*		innerSrc,
422e5c31af7Sopenharmony_ci									  const float*		outerSrc,
423e5c31af7Sopenharmony_ci									  int*				innerDst,
424e5c31af7Sopenharmony_ci									  int*				outerDst)
425e5c31af7Sopenharmony_ci{
426e5c31af7Sopenharmony_ci	for (int i = 0; i < 2; i++)
427e5c31af7Sopenharmony_ci		innerDst[i] = getClampedRoundedTessLevel(spacingMode, innerSrc[i]);
428e5c31af7Sopenharmony_ci	for (int i = 0; i < 4; i++)
429e5c31af7Sopenharmony_ci		outerDst[i] = getClampedRoundedTessLevel(spacingMode, outerSrc[i]);
430e5c31af7Sopenharmony_ci}
431e5c31af7Sopenharmony_ci
432e5c31af7Sopenharmony_civoid getClampedRoundedIsolineTessLevels (const SpacingMode	spacingMode,
433e5c31af7Sopenharmony_ci										 const float*		outerSrc,
434e5c31af7Sopenharmony_ci										 int*				outerDst)
435e5c31af7Sopenharmony_ci{
436e5c31af7Sopenharmony_ci	outerDst[0] = getClampedRoundedTessLevel(SPACINGMODE_EQUAL,	outerSrc[0]);
437e5c31af7Sopenharmony_ci	outerDst[1] = getClampedRoundedTessLevel(spacingMode,		outerSrc[1]);
438e5c31af7Sopenharmony_ci}
439e5c31af7Sopenharmony_ci
440e5c31af7Sopenharmony_ciint numOuterTessellationLevels (const TessPrimitiveType primType)
441e5c31af7Sopenharmony_ci{
442e5c31af7Sopenharmony_ci	switch (primType)
443e5c31af7Sopenharmony_ci	{
444e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_TRIANGLES:	return 3;
445e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_QUADS:		return 4;
446e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_ISOLINES:	return 2;
447e5c31af7Sopenharmony_ci		default:
448e5c31af7Sopenharmony_ci			DE_ASSERT(false);
449e5c31af7Sopenharmony_ci			return 0;
450e5c31af7Sopenharmony_ci	}
451e5c31af7Sopenharmony_ci}
452e5c31af7Sopenharmony_ci
453e5c31af7Sopenharmony_cibool isPatchDiscarded (const TessPrimitiveType primitiveType, const float* outerLevels)
454e5c31af7Sopenharmony_ci{
455e5c31af7Sopenharmony_ci	const int numOuterLevels = numOuterTessellationLevels(primitiveType);
456e5c31af7Sopenharmony_ci	for (int i = 0; i < numOuterLevels; i++)
457e5c31af7Sopenharmony_ci		if (outerLevels[i] <= 0.0f)
458e5c31af7Sopenharmony_ci			return true;
459e5c31af7Sopenharmony_ci	return false;
460e5c31af7Sopenharmony_ci}
461e5c31af7Sopenharmony_ci
462e5c31af7Sopenharmony_cistd::string getTessellationLevelsString (const TessLevels& tessLevels, const TessPrimitiveType primitiveType)
463e5c31af7Sopenharmony_ci{
464e5c31af7Sopenharmony_ci	std::ostringstream str;
465e5c31af7Sopenharmony_ci	switch (primitiveType)
466e5c31af7Sopenharmony_ci	{
467e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_ISOLINES:
468e5c31af7Sopenharmony_ci			str << "inner: { }, "
469e5c31af7Sopenharmony_ci				<< "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << " }";
470e5c31af7Sopenharmony_ci			break;
471e5c31af7Sopenharmony_ci
472e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_TRIANGLES:
473e5c31af7Sopenharmony_ci			str << "inner: { " << tessLevels.inner[0] << " }, "
474e5c31af7Sopenharmony_ci				<< "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << " }";
475e5c31af7Sopenharmony_ci			break;
476e5c31af7Sopenharmony_ci
477e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_QUADS:
478e5c31af7Sopenharmony_ci			str << "inner: { " << tessLevels.inner[0] << ", " << tessLevels.inner[1] << " }, "
479e5c31af7Sopenharmony_ci				<< "outer: { " << tessLevels.outer[0] << ", " << tessLevels.outer[1] << ", " << tessLevels.outer[2] << ", " << tessLevels.outer[3] << " }";
480e5c31af7Sopenharmony_ci			break;
481e5c31af7Sopenharmony_ci
482e5c31af7Sopenharmony_ci		default:
483e5c31af7Sopenharmony_ci			DE_ASSERT(false);
484e5c31af7Sopenharmony_ci	}
485e5c31af7Sopenharmony_ci
486e5c31af7Sopenharmony_ci	return str.str();
487e5c31af7Sopenharmony_ci}
488e5c31af7Sopenharmony_ci
489e5c31af7Sopenharmony_ci//! Assumes array sizes inner[2] and outer[4].
490e5c31af7Sopenharmony_cistd::string getTessellationLevelsString (const float* inner, const float* outer)
491e5c31af7Sopenharmony_ci{
492e5c31af7Sopenharmony_ci	const TessLevels tessLevels =
493e5c31af7Sopenharmony_ci	{
494e5c31af7Sopenharmony_ci		{ inner[0], inner[1] },
495e5c31af7Sopenharmony_ci		{ outer[0], outer[1], outer[2], outer[3] }
496e5c31af7Sopenharmony_ci	};
497e5c31af7Sopenharmony_ci	return getTessellationLevelsString(tessLevels, TESSPRIMITIVETYPE_QUADS);
498e5c31af7Sopenharmony_ci}
499e5c31af7Sopenharmony_ci
500e5c31af7Sopenharmony_ci// \note The tessellation coordinates generated by this function could break some of the rules given in the spec
501e5c31af7Sopenharmony_ci// (e.g. it may not exactly hold that u+v+w == 1.0f, or [uvw] + (1.0f-[uvw]) == 1.0f).
502e5c31af7Sopenharmony_cistd::vector<tcu::Vec3> generateReferenceTriangleTessCoords (const SpacingMode	spacingMode,
503e5c31af7Sopenharmony_ci															const int			inner,
504e5c31af7Sopenharmony_ci															const int			outer0,
505e5c31af7Sopenharmony_ci															const int			outer1,
506e5c31af7Sopenharmony_ci															const int			outer2)
507e5c31af7Sopenharmony_ci{
508e5c31af7Sopenharmony_ci	std::vector<tcu::Vec3> tessCoords;
509e5c31af7Sopenharmony_ci
510e5c31af7Sopenharmony_ci	if (inner == 1)
511e5c31af7Sopenharmony_ci	{
512e5c31af7Sopenharmony_ci		if (outer0 == 1 && outer1 == 1 && outer2 == 1)
513e5c31af7Sopenharmony_ci		{
514e5c31af7Sopenharmony_ci			tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f));
515e5c31af7Sopenharmony_ci			tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f));
516e5c31af7Sopenharmony_ci			tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 1.0f));
517e5c31af7Sopenharmony_ci			return tessCoords;
518e5c31af7Sopenharmony_ci		}
519e5c31af7Sopenharmony_ci		else
520e5c31af7Sopenharmony_ci			return generateReferenceTriangleTessCoords(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
521e5c31af7Sopenharmony_ci													   outer0, outer1, outer2);
522e5c31af7Sopenharmony_ci	}
523e5c31af7Sopenharmony_ci	else
524e5c31af7Sopenharmony_ci	{
525e5c31af7Sopenharmony_ci		for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(tcu::Vec3(    0.0f,        v, 1.0f - v)); }
526e5c31af7Sopenharmony_ci		for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(tcu::Vec3(1.0f - v,     0.0f,        v)); }
527e5c31af7Sopenharmony_ci		for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(tcu::Vec3(       v, 1.0f - v,     0.0f)); }
528e5c31af7Sopenharmony_ci
529e5c31af7Sopenharmony_ci		const int numInnerTriangles = inner/2;
530e5c31af7Sopenharmony_ci		for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++)
531e5c31af7Sopenharmony_ci		{
532e5c31af7Sopenharmony_ci			const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1);
533e5c31af7Sopenharmony_ci
534e5c31af7Sopenharmony_ci			if (curInnerTriangleLevel == 0)
535e5c31af7Sopenharmony_ci				tessCoords.push_back(tcu::Vec3(1.0f/3.0f));
536e5c31af7Sopenharmony_ci			else
537e5c31af7Sopenharmony_ci			{
538e5c31af7Sopenharmony_ci				const float		minUVW		= (float)(2 * (innerTriangleNdx + 1)) / (float)(3 * inner);
539e5c31af7Sopenharmony_ci				const float		maxUVW		= 1.0f - 2.0f*minUVW;
540e5c31af7Sopenharmony_ci				const tcu::Vec3	corners[3]	=
541e5c31af7Sopenharmony_ci				{
542e5c31af7Sopenharmony_ci					tcu::Vec3(maxUVW, minUVW, minUVW),
543e5c31af7Sopenharmony_ci					tcu::Vec3(minUVW, maxUVW, minUVW),
544e5c31af7Sopenharmony_ci					tcu::Vec3(minUVW, minUVW, maxUVW)
545e5c31af7Sopenharmony_ci				};
546e5c31af7Sopenharmony_ci
547e5c31af7Sopenharmony_ci				for (int i = 0; i < curInnerTriangleLevel; i++)
548e5c31af7Sopenharmony_ci				{
549e5c31af7Sopenharmony_ci					const float f = (float)i / (float)curInnerTriangleLevel;
550e5c31af7Sopenharmony_ci					for (int j = 0; j < 3; j++)
551e5c31af7Sopenharmony_ci						tessCoords.push_back((1.0f - f)*corners[j] + f*corners[(j+1)%3]);
552e5c31af7Sopenharmony_ci				}
553e5c31af7Sopenharmony_ci			}
554e5c31af7Sopenharmony_ci		}
555e5c31af7Sopenharmony_ci
556e5c31af7Sopenharmony_ci		return tessCoords;
557e5c31af7Sopenharmony_ci	}
558e5c31af7Sopenharmony_ci}
559e5c31af7Sopenharmony_ci
560e5c31af7Sopenharmony_ci// \note The tessellation coordinates generated by this function could break some of the rules given in the spec
561e5c31af7Sopenharmony_ci// (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f).
562e5c31af7Sopenharmony_cistd::vector<tcu::Vec3> generateReferenceQuadTessCoords (const SpacingMode	spacingMode,
563e5c31af7Sopenharmony_ci														const int			inner0,
564e5c31af7Sopenharmony_ci														const int			inner1,
565e5c31af7Sopenharmony_ci														const int			outer0,
566e5c31af7Sopenharmony_ci														const int			outer1,
567e5c31af7Sopenharmony_ci														const int			outer2,
568e5c31af7Sopenharmony_ci														const int			outer3)
569e5c31af7Sopenharmony_ci{
570e5c31af7Sopenharmony_ci	std::vector<tcu::Vec3> tessCoords;
571e5c31af7Sopenharmony_ci
572e5c31af7Sopenharmony_ci	if (inner0 == 1 || inner1 == 1)
573e5c31af7Sopenharmony_ci	{
574e5c31af7Sopenharmony_ci		if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1)
575e5c31af7Sopenharmony_ci		{
576e5c31af7Sopenharmony_ci			tessCoords.push_back(tcu::Vec3(0.0f, 0.0f, 0.0f));
577e5c31af7Sopenharmony_ci			tessCoords.push_back(tcu::Vec3(1.0f, 0.0f, 0.0f));
578e5c31af7Sopenharmony_ci			tessCoords.push_back(tcu::Vec3(0.0f, 1.0f, 0.0f));
579e5c31af7Sopenharmony_ci			tessCoords.push_back(tcu::Vec3(1.0f, 1.0f, 0.0f));
580e5c31af7Sopenharmony_ci			return tessCoords;
581e5c31af7Sopenharmony_ci		}
582e5c31af7Sopenharmony_ci		else
583e5c31af7Sopenharmony_ci			return generateReferenceQuadTessCoords(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
584e5c31af7Sopenharmony_ci																inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
585e5c31af7Sopenharmony_ci																outer0, outer1, outer2, outer3);
586e5c31af7Sopenharmony_ci	}
587e5c31af7Sopenharmony_ci	else
588e5c31af7Sopenharmony_ci	{
589e5c31af7Sopenharmony_ci		for (int i = 0; i < outer0; i++) { const float v = (float)i / (float)outer0; tessCoords.push_back(tcu::Vec3(    0.0f,        v, 0.0f)); }
590e5c31af7Sopenharmony_ci		for (int i = 0; i < outer1; i++) { const float v = (float)i / (float)outer1; tessCoords.push_back(tcu::Vec3(1.0f - v,     0.0f, 0.0f)); }
591e5c31af7Sopenharmony_ci		for (int i = 0; i < outer2; i++) { const float v = (float)i / (float)outer2; tessCoords.push_back(tcu::Vec3(    1.0f, 1.0f - v, 0.0f)); }
592e5c31af7Sopenharmony_ci		for (int i = 0; i < outer3; i++) { const float v = (float)i / (float)outer3; tessCoords.push_back(tcu::Vec3(       v,     1.0f, 0.0f)); }
593e5c31af7Sopenharmony_ci
594e5c31af7Sopenharmony_ci		for (int innerVtxY = 0; innerVtxY < inner1-1; innerVtxY++)
595e5c31af7Sopenharmony_ci		for (int innerVtxX = 0; innerVtxX < inner0-1; innerVtxX++)
596e5c31af7Sopenharmony_ci			tessCoords.push_back(tcu::Vec3((float)(innerVtxX + 1) / (float)inner0,
597e5c31af7Sopenharmony_ci										   (float)(innerVtxY + 1) / (float)inner1,
598e5c31af7Sopenharmony_ci										   0.0f));
599e5c31af7Sopenharmony_ci
600e5c31af7Sopenharmony_ci		return tessCoords;
601e5c31af7Sopenharmony_ci	}
602e5c31af7Sopenharmony_ci}
603e5c31af7Sopenharmony_ci
604e5c31af7Sopenharmony_ci// \note The tessellation coordinates generated by this function could break some of the rules given in the spec
605e5c31af7Sopenharmony_ci// (e.g. it may not exactly hold that [uv] + (1.0f-[uv]) == 1.0f).
606e5c31af7Sopenharmony_cistd::vector<tcu::Vec3> generateReferenceIsolineTessCoords (const int outer0, const int outer1)
607e5c31af7Sopenharmony_ci{
608e5c31af7Sopenharmony_ci	std::vector<tcu::Vec3> tessCoords;
609e5c31af7Sopenharmony_ci
610e5c31af7Sopenharmony_ci	for (int y = 0; y < outer0;   y++)
611e5c31af7Sopenharmony_ci	for (int x = 0; x < outer1+1; x++)
612e5c31af7Sopenharmony_ci		tessCoords.push_back(tcu::Vec3((float)x / (float)outer1,
613e5c31af7Sopenharmony_ci									   (float)y / (float)outer0,
614e5c31af7Sopenharmony_ci									   0.0f));
615e5c31af7Sopenharmony_ci
616e5c31af7Sopenharmony_ci	return tessCoords;
617e5c31af7Sopenharmony_ci}
618e5c31af7Sopenharmony_ci
619e5c31af7Sopenharmony_cistatic int referencePointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels)
620e5c31af7Sopenharmony_ci{
621e5c31af7Sopenharmony_ci	if (isPatchDiscarded(primitiveType, outerLevels))
622e5c31af7Sopenharmony_ci		return 0;
623e5c31af7Sopenharmony_ci
624e5c31af7Sopenharmony_ci	switch (primitiveType)
625e5c31af7Sopenharmony_ci	{
626e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_TRIANGLES:
627e5c31af7Sopenharmony_ci		{
628e5c31af7Sopenharmony_ci			int inner;
629e5c31af7Sopenharmony_ci			int outer[3];
630e5c31af7Sopenharmony_ci			getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]);
631e5c31af7Sopenharmony_ci			return static_cast<int>(generateReferenceTriangleTessCoords(spacingMode, inner, outer[0], outer[1], outer[2]).size());
632e5c31af7Sopenharmony_ci		}
633e5c31af7Sopenharmony_ci
634e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_QUADS:
635e5c31af7Sopenharmony_ci		{
636e5c31af7Sopenharmony_ci			int inner[2];
637e5c31af7Sopenharmony_ci			int outer[4];
638e5c31af7Sopenharmony_ci			getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]);
639e5c31af7Sopenharmony_ci			return static_cast<int>(generateReferenceQuadTessCoords(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]).size());
640e5c31af7Sopenharmony_ci		}
641e5c31af7Sopenharmony_ci
642e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_ISOLINES:
643e5c31af7Sopenharmony_ci		{
644e5c31af7Sopenharmony_ci			int outer[2];
645e5c31af7Sopenharmony_ci			getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]);
646e5c31af7Sopenharmony_ci			return static_cast<int>(generateReferenceIsolineTessCoords(outer[0], outer[1]).size());
647e5c31af7Sopenharmony_ci		}
648e5c31af7Sopenharmony_ci
649e5c31af7Sopenharmony_ci		default:
650e5c31af7Sopenharmony_ci			DE_ASSERT(false);
651e5c31af7Sopenharmony_ci			return 0;
652e5c31af7Sopenharmony_ci	}
653e5c31af7Sopenharmony_ci}
654e5c31af7Sopenharmony_ci
655e5c31af7Sopenharmony_cistatic int referenceTriangleNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner, const int outer0, const int outer1, const int outer2)
656e5c31af7Sopenharmony_ci{
657e5c31af7Sopenharmony_ci	if (inner == 1)
658e5c31af7Sopenharmony_ci	{
659e5c31af7Sopenharmony_ci		if (outer0 == 1 && outer1 == 1 && outer2 == 1)
660e5c31af7Sopenharmony_ci			return 1;
661e5c31af7Sopenharmony_ci		else
662e5c31af7Sopenharmony_ci			return referenceTriangleNonPointModePrimitiveCount(spacingMode, spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
663e5c31af7Sopenharmony_ci																			outer0, outer1, outer2);
664e5c31af7Sopenharmony_ci	}
665e5c31af7Sopenharmony_ci	else
666e5c31af7Sopenharmony_ci	{
667e5c31af7Sopenharmony_ci		int result = outer0 + outer1 + outer2;
668e5c31af7Sopenharmony_ci
669e5c31af7Sopenharmony_ci		const int numInnerTriangles = inner/2;
670e5c31af7Sopenharmony_ci		for (int innerTriangleNdx = 0; innerTriangleNdx < numInnerTriangles; innerTriangleNdx++)
671e5c31af7Sopenharmony_ci		{
672e5c31af7Sopenharmony_ci			const int curInnerTriangleLevel = inner - 2*(innerTriangleNdx+1);
673e5c31af7Sopenharmony_ci
674e5c31af7Sopenharmony_ci			if (curInnerTriangleLevel == 1)
675e5c31af7Sopenharmony_ci				result += 4;
676e5c31af7Sopenharmony_ci			else
677e5c31af7Sopenharmony_ci				result += 2*3*curInnerTriangleLevel;
678e5c31af7Sopenharmony_ci		}
679e5c31af7Sopenharmony_ci
680e5c31af7Sopenharmony_ci		return result;
681e5c31af7Sopenharmony_ci	}
682e5c31af7Sopenharmony_ci}
683e5c31af7Sopenharmony_ci
684e5c31af7Sopenharmony_cistatic int referenceQuadNonPointModePrimitiveCount (const SpacingMode spacingMode, const int inner0, const int inner1, const int outer0, const int outer1, const int outer2, const int outer3)
685e5c31af7Sopenharmony_ci{
686e5c31af7Sopenharmony_ci	if (inner0 == 1 || inner1 == 1)
687e5c31af7Sopenharmony_ci	{
688e5c31af7Sopenharmony_ci		if (inner0 == 1 && inner1 == 1 && outer0 == 1 && outer1 == 1 && outer2 == 1 && outer3 == 1)
689e5c31af7Sopenharmony_ci			return 2;
690e5c31af7Sopenharmony_ci		else
691e5c31af7Sopenharmony_ci			return referenceQuadNonPointModePrimitiveCount(spacingMode, inner0 > 1 ? inner0 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
692e5c31af7Sopenharmony_ci																		inner1 > 1 ? inner1 : spacingMode == SPACINGMODE_FRACTIONAL_ODD ? 3 : 2,
693e5c31af7Sopenharmony_ci																		outer0, outer1, outer2, outer3);
694e5c31af7Sopenharmony_ci	}
695e5c31af7Sopenharmony_ci	else
696e5c31af7Sopenharmony_ci		return 2*(inner0-2)*(inner1-2) + 2*(inner0-2) + 2*(inner1-2) + outer0+outer1+outer2+outer3;
697e5c31af7Sopenharmony_ci}
698e5c31af7Sopenharmony_ci
699e5c31af7Sopenharmony_cistatic inline int referenceIsolineNonPointModePrimitiveCount (const int outer0, const int outer1)
700e5c31af7Sopenharmony_ci{
701e5c31af7Sopenharmony_ci	return outer0*outer1;
702e5c31af7Sopenharmony_ci}
703e5c31af7Sopenharmony_ci
704e5c31af7Sopenharmony_cistatic int referenceNonPointModePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const float* innerLevels, const float* outerLevels)
705e5c31af7Sopenharmony_ci{
706e5c31af7Sopenharmony_ci	if (isPatchDiscarded(primitiveType, outerLevels))
707e5c31af7Sopenharmony_ci		return 0;
708e5c31af7Sopenharmony_ci
709e5c31af7Sopenharmony_ci	switch (primitiveType)
710e5c31af7Sopenharmony_ci	{
711e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_TRIANGLES:
712e5c31af7Sopenharmony_ci		{
713e5c31af7Sopenharmony_ci			int inner;
714e5c31af7Sopenharmony_ci			int outer[3];
715e5c31af7Sopenharmony_ci			getClampedRoundedTriangleTessLevels(spacingMode, innerLevels, outerLevels, &inner, &outer[0]);
716e5c31af7Sopenharmony_ci			return referenceTriangleNonPointModePrimitiveCount(spacingMode, inner, outer[0], outer[1], outer[2]);
717e5c31af7Sopenharmony_ci		}
718e5c31af7Sopenharmony_ci
719e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_QUADS:
720e5c31af7Sopenharmony_ci		{
721e5c31af7Sopenharmony_ci			int inner[2];
722e5c31af7Sopenharmony_ci			int outer[4];
723e5c31af7Sopenharmony_ci			getClampedRoundedQuadTessLevels(spacingMode, innerLevels, outerLevels, &inner[0], &outer[0]);
724e5c31af7Sopenharmony_ci			return referenceQuadNonPointModePrimitiveCount(spacingMode, inner[0], inner[1], outer[0], outer[1], outer[2], outer[3]);
725e5c31af7Sopenharmony_ci		}
726e5c31af7Sopenharmony_ci
727e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_ISOLINES:
728e5c31af7Sopenharmony_ci		{
729e5c31af7Sopenharmony_ci			int outer[2];
730e5c31af7Sopenharmony_ci			getClampedRoundedIsolineTessLevels(spacingMode, &outerLevels[0], &outer[0]);
731e5c31af7Sopenharmony_ci			return referenceIsolineNonPointModePrimitiveCount(outer[0], outer[1]);
732e5c31af7Sopenharmony_ci		}
733e5c31af7Sopenharmony_ci
734e5c31af7Sopenharmony_ci		default:
735e5c31af7Sopenharmony_ci			DE_ASSERT(false);
736e5c31af7Sopenharmony_ci			return 0;
737e5c31af7Sopenharmony_ci	}
738e5c31af7Sopenharmony_ci}
739e5c31af7Sopenharmony_ci
740e5c31af7Sopenharmony_ciint numVerticesPerPrimitive (const TessPrimitiveType primitiveType, const bool usePointMode)
741e5c31af7Sopenharmony_ci{
742e5c31af7Sopenharmony_ci	if (usePointMode)
743e5c31af7Sopenharmony_ci		return 1;
744e5c31af7Sopenharmony_ci
745e5c31af7Sopenharmony_ci	switch (primitiveType)
746e5c31af7Sopenharmony_ci	{
747e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_TRIANGLES:	return 3;
748e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_QUADS:		return 3;  // quads are composed of two triangles
749e5c31af7Sopenharmony_ci		case TESSPRIMITIVETYPE_ISOLINES:	return 2;
750e5c31af7Sopenharmony_ci		default:
751e5c31af7Sopenharmony_ci			DE_ASSERT(false);
752e5c31af7Sopenharmony_ci			return 0;
753e5c31af7Sopenharmony_ci	}
754e5c31af7Sopenharmony_ci}
755e5c31af7Sopenharmony_ci
756e5c31af7Sopenharmony_ciint referencePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels)
757e5c31af7Sopenharmony_ci{
758e5c31af7Sopenharmony_ci	return usePointMode ? referencePointModePrimitiveCount		(primitiveType, spacingMode, innerLevels, outerLevels)
759e5c31af7Sopenharmony_ci						: referenceNonPointModePrimitiveCount	(primitiveType, spacingMode, innerLevels, outerLevels);
760e5c31af7Sopenharmony_ci}
761e5c31af7Sopenharmony_ci
762e5c31af7Sopenharmony_ci//! In point mode this should return the number of unique vertices, while in non-point mode the maximum theoretical number of verticies.
763e5c31af7Sopenharmony_ci//! Actual implementation will likely return a much smaller number because the shader isn't required to be run for duplicate coordinates.
764e5c31af7Sopenharmony_ciint referenceVertexCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* innerLevels, const float* outerLevels)
765e5c31af7Sopenharmony_ci{
766e5c31af7Sopenharmony_ci	return referencePrimitiveCount(primitiveType, spacingMode, usePointMode, innerLevels, outerLevels)
767e5c31af7Sopenharmony_ci		   * numVerticesPerPrimitive(primitiveType, usePointMode);
768e5c31af7Sopenharmony_ci}
769e5c31af7Sopenharmony_ci
770e5c31af7Sopenharmony_civoid requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
771e5c31af7Sopenharmony_ci{
772e5c31af7Sopenharmony_ci	const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
773e5c31af7Sopenharmony_ci
774e5c31af7Sopenharmony_ci	if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
775e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("Tessellation shader not supported");
776e5c31af7Sopenharmony_ci
777e5c31af7Sopenharmony_ci	if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
778e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("Geometry shader not supported");
779e5c31af7Sopenharmony_ci
780e5c31af7Sopenharmony_ci	if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
781e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("Double-precision floats not supported");
782e5c31af7Sopenharmony_ci
783e5c31af7Sopenharmony_ci	if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
784e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
785e5c31af7Sopenharmony_ci
786e5c31af7Sopenharmony_ci	if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
787e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
788e5c31af7Sopenharmony_ci
789e5c31af7Sopenharmony_ci	if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
790e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
791e5c31af7Sopenharmony_ci}
792e5c31af7Sopenharmony_ci
793e5c31af7Sopenharmony_ci} // tessellation
794e5c31af7Sopenharmony_ci} // vkt
795