1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2017 Google Inc.
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Graphics pipeline for SPIR-V assembly tests
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "vktSpvAsmGraphicsShaderTestUtil.hpp"
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "tcuFloat.hpp"
27e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
28e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
29e5c31af7Sopenharmony_ci
30e5c31af7Sopenharmony_ci#include "vkDefs.hpp"
31e5c31af7Sopenharmony_ci#include "vkMemUtil.hpp"
32e5c31af7Sopenharmony_ci#include "vkPlatform.hpp"
33e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
34e5c31af7Sopenharmony_ci#include "vkRefUtil.hpp"
35e5c31af7Sopenharmony_ci#include "vkTypeUtil.hpp"
36e5c31af7Sopenharmony_ci#include "vkImageUtil.hpp"
37e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp"
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_ci#include "deRandom.hpp"
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_cinamespace vkt
42e5c31af7Sopenharmony_ci{
43e5c31af7Sopenharmony_cinamespace SpirVAssembly
44e5c31af7Sopenharmony_ci{
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_ciusing namespace vk;
47e5c31af7Sopenharmony_ciusing std::map;
48e5c31af7Sopenharmony_ciusing std::string;
49e5c31af7Sopenharmony_ciusing std::vector;
50e5c31af7Sopenharmony_ciusing tcu::Float16;
51e5c31af7Sopenharmony_ciusing tcu::Float32;
52e5c31af7Sopenharmony_ciusing tcu::Float64;
53e5c31af7Sopenharmony_ciusing tcu::IVec3;
54e5c31af7Sopenharmony_ciusing tcu::IVec4;
55e5c31af7Sopenharmony_ciusing tcu::RGBA;
56e5c31af7Sopenharmony_ciusing tcu::TestLog;
57e5c31af7Sopenharmony_ciusing tcu::TestStatus;
58e5c31af7Sopenharmony_ciusing tcu::Vec4;
59e5c31af7Sopenharmony_ciusing de::UniquePtr;
60e5c31af7Sopenharmony_ciusing tcu::StringTemplate;
61e5c31af7Sopenharmony_ciusing tcu::Vec4;
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_cideUint32 IFDataType::getElementNumBytes (void) const
64e5c31af7Sopenharmony_ci{
65e5c31af7Sopenharmony_ci	if (elementType < NUMBERTYPE_END32)
66e5c31af7Sopenharmony_ci		return 4;
67e5c31af7Sopenharmony_ci
68e5c31af7Sopenharmony_ci	if (elementType < NUMBERTYPE_END16)
69e5c31af7Sopenharmony_ci		return 2;
70e5c31af7Sopenharmony_ci
71e5c31af7Sopenharmony_ci	return 8;
72e5c31af7Sopenharmony_ci}
73e5c31af7Sopenharmony_ci
74e5c31af7Sopenharmony_ciVkFormat IFDataType::getVkFormat (void) const
75e5c31af7Sopenharmony_ci{
76e5c31af7Sopenharmony_ci	if (numElements == 1)
77e5c31af7Sopenharmony_ci	{
78e5c31af7Sopenharmony_ci		switch (elementType)
79e5c31af7Sopenharmony_ci		{
80e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT64:	return VK_FORMAT_R64_SFLOAT;
81e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32_SFLOAT;
82e5c31af7Sopenharmony_ci			case NUMBERTYPE_INT32:		return VK_FORMAT_R32_SINT;
83e5c31af7Sopenharmony_ci			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32_UINT;
84e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16_SFLOAT;
85e5c31af7Sopenharmony_ci			case NUMBERTYPE_INT16:		return VK_FORMAT_R16_SINT;
86e5c31af7Sopenharmony_ci			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16_UINT;
87e5c31af7Sopenharmony_ci			default:					break;
88e5c31af7Sopenharmony_ci		}
89e5c31af7Sopenharmony_ci	}
90e5c31af7Sopenharmony_ci	else if (numElements == 2)
91e5c31af7Sopenharmony_ci	{
92e5c31af7Sopenharmony_ci		switch (elementType)
93e5c31af7Sopenharmony_ci		{
94e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT64:	return VK_FORMAT_R64G64_SFLOAT;
95e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32G32_SFLOAT;
96e5c31af7Sopenharmony_ci			case NUMBERTYPE_INT32:		return VK_FORMAT_R32G32_SINT;
97e5c31af7Sopenharmony_ci			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32G32_UINT;
98e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16G16_SFLOAT;
99e5c31af7Sopenharmony_ci			case NUMBERTYPE_INT16:		return VK_FORMAT_R16G16_SINT;
100e5c31af7Sopenharmony_ci			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16G16_UINT;
101e5c31af7Sopenharmony_ci			default:					break;
102e5c31af7Sopenharmony_ci		}
103e5c31af7Sopenharmony_ci	}
104e5c31af7Sopenharmony_ci	else if (numElements == 3)
105e5c31af7Sopenharmony_ci	{
106e5c31af7Sopenharmony_ci		switch (elementType)
107e5c31af7Sopenharmony_ci		{
108e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT64:	return VK_FORMAT_R64G64B64_SFLOAT;
109e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32G32B32_SFLOAT;
110e5c31af7Sopenharmony_ci			case NUMBERTYPE_INT32:		return VK_FORMAT_R32G32B32_SINT;
111e5c31af7Sopenharmony_ci			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32G32B32_UINT;
112e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16G16B16_SFLOAT;
113e5c31af7Sopenharmony_ci			case NUMBERTYPE_INT16:		return VK_FORMAT_R16G16B16_SINT;
114e5c31af7Sopenharmony_ci			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16G16B16_UINT;
115e5c31af7Sopenharmony_ci			default:					break;
116e5c31af7Sopenharmony_ci		}
117e5c31af7Sopenharmony_ci	}
118e5c31af7Sopenharmony_ci	else if (numElements == 4)
119e5c31af7Sopenharmony_ci	{
120e5c31af7Sopenharmony_ci		switch (elementType)
121e5c31af7Sopenharmony_ci		{
122e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT64:	return VK_FORMAT_R64G64B64A64_SFLOAT;
123e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32G32B32A32_SFLOAT;
124e5c31af7Sopenharmony_ci			case NUMBERTYPE_INT32:		return VK_FORMAT_R32G32B32A32_SINT;
125e5c31af7Sopenharmony_ci			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32G32B32A32_UINT;
126e5c31af7Sopenharmony_ci			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16G16B16A16_SFLOAT;
127e5c31af7Sopenharmony_ci			case NUMBERTYPE_INT16:		return VK_FORMAT_R16G16B16A16_SINT;
128e5c31af7Sopenharmony_ci			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16G16B16A16_UINT;
129e5c31af7Sopenharmony_ci			default:					break;
130e5c31af7Sopenharmony_ci		}
131e5c31af7Sopenharmony_ci	}
132e5c31af7Sopenharmony_ci
133e5c31af7Sopenharmony_ci	DE_ASSERT(false);
134e5c31af7Sopenharmony_ci	return VK_FORMAT_UNDEFINED;
135e5c31af7Sopenharmony_ci}
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_citcu::TextureFormat IFDataType::getTextureFormat (void) const
138e5c31af7Sopenharmony_ci{
139e5c31af7Sopenharmony_ci	tcu::TextureFormat::ChannelType		ct	= tcu::TextureFormat::CHANNELTYPE_LAST;
140e5c31af7Sopenharmony_ci	tcu::TextureFormat::ChannelOrder	co	= tcu::TextureFormat::CHANNELORDER_LAST;
141e5c31af7Sopenharmony_ci
142e5c31af7Sopenharmony_ci	switch (elementType)
143e5c31af7Sopenharmony_ci	{
144e5c31af7Sopenharmony_ci		case NUMBERTYPE_FLOAT64:	ct = tcu::TextureFormat::FLOAT64;			break;
145e5c31af7Sopenharmony_ci		case NUMBERTYPE_FLOAT32:	ct = tcu::TextureFormat::FLOAT;				break;
146e5c31af7Sopenharmony_ci		case NUMBERTYPE_INT32:		ct = tcu::TextureFormat::SIGNED_INT32;		break;
147e5c31af7Sopenharmony_ci		case NUMBERTYPE_UINT32:		ct = tcu::TextureFormat::UNSIGNED_INT32;	break;
148e5c31af7Sopenharmony_ci		case NUMBERTYPE_FLOAT16:	ct = tcu::TextureFormat::HALF_FLOAT;		break;
149e5c31af7Sopenharmony_ci		case NUMBERTYPE_INT16:		ct = tcu::TextureFormat::SIGNED_INT16;		break;
150e5c31af7Sopenharmony_ci		case NUMBERTYPE_UINT16:		ct = tcu::TextureFormat::UNSIGNED_INT16;	break;
151e5c31af7Sopenharmony_ci		default:					DE_ASSERT(false);
152e5c31af7Sopenharmony_ci	}
153e5c31af7Sopenharmony_ci
154e5c31af7Sopenharmony_ci	switch (numElements)
155e5c31af7Sopenharmony_ci	{
156e5c31af7Sopenharmony_ci		case 1:				co = tcu::TextureFormat::R;					break;
157e5c31af7Sopenharmony_ci		case 2:				co = tcu::TextureFormat::RG;				break;
158e5c31af7Sopenharmony_ci		case 3:				co = tcu::TextureFormat::RGB;				break;
159e5c31af7Sopenharmony_ci		case 4:				co = tcu::TextureFormat::RGBA;				break;
160e5c31af7Sopenharmony_ci		default:			DE_ASSERT(false);
161e5c31af7Sopenharmony_ci	}
162e5c31af7Sopenharmony_ci
163e5c31af7Sopenharmony_ci	return tcu::TextureFormat(co, ct);
164e5c31af7Sopenharmony_ci}
165e5c31af7Sopenharmony_ci
166e5c31af7Sopenharmony_cistring IFDataType::str (void) const
167e5c31af7Sopenharmony_ci{
168e5c31af7Sopenharmony_ci	string	ret;
169e5c31af7Sopenharmony_ci
170e5c31af7Sopenharmony_ci	switch (elementType)
171e5c31af7Sopenharmony_ci	{
172e5c31af7Sopenharmony_ci		case NUMBERTYPE_FLOAT64:	ret = "f64"; break;
173e5c31af7Sopenharmony_ci		case NUMBERTYPE_FLOAT32:	ret = "f32"; break;
174e5c31af7Sopenharmony_ci		case NUMBERTYPE_INT32:		ret = "i32"; break;
175e5c31af7Sopenharmony_ci		case NUMBERTYPE_UINT32:		ret = "u32"; break;
176e5c31af7Sopenharmony_ci		case NUMBERTYPE_FLOAT16:	ret = "f16"; break;
177e5c31af7Sopenharmony_ci		case NUMBERTYPE_INT16:		ret = "i16"; break;
178e5c31af7Sopenharmony_ci		case NUMBERTYPE_UINT16:		ret = "u16"; break;
179e5c31af7Sopenharmony_ci		default:					DE_ASSERT(false);
180e5c31af7Sopenharmony_ci	}
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_ci	if (numElements == 1)
183e5c31af7Sopenharmony_ci		return ret;
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_ci	return string("v") + numberToString(numElements) + ret;
186e5c31af7Sopenharmony_ci}
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ciVkBufferUsageFlagBits getMatchingBufferUsageFlagBit (VkDescriptorType dType)
189e5c31af7Sopenharmony_ci{
190e5c31af7Sopenharmony_ci	switch (dType)
191e5c31af7Sopenharmony_ci	{
192e5c31af7Sopenharmony_ci		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:			return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
193e5c31af7Sopenharmony_ci		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:			return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
194e5c31af7Sopenharmony_ci		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:			return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
195e5c31af7Sopenharmony_ci		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:			return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
196e5c31af7Sopenharmony_ci		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:	return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
197e5c31af7Sopenharmony_ci		default:										DE_ASSERT(0 && "not implemented");
198e5c31af7Sopenharmony_ci	}
199e5c31af7Sopenharmony_ci	return (VkBufferUsageFlagBits)0;
200e5c31af7Sopenharmony_ci}
201e5c31af7Sopenharmony_ci
202e5c31af7Sopenharmony_ciVkImageUsageFlags getMatchingImageUsageFlags (VkDescriptorType dType)
203e5c31af7Sopenharmony_ci{
204e5c31af7Sopenharmony_ci	switch (dType)
205e5c31af7Sopenharmony_ci	{
206e5c31af7Sopenharmony_ci		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:			return VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
207e5c31af7Sopenharmony_ci		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:			return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
208e5c31af7Sopenharmony_ci		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:	return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
209e5c31af7Sopenharmony_ci		default:										DE_FATAL("Not implemented");
210e5c31af7Sopenharmony_ci	}
211e5c31af7Sopenharmony_ci	return (VkImageUsageFlags)0;
212e5c31af7Sopenharmony_ci}
213e5c31af7Sopenharmony_ci
214e5c31af7Sopenharmony_cistatic void requireFormatUsageSupport (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkFormat format, VkImageTiling imageTiling, VkImageUsageFlags requiredUsageFlags)
215e5c31af7Sopenharmony_ci{
216e5c31af7Sopenharmony_ci	VkFormatProperties		properties;
217e5c31af7Sopenharmony_ci	VkFormatFeatureFlags	tilingFeatures	= 0;
218e5c31af7Sopenharmony_ci
219e5c31af7Sopenharmony_ci	vki.getPhysicalDeviceFormatProperties(physicalDevice, format, &properties);
220e5c31af7Sopenharmony_ci
221e5c31af7Sopenharmony_ci	switch (imageTiling)
222e5c31af7Sopenharmony_ci	{
223e5c31af7Sopenharmony_ci		case VK_IMAGE_TILING_LINEAR:
224e5c31af7Sopenharmony_ci			tilingFeatures = properties.linearTilingFeatures;
225e5c31af7Sopenharmony_ci			break;
226e5c31af7Sopenharmony_ci
227e5c31af7Sopenharmony_ci		case VK_IMAGE_TILING_OPTIMAL:
228e5c31af7Sopenharmony_ci			tilingFeatures = properties.optimalTilingFeatures;
229e5c31af7Sopenharmony_ci			break;
230e5c31af7Sopenharmony_ci
231e5c31af7Sopenharmony_ci		default:
232e5c31af7Sopenharmony_ci			DE_ASSERT(false);
233e5c31af7Sopenharmony_ci			break;
234e5c31af7Sopenharmony_ci	}
235e5c31af7Sopenharmony_ci
236e5c31af7Sopenharmony_ci	if ((requiredUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0)
237e5c31af7Sopenharmony_ci	{
238e5c31af7Sopenharmony_ci		if ((tilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
239e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Image format cannot be used as color attachment");
240e5c31af7Sopenharmony_ci		requiredUsageFlags ^= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
241e5c31af7Sopenharmony_ci	}
242e5c31af7Sopenharmony_ci
243e5c31af7Sopenharmony_ci
244e5c31af7Sopenharmony_ci	if ((requiredUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) != 0)
245e5c31af7Sopenharmony_ci	{
246e5c31af7Sopenharmony_ci		if ((tilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0)
247e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, "Image format cannot be used as transfer source");
248e5c31af7Sopenharmony_ci		requiredUsageFlags ^= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
249e5c31af7Sopenharmony_ci	}
250e5c31af7Sopenharmony_ci
251e5c31af7Sopenharmony_ci
252e5c31af7Sopenharmony_ci	DE_ASSERT(!requiredUsageFlags && "checking other image usage bits not supported yet");
253e5c31af7Sopenharmony_ci}
254e5c31af7Sopenharmony_ci
255e5c31af7Sopenharmony_ciInstanceContext::InstanceContext (const RGBA						(&inputs)[4],
256e5c31af7Sopenharmony_ci								  const RGBA						(&outputs)[4],
257e5c31af7Sopenharmony_ci								  const map<string, string>&		testCodeFragments_,
258e5c31af7Sopenharmony_ci								  const StageToSpecConstantMap&		specConstants_,
259e5c31af7Sopenharmony_ci								  const PushConstants&				pushConsants_,
260e5c31af7Sopenharmony_ci								  const GraphicsResources&			resources_,
261e5c31af7Sopenharmony_ci								  const GraphicsInterfaces&			interfaces_,
262e5c31af7Sopenharmony_ci								  const vector<string>&				extensions_,
263e5c31af7Sopenharmony_ci								  VulkanFeatures					vulkanFeatures_,
264e5c31af7Sopenharmony_ci								  VkShaderStageFlags				customizedStages_)
265e5c31af7Sopenharmony_ci	: testCodeFragments				(testCodeFragments_)
266e5c31af7Sopenharmony_ci	, specConstants					(specConstants_)
267e5c31af7Sopenharmony_ci	, hasTessellation				(false)
268e5c31af7Sopenharmony_ci	, requiredStages				(static_cast<VkShaderStageFlagBits>(0))
269e5c31af7Sopenharmony_ci	, requiredDeviceExtensions		(extensions_)
270e5c31af7Sopenharmony_ci	, requestedFeatures				(vulkanFeatures_)
271e5c31af7Sopenharmony_ci	, pushConstants					(pushConsants_)
272e5c31af7Sopenharmony_ci	, customizedStages				(customizedStages_)
273e5c31af7Sopenharmony_ci	, resources						(resources_)
274e5c31af7Sopenharmony_ci	, interfaces					(interfaces_)
275e5c31af7Sopenharmony_ci	, failResult					(QP_TEST_RESULT_FAIL)
276e5c31af7Sopenharmony_ci	, failMessageTemplate			("${reason}")
277e5c31af7Sopenharmony_ci	, renderFullSquare				(false)
278e5c31af7Sopenharmony_ci	, splitRenderArea				(false)
279e5c31af7Sopenharmony_ci{
280e5c31af7Sopenharmony_ci	inputColors[0]		= inputs[0];
281e5c31af7Sopenharmony_ci	inputColors[1]		= inputs[1];
282e5c31af7Sopenharmony_ci	inputColors[2]		= inputs[2];
283e5c31af7Sopenharmony_ci	inputColors[3]		= inputs[3];
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_ci	outputColors[0]		= outputs[0];
286e5c31af7Sopenharmony_ci	outputColors[1]		= outputs[1];
287e5c31af7Sopenharmony_ci	outputColors[2]		= outputs[2];
288e5c31af7Sopenharmony_ci	outputColors[3]		= outputs[3];
289e5c31af7Sopenharmony_ci}
290e5c31af7Sopenharmony_ci
291e5c31af7Sopenharmony_ciInstanceContext::InstanceContext (const InstanceContext& other)
292e5c31af7Sopenharmony_ci	: moduleMap						(other.moduleMap)
293e5c31af7Sopenharmony_ci	, testCodeFragments				(other.testCodeFragments)
294e5c31af7Sopenharmony_ci	, specConstants					(other.specConstants)
295e5c31af7Sopenharmony_ci	, hasTessellation				(other.hasTessellation)
296e5c31af7Sopenharmony_ci	, requiredStages				(other.requiredStages)
297e5c31af7Sopenharmony_ci	, requiredDeviceExtensions		(other.requiredDeviceExtensions)
298e5c31af7Sopenharmony_ci	, requestedFeatures				(other.requestedFeatures)
299e5c31af7Sopenharmony_ci	, pushConstants					(other.pushConstants)
300e5c31af7Sopenharmony_ci	, customizedStages				(other.customizedStages)
301e5c31af7Sopenharmony_ci	, resources						(other.resources)
302e5c31af7Sopenharmony_ci	, interfaces					(other.interfaces)
303e5c31af7Sopenharmony_ci	, failResult					(other.failResult)
304e5c31af7Sopenharmony_ci	, failMessageTemplate			(other.failMessageTemplate)
305e5c31af7Sopenharmony_ci	, renderFullSquare				(other.renderFullSquare)
306e5c31af7Sopenharmony_ci	, splitRenderArea				(other.splitRenderArea)
307e5c31af7Sopenharmony_ci{
308e5c31af7Sopenharmony_ci	inputColors[0]		= other.inputColors[0];
309e5c31af7Sopenharmony_ci	inputColors[1]		= other.inputColors[1];
310e5c31af7Sopenharmony_ci	inputColors[2]		= other.inputColors[2];
311e5c31af7Sopenharmony_ci	inputColors[3]		= other.inputColors[3];
312e5c31af7Sopenharmony_ci
313e5c31af7Sopenharmony_ci	outputColors[0]		= other.outputColors[0];
314e5c31af7Sopenharmony_ci	outputColors[1]		= other.outputColors[1];
315e5c31af7Sopenharmony_ci	outputColors[2]		= other.outputColors[2];
316e5c31af7Sopenharmony_ci	outputColors[3]		= other.outputColors[3];
317e5c31af7Sopenharmony_ci}
318e5c31af7Sopenharmony_ci
319e5c31af7Sopenharmony_cistring InstanceContext::getSpecializedFailMessage (const string& failureReason)
320e5c31af7Sopenharmony_ci{
321e5c31af7Sopenharmony_ci	map<string, string>		parameters;
322e5c31af7Sopenharmony_ci	parameters["reason"]	= failureReason;
323e5c31af7Sopenharmony_ci	return StringTemplate(failMessageTemplate).specialize(parameters);
324e5c31af7Sopenharmony_ci}
325e5c31af7Sopenharmony_ci
326e5c31af7Sopenharmony_ciInstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
327e5c31af7Sopenharmony_ci									   const tcu::RGBA								(&inputColors)[4],
328e5c31af7Sopenharmony_ci									   const tcu::RGBA								(&outputColors)[4],
329e5c31af7Sopenharmony_ci									   const std::map<std::string, std::string>&	testCodeFragments,
330e5c31af7Sopenharmony_ci									   const StageToSpecConstantMap&				specConstants,
331e5c31af7Sopenharmony_ci									   const PushConstants&							pushConstants,
332e5c31af7Sopenharmony_ci									   const GraphicsResources&						resources,
333e5c31af7Sopenharmony_ci									   const GraphicsInterfaces&					interfaces,
334e5c31af7Sopenharmony_ci									   const std::vector<std::string>&				extensions,
335e5c31af7Sopenharmony_ci									   VulkanFeatures								vulkanFeatures,
336e5c31af7Sopenharmony_ci									   VkShaderStageFlags							customizedStages,
337e5c31af7Sopenharmony_ci									   const qpTestResult							failResult,
338e5c31af7Sopenharmony_ci									   const std::string&							failMessageTemplate)
339e5c31af7Sopenharmony_ci{
340e5c31af7Sopenharmony_ci	InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources, interfaces, extensions, vulkanFeatures, customizedStages);
341e5c31af7Sopenharmony_ci	for (size_t i = 0; i < elements.size(); ++i)
342e5c31af7Sopenharmony_ci	{
343e5c31af7Sopenharmony_ci		ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage));
344e5c31af7Sopenharmony_ci		ctx.requiredStages = static_cast<VkShaderStageFlagBits>(ctx.requiredStages | elements[i].stage);
345e5c31af7Sopenharmony_ci	}
346e5c31af7Sopenharmony_ci	ctx.failResult				= failResult;
347e5c31af7Sopenharmony_ci	if (!failMessageTemplate.empty())
348e5c31af7Sopenharmony_ci		ctx.failMessageTemplate	= failMessageTemplate;
349e5c31af7Sopenharmony_ci	return ctx;
350e5c31af7Sopenharmony_ci}
351e5c31af7Sopenharmony_ci
352e5c31af7Sopenharmony_ciInstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
353e5c31af7Sopenharmony_ci									   tcu::RGBA									(&inputColors)[4],
354e5c31af7Sopenharmony_ci									   const tcu::RGBA								(&outputColors)[4],
355e5c31af7Sopenharmony_ci									   const std::map<std::string, std::string>&	testCodeFragments)
356e5c31af7Sopenharmony_ci{
357e5c31af7Sopenharmony_ci	return createInstanceContext(elements, inputColors, outputColors, testCodeFragments,
358e5c31af7Sopenharmony_ci								 StageToSpecConstantMap(), PushConstants(), GraphicsResources(),
359e5c31af7Sopenharmony_ci								 GraphicsInterfaces(), std::vector<std::string>(),
360e5c31af7Sopenharmony_ci								 VulkanFeatures(), vk::VK_SHADER_STAGE_ALL);
361e5c31af7Sopenharmony_ci}
362e5c31af7Sopenharmony_ci
363e5c31af7Sopenharmony_ciInstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
364e5c31af7Sopenharmony_ci									   const std::map<std::string, std::string>&	testCodeFragments)
365e5c31af7Sopenharmony_ci{
366e5c31af7Sopenharmony_ci	tcu::RGBA defaultColors[4];
367e5c31af7Sopenharmony_ci	getDefaultColors(defaultColors);
368e5c31af7Sopenharmony_ci	return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments);
369e5c31af7Sopenharmony_ci}
370e5c31af7Sopenharmony_ci
371e5c31af7Sopenharmony_ciUnusedVariableContext createUnusedVariableContext(const ShaderTaskArray& shaderTasks, const VariableLocation& location)
372e5c31af7Sopenharmony_ci{
373e5c31af7Sopenharmony_ci	for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(shaderTasks); ++i)
374e5c31af7Sopenharmony_ci	{
375e5c31af7Sopenharmony_ci		DE_ASSERT(shaderTasks[i] >= 0 && shaderTasks[i] < SHADER_TASK_LAST);
376e5c31af7Sopenharmony_ci	}
377e5c31af7Sopenharmony_ci
378e5c31af7Sopenharmony_ci	std::vector<ShaderElement> elements;
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_ci	DE_ASSERT(shaderTasks[SHADER_TASK_INDEX_VERTEX]		!= SHADER_TASK_NONE);
381e5c31af7Sopenharmony_ci	DE_ASSERT(shaderTasks[SHADER_TASK_INDEX_FRAGMENT]	!= SHADER_TASK_NONE);
382e5c31af7Sopenharmony_ci	elements.push_back(ShaderElement("vert", "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
383e5c31af7Sopenharmony_ci	elements.push_back(ShaderElement("frag", "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
384e5c31af7Sopenharmony_ci
385e5c31af7Sopenharmony_ci	if (shaderTasks[SHADER_TASK_INDEX_GEOMETRY] != SHADER_TASK_NONE)
386e5c31af7Sopenharmony_ci		elements.push_back(ShaderElement("geom", "main", vk::VK_SHADER_STAGE_GEOMETRY_BIT));
387e5c31af7Sopenharmony_ci
388e5c31af7Sopenharmony_ci	if (shaderTasks[SHADER_TASK_INDEX_TESS_CONTROL] != SHADER_TASK_NONE)
389e5c31af7Sopenharmony_ci		elements.push_back(ShaderElement("tessc", "main", vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
390e5c31af7Sopenharmony_ci
391e5c31af7Sopenharmony_ci	if (shaderTasks[SHADER_TASK_INDEX_TESS_EVAL] != SHADER_TASK_NONE)
392e5c31af7Sopenharmony_ci		elements.push_back(ShaderElement("tesse", "main", vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
393e5c31af7Sopenharmony_ci
394e5c31af7Sopenharmony_ci	return UnusedVariableContext(
395e5c31af7Sopenharmony_ci		createInstanceContext(elements, map<string, string>()),
396e5c31af7Sopenharmony_ci		shaderTasks,
397e5c31af7Sopenharmony_ci		location);
398e5c31af7Sopenharmony_ci}
399e5c31af7Sopenharmony_ci
400e5c31af7Sopenharmony_ciShaderElement::ShaderElement (const string&				moduleName_,
401e5c31af7Sopenharmony_ci							  const string&				entryPoint_,
402e5c31af7Sopenharmony_ci							  VkShaderStageFlagBits		shaderStage_)
403e5c31af7Sopenharmony_ci		: moduleName(moduleName_)
404e5c31af7Sopenharmony_ci		, entryName(entryPoint_)
405e5c31af7Sopenharmony_ci		, stage(shaderStage_)
406e5c31af7Sopenharmony_ci{
407e5c31af7Sopenharmony_ci}
408e5c31af7Sopenharmony_ci
409e5c31af7Sopenharmony_civoid getDefaultColors (RGBA (&colors)[4])
410e5c31af7Sopenharmony_ci{
411e5c31af7Sopenharmony_ci	colors[0] = RGBA::white();
412e5c31af7Sopenharmony_ci	colors[1] = RGBA::red();
413e5c31af7Sopenharmony_ci	colors[2] = RGBA::green();
414e5c31af7Sopenharmony_ci	colors[3] = RGBA::blue();
415e5c31af7Sopenharmony_ci}
416e5c31af7Sopenharmony_ci
417e5c31af7Sopenharmony_civoid getHalfColorsFullAlpha (RGBA (&colors)[4])
418e5c31af7Sopenharmony_ci{
419e5c31af7Sopenharmony_ci	colors[0] = RGBA(127, 127, 127, 255);
420e5c31af7Sopenharmony_ci	colors[1] = RGBA(127, 0,   0,	255);
421e5c31af7Sopenharmony_ci	colors[2] = RGBA(0,	  127, 0,	255);
422e5c31af7Sopenharmony_ci	colors[3] = RGBA(0,	  0,   127, 255);
423e5c31af7Sopenharmony_ci}
424e5c31af7Sopenharmony_ci
425e5c31af7Sopenharmony_civoid getInvertedDefaultColors (RGBA (&colors)[4])
426e5c31af7Sopenharmony_ci{
427e5c31af7Sopenharmony_ci	colors[0] = RGBA(0,		0,		0,		255);
428e5c31af7Sopenharmony_ci	colors[1] = RGBA(0,		255,	255,	255);
429e5c31af7Sopenharmony_ci	colors[2] = RGBA(255,	0,		255,	255);
430e5c31af7Sopenharmony_ci	colors[3] = RGBA(255,	255,	0,		255);
431e5c31af7Sopenharmony_ci}
432e5c31af7Sopenharmony_ci
433e5c31af7Sopenharmony_ci// For the current InstanceContext, constructs the required modules and shader stage create infos.
434e5c31af7Sopenharmony_civoid createPipelineShaderStages (const DeviceInterface&						vk,
435e5c31af7Sopenharmony_ci								 const VkDevice								vkDevice,
436e5c31af7Sopenharmony_ci								 InstanceContext&							instance,
437e5c31af7Sopenharmony_ci								 Context&									context,
438e5c31af7Sopenharmony_ci								 vector<ModuleHandleSp>&					modules,
439e5c31af7Sopenharmony_ci								 vector<VkPipelineShaderStageCreateInfo>&	createInfos)
440e5c31af7Sopenharmony_ci{
441e5c31af7Sopenharmony_ci	for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx)
442e5c31af7Sopenharmony_ci	{
443e5c31af7Sopenharmony_ci		const ModuleHandleSp mod(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, context.getBinaryCollection().get(moduleNdx->first), 0)));
444e5c31af7Sopenharmony_ci		modules.push_back(ModuleHandleSp(mod));
445e5c31af7Sopenharmony_ci		for (vector<EntryToStage>::const_iterator shaderNdx = moduleNdx->second.begin(); shaderNdx != moduleNdx->second.end(); ++shaderNdx)
446e5c31af7Sopenharmony_ci		{
447e5c31af7Sopenharmony_ci			const EntryToStage&						stage			= *shaderNdx;
448e5c31af7Sopenharmony_ci			const VkPipelineShaderStageCreateInfo	shaderParam		=
449e5c31af7Sopenharmony_ci			{
450e5c31af7Sopenharmony_ci				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType			sType;
451e5c31af7Sopenharmony_ci				DE_NULL,												//	const void*				pNext;
452e5c31af7Sopenharmony_ci				(VkPipelineShaderStageCreateFlags)0,
453e5c31af7Sopenharmony_ci				stage.second,											//	VkShaderStageFlagBits	stage;
454e5c31af7Sopenharmony_ci				**modules.back(),										//	VkShaderModule			module;
455e5c31af7Sopenharmony_ci				stage.first.c_str(),									//	const char*				pName;
456e5c31af7Sopenharmony_ci				(const VkSpecializationInfo*)DE_NULL,
457e5c31af7Sopenharmony_ci			};
458e5c31af7Sopenharmony_ci			createInfos.push_back(shaderParam);
459e5c31af7Sopenharmony_ci		}
460e5c31af7Sopenharmony_ci	}
461e5c31af7Sopenharmony_ci}
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ci// Creates vertex-shader assembly by specializing a boilerplate StringTemplate
464e5c31af7Sopenharmony_ci// on fragments, which must (at least) map "testfun" to an OpFunction definition
465e5c31af7Sopenharmony_ci// for %test_code that takes and returns a %v4f32.  Boilerplate IDs are prefixed
466e5c31af7Sopenharmony_ci// with "BP_" to avoid collisions with fragments.
467e5c31af7Sopenharmony_ci//
468e5c31af7Sopenharmony_ci// It corresponds roughly to this GLSL:
469e5c31af7Sopenharmony_ci//;
470e5c31af7Sopenharmony_ci// layout(location = 0) in vec4 position;
471e5c31af7Sopenharmony_ci// layout(location = 1) in vec4 color;
472e5c31af7Sopenharmony_ci// layout(location = 1) out highp vec4 vtxColor;
473e5c31af7Sopenharmony_ci// void main (void) { gl_Position = position; vtxColor = test_func(color); }
474e5c31af7Sopenharmony_cistring makeVertexShaderAssembly (const map<string, string>& fragments)
475e5c31af7Sopenharmony_ci{
476e5c31af7Sopenharmony_ci	static const char vertexShaderBoilerplate[] =
477e5c31af7Sopenharmony_ci		"OpCapability Shader\n"
478e5c31af7Sopenharmony_ci		"${capability:opt}\n"
479e5c31af7Sopenharmony_ci		"${extension:opt}\n"
480e5c31af7Sopenharmony_ci		"OpMemoryModel Logical GLSL450\n"
481e5c31af7Sopenharmony_ci		"OpEntryPoint Vertex %BP_main \"main\" %BP_stream %BP_position %BP_vtx_color %BP_color %BP_gl_VertexIndex %BP_gl_InstanceIndex ${IF_entrypoint:opt} \n"
482e5c31af7Sopenharmony_ci		"${execution_mode:opt}\n"
483e5c31af7Sopenharmony_ci		"${debug:opt}\n"
484e5c31af7Sopenharmony_ci		"${moduleprocessed:opt}\n"
485e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n"
486e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n"
487e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n"
488e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n"
489e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_PerVertex Block\n"
490e5c31af7Sopenharmony_ci		"OpDecorate %BP_position Location 0\n"
491e5c31af7Sopenharmony_ci		"OpDecorate %BP_vtx_color Location 1\n"
492e5c31af7Sopenharmony_ci		"OpDecorate %BP_color Location 1\n"
493e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_VertexIndex BuiltIn VertexIndex\n"
494e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_InstanceIndex BuiltIn InstanceIndex\n"
495e5c31af7Sopenharmony_ci		"${IF_decoration:opt}\n"
496e5c31af7Sopenharmony_ci		"${decoration:opt}\n"
497e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_TYPES
498e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_CONSTANTS
499e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_ARRAYS
500e5c31af7Sopenharmony_ci		"%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
501e5c31af7Sopenharmony_ci		"%BP_op_gl_PerVertex = OpTypePointer Output %BP_gl_PerVertex\n"
502e5c31af7Sopenharmony_ci		"%BP_stream = OpVariable %BP_op_gl_PerVertex Output\n"
503e5c31af7Sopenharmony_ci		"%BP_position = OpVariable %ip_v4f32 Input\n"
504e5c31af7Sopenharmony_ci		"%BP_vtx_color = OpVariable %op_v4f32 Output\n"
505e5c31af7Sopenharmony_ci		"%BP_color = OpVariable %ip_v4f32 Input\n"
506e5c31af7Sopenharmony_ci		"%BP_gl_VertexIndex = OpVariable %ip_i32 Input\n"
507e5c31af7Sopenharmony_ci		"%BP_gl_InstanceIndex = OpVariable %ip_i32 Input\n"
508e5c31af7Sopenharmony_ci		"${pre_main:opt}\n"
509e5c31af7Sopenharmony_ci		"${IF_variable:opt}\n"
510e5c31af7Sopenharmony_ci		"%BP_main = OpFunction %void None %voidf\n"
511e5c31af7Sopenharmony_ci		"%BP_label = OpLabel\n"
512e5c31af7Sopenharmony_ci		"${IF_carryforward:opt}\n"
513e5c31af7Sopenharmony_ci		"${post_interface_op_vert:opt}\n"
514e5c31af7Sopenharmony_ci		"%BP_pos = OpLoad %v4f32 %BP_position\n"
515e5c31af7Sopenharmony_ci		"%BP_gl_pos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
516e5c31af7Sopenharmony_ci		"OpStore %BP_gl_pos %BP_pos\n"
517e5c31af7Sopenharmony_ci		"%BP_col = OpLoad %v4f32 %BP_color\n"
518e5c31af7Sopenharmony_ci		"%BP_col_transformed = OpFunctionCall %v4f32 %test_code %BP_col\n"
519e5c31af7Sopenharmony_ci		"OpStore %BP_vtx_color %BP_col_transformed\n"
520e5c31af7Sopenharmony_ci		"OpReturn\n"
521e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
522e5c31af7Sopenharmony_ci		"${interface_op_func:opt}\n"
523e5c31af7Sopenharmony_ci
524e5c31af7Sopenharmony_ci		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
525e5c31af7Sopenharmony_ci		"%getId_label = OpLabel\n"
526e5c31af7Sopenharmony_ci		"%vert_id = OpLoad %i32 %BP_gl_VertexIndex\n"
527e5c31af7Sopenharmony_ci		"%is_id_0 = OpIEqual %bool %vert_id %c_i32_0\n"
528e5c31af7Sopenharmony_ci		"OpReturnValue %is_id_0\n"
529e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
530e5c31af7Sopenharmony_ci
531e5c31af7Sopenharmony_ci		"${testfun}\n";
532e5c31af7Sopenharmony_ci	return tcu::StringTemplate(vertexShaderBoilerplate).specialize(fragments);
533e5c31af7Sopenharmony_ci}
534e5c31af7Sopenharmony_ci
535e5c31af7Sopenharmony_ci// Creates tess-control-shader assembly by specializing a boilerplate
536e5c31af7Sopenharmony_ci// StringTemplate on fragments, which must (at least) map "testfun" to an
537e5c31af7Sopenharmony_ci// OpFunction definition for %test_code that takes and returns a %v4f32.
538e5c31af7Sopenharmony_ci// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments.
539e5c31af7Sopenharmony_ci//
540e5c31af7Sopenharmony_ci// It roughly corresponds to the following GLSL.
541e5c31af7Sopenharmony_ci//
542e5c31af7Sopenharmony_ci// #version 450
543e5c31af7Sopenharmony_ci// layout(vertices = 3) out;
544e5c31af7Sopenharmony_ci// layout(location = 1) in vec4 in_color[];
545e5c31af7Sopenharmony_ci// layout(location = 1) out vec4 out_color[];
546e5c31af7Sopenharmony_ci//
547e5c31af7Sopenharmony_ci// void main() {
548e5c31af7Sopenharmony_ci//   out_color[gl_InvocationID] = testfun(in_color[gl_InvocationID]);
549e5c31af7Sopenharmony_ci//   gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
550e5c31af7Sopenharmony_ci//   if (gl_InvocationID == 0) {
551e5c31af7Sopenharmony_ci//     gl_TessLevelOuter[0] = 1.0;
552e5c31af7Sopenharmony_ci//     gl_TessLevelOuter[1] = 1.0;
553e5c31af7Sopenharmony_ci//     gl_TessLevelOuter[2] = 1.0;
554e5c31af7Sopenharmony_ci//     gl_TessLevelInner[0] = 1.0;
555e5c31af7Sopenharmony_ci//   }
556e5c31af7Sopenharmony_ci// }
557e5c31af7Sopenharmony_cistring makeTessControlShaderAssembly (const map<string, string>& fragments)
558e5c31af7Sopenharmony_ci{
559e5c31af7Sopenharmony_ci	static const char tessControlShaderBoilerplate[] =
560e5c31af7Sopenharmony_ci		"OpCapability Tessellation\n"
561e5c31af7Sopenharmony_ci		"${capability:opt}\n"
562e5c31af7Sopenharmony_ci		"${extension:opt}\n"
563e5c31af7Sopenharmony_ci		"OpMemoryModel Logical GLSL450\n"
564e5c31af7Sopenharmony_ci		"OpEntryPoint TessellationControl %BP_main \"main\" %BP_out_color %BP_gl_InvocationID %BP_gl_PrimitiveID %BP_in_color %BP_gl_out %BP_gl_in %BP_gl_TessLevelOuter %BP_gl_TessLevelInner ${IF_entrypoint:opt} \n"
565e5c31af7Sopenharmony_ci		"OpExecutionMode %BP_main OutputVertices 3\n"
566e5c31af7Sopenharmony_ci		"${execution_mode:opt}\n"
567e5c31af7Sopenharmony_ci		"${debug:opt}\n"
568e5c31af7Sopenharmony_ci		"${moduleprocessed:opt}\n"
569e5c31af7Sopenharmony_ci		"OpDecorate %BP_out_color Location 1\n"
570e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n"
571e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n"
572e5c31af7Sopenharmony_ci		"OpDecorate %BP_in_color Location 1\n"
573e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n"
574e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n"
575e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n"
576e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n"
577e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_PerVertex Block\n"
578e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PVOut 0 BuiltIn Position\n"
579e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PVOut 1 BuiltIn PointSize\n"
580e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PVOut 2 BuiltIn ClipDistance\n"
581e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PVOut 3 BuiltIn CullDistance\n"
582e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_PVOut Block\n"
583e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_TessLevelOuter Patch\n"
584e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_TessLevelOuter BuiltIn TessLevelOuter\n"
585e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_TessLevelInner Patch\n"
586e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_TessLevelInner BuiltIn TessLevelInner\n"
587e5c31af7Sopenharmony_ci		"${IF_decoration:opt}\n"
588e5c31af7Sopenharmony_ci		"${decoration:opt}\n"
589e5c31af7Sopenharmony_ci		"${decoration_tessc:opt}\n"
590e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_TYPES
591e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_CONSTANTS
592e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_ARRAYS
593e5c31af7Sopenharmony_ci		"%BP_out_color = OpVariable %op_a3v4f32 Output\n"
594e5c31af7Sopenharmony_ci		"%BP_gl_InvocationID = OpVariable %ip_i32 Input\n"
595e5c31af7Sopenharmony_ci		"%BP_gl_PrimitiveID = OpVariable %ip_i32 Input\n"
596e5c31af7Sopenharmony_ci		"%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
597e5c31af7Sopenharmony_ci		"%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
598e5c31af7Sopenharmony_ci		"%BP_a3_gl_PerVertex = OpTypeArray %BP_gl_PerVertex %c_u32_3\n"
599e5c31af7Sopenharmony_ci		"%BP_op_a3_gl_PerVertex = OpTypePointer Output %BP_a3_gl_PerVertex\n"
600e5c31af7Sopenharmony_ci		"%BP_gl_out = OpVariable %BP_op_a3_gl_PerVertex Output\n"
601e5c31af7Sopenharmony_ci		"%BP_gl_PVOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
602e5c31af7Sopenharmony_ci		"%BP_a32_gl_PVOut = OpTypeArray %BP_gl_PVOut %c_u32_32\n"
603e5c31af7Sopenharmony_ci		"%BP_ip_a32_gl_PVOut = OpTypePointer Input %BP_a32_gl_PVOut\n"
604e5c31af7Sopenharmony_ci		"%BP_gl_in = OpVariable %BP_ip_a32_gl_PVOut Input\n"
605e5c31af7Sopenharmony_ci		"%BP_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
606e5c31af7Sopenharmony_ci		"%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
607e5c31af7Sopenharmony_ci		"${pre_main:opt}\n"
608e5c31af7Sopenharmony_ci		"${IF_variable:opt}\n"
609e5c31af7Sopenharmony_ci
610e5c31af7Sopenharmony_ci		"%BP_main = OpFunction %void None %voidf\n"
611e5c31af7Sopenharmony_ci		"%BP_label = OpLabel\n"
612e5c31af7Sopenharmony_ci		"%BP_gl_Invoc = OpLoad %i32 %BP_gl_InvocationID\n"
613e5c31af7Sopenharmony_ci		"${IF_carryforward:opt}\n"
614e5c31af7Sopenharmony_ci		"${post_interface_op_tessc:opt}\n"
615e5c31af7Sopenharmony_ci		"%BP_in_col_loc = OpAccessChain %ip_v4f32 %BP_in_color %BP_gl_Invoc\n"
616e5c31af7Sopenharmony_ci		"%BP_out_col_loc = OpAccessChain %op_v4f32 %BP_out_color %BP_gl_Invoc\n"
617e5c31af7Sopenharmony_ci		"%BP_in_col_val = OpLoad %v4f32 %BP_in_col_loc\n"
618e5c31af7Sopenharmony_ci		"%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_col_val\n"
619e5c31af7Sopenharmony_ci		"OpStore %BP_out_col_loc %BP_clr_transformed\n"
620e5c31af7Sopenharmony_ci
621e5c31af7Sopenharmony_ci		"%BP_in_pos_loc = OpAccessChain %ip_v4f32 %BP_gl_in %BP_gl_Invoc %c_i32_0\n"
622e5c31af7Sopenharmony_ci		"%BP_out_pos_loc = OpAccessChain %op_v4f32 %BP_gl_out %BP_gl_Invoc %c_i32_0\n"
623e5c31af7Sopenharmony_ci		"%BP_in_pos_val = OpLoad %v4f32 %BP_in_pos_loc\n"
624e5c31af7Sopenharmony_ci		"OpStore %BP_out_pos_loc %BP_in_pos_val\n"
625e5c31af7Sopenharmony_ci
626e5c31af7Sopenharmony_ci		"%BP_cmp = OpIEqual %bool %BP_gl_Invoc %c_i32_0\n"
627e5c31af7Sopenharmony_ci		"OpSelectionMerge %BP_merge_label None\n"
628e5c31af7Sopenharmony_ci		"OpBranchConditional %BP_cmp %BP_if_label %BP_merge_label\n"
629e5c31af7Sopenharmony_ci		"%BP_if_label = OpLabel\n"
630e5c31af7Sopenharmony_ci		"%BP_gl_TessLevelOuterPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_0\n"
631e5c31af7Sopenharmony_ci		"%BP_gl_TessLevelOuterPos_1 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_1\n"
632e5c31af7Sopenharmony_ci		"%BP_gl_TessLevelOuterPos_2 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_2\n"
633e5c31af7Sopenharmony_ci		"%BP_gl_TessLevelInnerPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelInner %c_i32_0\n"
634e5c31af7Sopenharmony_ci		"OpStore %BP_gl_TessLevelOuterPos_0 %c_f32_1\n"
635e5c31af7Sopenharmony_ci		"OpStore %BP_gl_TessLevelOuterPos_1 %c_f32_1\n"
636e5c31af7Sopenharmony_ci		"OpStore %BP_gl_TessLevelOuterPos_2 %c_f32_1\n"
637e5c31af7Sopenharmony_ci		"OpStore %BP_gl_TessLevelInnerPos_0 %c_f32_1\n"
638e5c31af7Sopenharmony_ci		"OpBranch %BP_merge_label\n"
639e5c31af7Sopenharmony_ci		"%BP_merge_label = OpLabel\n"
640e5c31af7Sopenharmony_ci		"OpReturn\n"
641e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
642e5c31af7Sopenharmony_ci		"${interface_op_func:opt}\n"
643e5c31af7Sopenharmony_ci
644e5c31af7Sopenharmony_ci		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
645e5c31af7Sopenharmony_ci		"%getId_label = OpLabel\n"
646e5c31af7Sopenharmony_ci		"%invocation_id = OpLoad %i32 %BP_gl_InvocationID\n"
647e5c31af7Sopenharmony_ci		"%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n"
648e5c31af7Sopenharmony_ci		"%is_invocation_0 = OpIEqual %bool %invocation_id %c_i32_0\n"
649e5c31af7Sopenharmony_ci		"%is_primitive_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
650e5c31af7Sopenharmony_ci		"%is_id_0 = OpLogicalAnd %bool %is_invocation_0 %is_primitive_0\n"
651e5c31af7Sopenharmony_ci		"OpReturnValue %is_id_0\n"
652e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
653e5c31af7Sopenharmony_ci
654e5c31af7Sopenharmony_ci		"${testfun}\n";
655e5c31af7Sopenharmony_ci	return tcu::StringTemplate(tessControlShaderBoilerplate).specialize(fragments);
656e5c31af7Sopenharmony_ci}
657e5c31af7Sopenharmony_ci
658e5c31af7Sopenharmony_ci// Creates tess-evaluation-shader assembly by specializing a boilerplate
659e5c31af7Sopenharmony_ci// StringTemplate on fragments, which must (at least) map "testfun" to an
660e5c31af7Sopenharmony_ci// OpFunction definition for %test_code that takes and returns a %v4f32.
661e5c31af7Sopenharmony_ci// Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments.
662e5c31af7Sopenharmony_ci//
663e5c31af7Sopenharmony_ci// It roughly corresponds to the following glsl.
664e5c31af7Sopenharmony_ci//
665e5c31af7Sopenharmony_ci// #version 450
666e5c31af7Sopenharmony_ci//
667e5c31af7Sopenharmony_ci// layout(triangles, equal_spacing, ccw) in;
668e5c31af7Sopenharmony_ci// layout(location = 1) in vec4 in_color[];
669e5c31af7Sopenharmony_ci// layout(location = 1) out vec4 out_color;
670e5c31af7Sopenharmony_ci//
671e5c31af7Sopenharmony_ci// #define interpolate(val)
672e5c31af7Sopenharmony_ci//   vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] +
673e5c31af7Sopenharmony_ci//          vec4(gl_TessCoord.z) * val[2]
674e5c31af7Sopenharmony_ci//
675e5c31af7Sopenharmony_ci// void main() {
676e5c31af7Sopenharmony_ci//   gl_Position = vec4(gl_TessCoord.x) * gl_in[0].gl_Position +
677e5c31af7Sopenharmony_ci//                  vec4(gl_TessCoord.y) * gl_in[1].gl_Position +
678e5c31af7Sopenharmony_ci//                  vec4(gl_TessCoord.z) * gl_in[2].gl_Position;
679e5c31af7Sopenharmony_ci//   out_color = testfun(interpolate(in_color));
680e5c31af7Sopenharmony_ci// }
681e5c31af7Sopenharmony_cistring makeTessEvalShaderAssembly (const map<string, string>& fragments)
682e5c31af7Sopenharmony_ci{
683e5c31af7Sopenharmony_ci	static const char tessEvalBoilerplate[] =
684e5c31af7Sopenharmony_ci		"OpCapability Tessellation\n"
685e5c31af7Sopenharmony_ci		"${capability:opt}\n"
686e5c31af7Sopenharmony_ci		"${extension:opt}\n"
687e5c31af7Sopenharmony_ci		"OpMemoryModel Logical GLSL450\n"
688e5c31af7Sopenharmony_ci		"OpEntryPoint TessellationEvaluation %BP_main \"main\" %BP_stream %BP_gl_TessCoord %BP_gl_PrimitiveID %BP_gl_in %BP_out_color %BP_in_color ${IF_entrypoint:opt} \n"
689e5c31af7Sopenharmony_ci		"OpExecutionMode %BP_main Triangles\n"
690e5c31af7Sopenharmony_ci		"OpExecutionMode %BP_main SpacingEqual\n"
691e5c31af7Sopenharmony_ci		"OpExecutionMode %BP_main VertexOrderCcw\n"
692e5c31af7Sopenharmony_ci		"${execution_mode:opt}\n"
693e5c31af7Sopenharmony_ci		"${debug:opt}\n"
694e5c31af7Sopenharmony_ci		"${moduleprocessed:opt}\n"
695e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertexOut 0 BuiltIn Position\n"
696e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertexOut 1 BuiltIn PointSize\n"
697e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertexOut 2 BuiltIn ClipDistance\n"
698e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertexOut 3 BuiltIn CullDistance\n"
699e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_PerVertexOut Block\n"
700e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n"
701e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_TessCoord BuiltIn TessCoord\n"
702e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertexIn 0 BuiltIn Position\n"
703e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertexIn 1 BuiltIn PointSize\n"
704e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertexIn 2 BuiltIn ClipDistance\n"
705e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_gl_PerVertexIn 3 BuiltIn CullDistance\n"
706e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_PerVertexIn Block\n"
707e5c31af7Sopenharmony_ci		"OpDecorate %BP_out_color Location 1\n"
708e5c31af7Sopenharmony_ci		"OpDecorate %BP_in_color Location 1\n"
709e5c31af7Sopenharmony_ci		"${IF_decoration:opt}\n"
710e5c31af7Sopenharmony_ci		"${decoration:opt}\n"
711e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_TYPES
712e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_CONSTANTS
713e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_ARRAYS
714e5c31af7Sopenharmony_ci		"%BP_gl_PerVertexOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
715e5c31af7Sopenharmony_ci		"%BP_op_gl_PerVertexOut = OpTypePointer Output %BP_gl_PerVertexOut\n"
716e5c31af7Sopenharmony_ci		"%BP_stream = OpVariable %BP_op_gl_PerVertexOut Output\n"
717e5c31af7Sopenharmony_ci		"%BP_gl_TessCoord = OpVariable %ip_v3f32 Input\n"
718e5c31af7Sopenharmony_ci		"%BP_gl_PrimitiveID = OpVariable %ip_i32 Input\n"
719e5c31af7Sopenharmony_ci		"%BP_gl_PerVertexIn = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
720e5c31af7Sopenharmony_ci		"%BP_a32_gl_PerVertexIn = OpTypeArray %BP_gl_PerVertexIn %c_u32_32\n"
721e5c31af7Sopenharmony_ci		"%BP_ip_a32_gl_PerVertexIn = OpTypePointer Input %BP_a32_gl_PerVertexIn\n"
722e5c31af7Sopenharmony_ci		"%BP_gl_in = OpVariable %BP_ip_a32_gl_PerVertexIn Input\n"
723e5c31af7Sopenharmony_ci		"%BP_out_color = OpVariable %op_v4f32 Output\n"
724e5c31af7Sopenharmony_ci		"%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
725e5c31af7Sopenharmony_ci		"${pre_main:opt}\n"
726e5c31af7Sopenharmony_ci		"${IF_variable:opt}\n"
727e5c31af7Sopenharmony_ci		"%BP_main = OpFunction %void None %voidf\n"
728e5c31af7Sopenharmony_ci		"%BP_label = OpLabel\n"
729e5c31af7Sopenharmony_ci		"${IF_carryforward:opt}\n"
730e5c31af7Sopenharmony_ci		"${post_interface_op_tesse:opt}\n"
731e5c31af7Sopenharmony_ci		"%BP_gl_TC_0 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n"
732e5c31af7Sopenharmony_ci		"%BP_gl_TC_1 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n"
733e5c31af7Sopenharmony_ci		"%BP_gl_TC_2 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n"
734e5c31af7Sopenharmony_ci		"%BP_gl_in_gl_Pos_0 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n"
735e5c31af7Sopenharmony_ci		"%BP_gl_in_gl_Pos_1 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n"
736e5c31af7Sopenharmony_ci		"%BP_gl_in_gl_Pos_2 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n"
737e5c31af7Sopenharmony_ci
738e5c31af7Sopenharmony_ci		"%BP_gl_OPos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
739e5c31af7Sopenharmony_ci		"%BP_in_color_0 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
740e5c31af7Sopenharmony_ci		"%BP_in_color_1 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
741e5c31af7Sopenharmony_ci		"%BP_in_color_2 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
742e5c31af7Sopenharmony_ci
743e5c31af7Sopenharmony_ci		"%BP_TC_W_0 = OpLoad %f32 %BP_gl_TC_0\n"
744e5c31af7Sopenharmony_ci		"%BP_TC_W_1 = OpLoad %f32 %BP_gl_TC_1\n"
745e5c31af7Sopenharmony_ci		"%BP_TC_W_2 = OpLoad %f32 %BP_gl_TC_2\n"
746e5c31af7Sopenharmony_ci		"%BP_v4f32_TC_0 = OpCompositeConstruct %v4f32 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0\n"
747e5c31af7Sopenharmony_ci		"%BP_v4f32_TC_1 = OpCompositeConstruct %v4f32 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1\n"
748e5c31af7Sopenharmony_ci		"%BP_v4f32_TC_2 = OpCompositeConstruct %v4f32 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2\n"
749e5c31af7Sopenharmony_ci
750e5c31af7Sopenharmony_ci		"%BP_gl_IP_0 = OpLoad %v4f32 %BP_gl_in_gl_Pos_0\n"
751e5c31af7Sopenharmony_ci		"%BP_gl_IP_1 = OpLoad %v4f32 %BP_gl_in_gl_Pos_1\n"
752e5c31af7Sopenharmony_ci		"%BP_gl_IP_2 = OpLoad %v4f32 %BP_gl_in_gl_Pos_2\n"
753e5c31af7Sopenharmony_ci
754e5c31af7Sopenharmony_ci		"%BP_IP_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_gl_IP_0\n"
755e5c31af7Sopenharmony_ci		"%BP_IP_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_gl_IP_1\n"
756e5c31af7Sopenharmony_ci		"%BP_IP_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_gl_IP_2\n"
757e5c31af7Sopenharmony_ci
758e5c31af7Sopenharmony_ci		"%BP_pos_sum_0 = OpFAdd %v4f32 %BP_IP_W_0 %BP_IP_W_1\n"
759e5c31af7Sopenharmony_ci		"%BP_pos_sum_1 = OpFAdd %v4f32 %BP_pos_sum_0 %BP_IP_W_2\n"
760e5c31af7Sopenharmony_ci
761e5c31af7Sopenharmony_ci		"OpStore %BP_gl_OPos %BP_pos_sum_1\n"
762e5c31af7Sopenharmony_ci
763e5c31af7Sopenharmony_ci		"%BP_IC_0 = OpLoad %v4f32 %BP_in_color_0\n"
764e5c31af7Sopenharmony_ci		"%BP_IC_1 = OpLoad %v4f32 %BP_in_color_1\n"
765e5c31af7Sopenharmony_ci		"%BP_IC_2 = OpLoad %v4f32 %BP_in_color_2\n"
766e5c31af7Sopenharmony_ci
767e5c31af7Sopenharmony_ci		"%BP_IC_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_IC_0\n"
768e5c31af7Sopenharmony_ci		"%BP_IC_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_IC_1\n"
769e5c31af7Sopenharmony_ci		"%BP_IC_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_IC_2\n"
770e5c31af7Sopenharmony_ci
771e5c31af7Sopenharmony_ci		"%BP_col_sum_0 = OpFAdd %v4f32 %BP_IC_W_0 %BP_IC_W_1\n"
772e5c31af7Sopenharmony_ci		"%BP_col_sum_1 = OpFAdd %v4f32 %BP_col_sum_0 %BP_IC_W_2\n"
773e5c31af7Sopenharmony_ci
774e5c31af7Sopenharmony_ci		"%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_col_sum_1\n"
775e5c31af7Sopenharmony_ci
776e5c31af7Sopenharmony_ci		"OpStore %BP_out_color %BP_clr_transformed\n"
777e5c31af7Sopenharmony_ci		"OpReturn\n"
778e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
779e5c31af7Sopenharmony_ci		"${interface_op_func:opt}\n"
780e5c31af7Sopenharmony_ci
781e5c31af7Sopenharmony_ci		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
782e5c31af7Sopenharmony_ci		"%getId_label = OpLabel\n"
783e5c31af7Sopenharmony_ci		"%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n"
784e5c31af7Sopenharmony_ci		"%is_primitive_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
785e5c31af7Sopenharmony_ci		"%TC_0_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n"
786e5c31af7Sopenharmony_ci		"%TC_1_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n"
787e5c31af7Sopenharmony_ci		"%TC_2_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n"
788e5c31af7Sopenharmony_ci		"%TC_W_0 = OpLoad %f32 %TC_0_loc\n"
789e5c31af7Sopenharmony_ci		"%TC_W_1 = OpLoad %f32 %TC_1_loc\n"
790e5c31af7Sopenharmony_ci		"%TC_W_2 = OpLoad %f32 %TC_2_loc\n"
791e5c31af7Sopenharmony_ci		"%is_W_0_1 = OpFOrdEqual %bool %TC_W_0 %c_f32_1\n"
792e5c31af7Sopenharmony_ci		"%is_W_1_0 = OpFOrdEqual %bool %TC_W_1 %c_f32_0\n"
793e5c31af7Sopenharmony_ci		"%is_W_2_0 = OpFOrdEqual %bool %TC_W_2 %c_f32_0\n"
794e5c31af7Sopenharmony_ci		"%is_tessCoord_1_0 = OpLogicalAnd %bool %is_W_0_1 %is_W_1_0\n"
795e5c31af7Sopenharmony_ci		"%is_tessCoord_1_0_0 = OpLogicalAnd %bool %is_tessCoord_1_0 %is_W_2_0\n"
796e5c31af7Sopenharmony_ci		"%is_unique_id_0 = OpLogicalAnd %bool %is_tessCoord_1_0_0 %is_primitive_0\n"
797e5c31af7Sopenharmony_ci		"OpReturnValue %is_unique_id_0\n"
798e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
799e5c31af7Sopenharmony_ci
800e5c31af7Sopenharmony_ci		"${testfun}\n";
801e5c31af7Sopenharmony_ci	return tcu::StringTemplate(tessEvalBoilerplate).specialize(fragments);
802e5c31af7Sopenharmony_ci}
803e5c31af7Sopenharmony_ci
804e5c31af7Sopenharmony_ci// Creates geometry-shader assembly by specializing a boilerplate StringTemplate
805e5c31af7Sopenharmony_ci// on fragments, which must (at least) map "testfun" to an OpFunction definition
806e5c31af7Sopenharmony_ci// for %test_code that takes and returns a %v4f32.  Boilerplate IDs are prefixed
807e5c31af7Sopenharmony_ci// with "BP_" to avoid collisions with fragments.
808e5c31af7Sopenharmony_ci//
809e5c31af7Sopenharmony_ci// Derived from this GLSL:
810e5c31af7Sopenharmony_ci//
811e5c31af7Sopenharmony_ci// #version 450
812e5c31af7Sopenharmony_ci// layout(triangles) in;
813e5c31af7Sopenharmony_ci// layout(triangle_strip, max_vertices = 3) out;
814e5c31af7Sopenharmony_ci//
815e5c31af7Sopenharmony_ci// layout(location = 1) in vec4 in_color[];
816e5c31af7Sopenharmony_ci// layout(location = 1) out vec4 out_color;
817e5c31af7Sopenharmony_ci//
818e5c31af7Sopenharmony_ci// void main() {
819e5c31af7Sopenharmony_ci//   gl_Position = gl_in[0].gl_Position;
820e5c31af7Sopenharmony_ci//   out_color = test_fun(in_color[0]);
821e5c31af7Sopenharmony_ci//   EmitVertex();
822e5c31af7Sopenharmony_ci//   gl_Position = gl_in[1].gl_Position;
823e5c31af7Sopenharmony_ci//   out_color = test_fun(in_color[1]);
824e5c31af7Sopenharmony_ci//   EmitVertex();
825e5c31af7Sopenharmony_ci//   gl_Position = gl_in[2].gl_Position;
826e5c31af7Sopenharmony_ci//   out_color = test_fun(in_color[2]);
827e5c31af7Sopenharmony_ci//   EmitVertex();
828e5c31af7Sopenharmony_ci//   EndPrimitive();
829e5c31af7Sopenharmony_ci// }
830e5c31af7Sopenharmony_cistring makeGeometryShaderAssembly (const map<string, string>& fragments)
831e5c31af7Sopenharmony_ci{
832e5c31af7Sopenharmony_ci	static const char geometryShaderBoilerplate[] =
833e5c31af7Sopenharmony_ci		"OpCapability Geometry\n"
834e5c31af7Sopenharmony_ci		"${capability:opt}\n"
835e5c31af7Sopenharmony_ci		"${extension:opt}\n"
836e5c31af7Sopenharmony_ci		"OpMemoryModel Logical GLSL450\n"
837e5c31af7Sopenharmony_ci		"OpEntryPoint Geometry %BP_main \"main\" %BP_out_gl_position %BP_gl_PrimitiveID %BP_gl_in %BP_out_color %BP_in_color ${IF_entrypoint:opt} ${GL_entrypoint:opt} \n"
838e5c31af7Sopenharmony_ci		"OpExecutionMode %BP_main Triangles\n"
839e5c31af7Sopenharmony_ci		"OpExecutionMode %BP_main Invocations 1\n"
840e5c31af7Sopenharmony_ci		"OpExecutionMode %BP_main OutputTriangleStrip\n"
841e5c31af7Sopenharmony_ci		"OpExecutionMode %BP_main OutputVertices 3\n"
842e5c31af7Sopenharmony_ci		"${execution_mode:opt}\n"
843e5c31af7Sopenharmony_ci		"${debug:opt}\n"
844e5c31af7Sopenharmony_ci		"${moduleprocessed:opt}\n"
845e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n"
846e5c31af7Sopenharmony_ci		"OpDecorate %BP_out_gl_position BuiltIn Position\n"
847e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n"
848e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_per_vertex_in 1 BuiltIn PointSize\n"
849e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_per_vertex_in 2 BuiltIn ClipDistance\n"
850e5c31af7Sopenharmony_ci		"OpMemberDecorate %BP_per_vertex_in 3 BuiltIn CullDistance\n"
851e5c31af7Sopenharmony_ci		"OpDecorate %BP_per_vertex_in Block\n"
852e5c31af7Sopenharmony_ci		"OpDecorate %BP_out_color Location 1\n"
853e5c31af7Sopenharmony_ci		"OpDecorate %BP_in_color Location 1\n"
854e5c31af7Sopenharmony_ci		"${IF_decoration:opt}\n"
855e5c31af7Sopenharmony_ci		"${decoration:opt}\n"
856e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_TYPES
857e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_CONSTANTS
858e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_ARRAYS
859e5c31af7Sopenharmony_ci		"%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
860e5c31af7Sopenharmony_ci		"%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n"
861e5c31af7Sopenharmony_ci		"%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n"
862e5c31af7Sopenharmony_ci		"%BP_pp_i32 = OpTypePointer Private %i32\n"
863e5c31af7Sopenharmony_ci		"%BP_pp_v4i32 = OpTypePointer Private %v4i32\n"
864e5c31af7Sopenharmony_ci
865e5c31af7Sopenharmony_ci		"%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n"
866e5c31af7Sopenharmony_ci		"%BP_out_color = OpVariable %op_v4f32 Output\n"
867e5c31af7Sopenharmony_ci		"%BP_in_color = OpVariable %ip_a3v4f32 Input\n"
868e5c31af7Sopenharmony_ci		"%BP_gl_PrimitiveID = OpVariable %ip_i32 Input\n"
869e5c31af7Sopenharmony_ci		"%BP_out_gl_position = OpVariable %op_v4f32 Output\n"
870e5c31af7Sopenharmony_ci		"%BP_vertexIdInCurrentPatch = OpVariable %BP_pp_v4i32 Private\n"
871e5c31af7Sopenharmony_ci		"${pre_main:opt}\n"
872e5c31af7Sopenharmony_ci		"${IF_variable:opt}\n"
873e5c31af7Sopenharmony_ci
874e5c31af7Sopenharmony_ci		"%BP_main = OpFunction %void None %voidf\n"
875e5c31af7Sopenharmony_ci		"%BP_label = OpLabel\n"
876e5c31af7Sopenharmony_ci
877e5c31af7Sopenharmony_ci		"${IF_carryforward:opt}\n"
878e5c31af7Sopenharmony_ci		"${post_interface_op_geom:opt}\n"
879e5c31af7Sopenharmony_ci
880e5c31af7Sopenharmony_ci		"%BP_primitiveId = OpLoad %i32 %BP_gl_PrimitiveID\n"
881e5c31af7Sopenharmony_ci		"%BP_addr_vertexIdInCurrentPatch = OpAccessChain %BP_pp_i32 %BP_vertexIdInCurrentPatch %BP_primitiveId\n"
882e5c31af7Sopenharmony_ci
883e5c31af7Sopenharmony_ci		"%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n"
884e5c31af7Sopenharmony_ci		"%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n"
885e5c31af7Sopenharmony_ci		"%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n"
886e5c31af7Sopenharmony_ci
887e5c31af7Sopenharmony_ci		"%BP_in_position_0 = OpLoad %v4f32 %BP_gl_in_0_gl_position\n"
888e5c31af7Sopenharmony_ci		"%BP_in_position_1 = OpLoad %v4f32 %BP_gl_in_1_gl_position\n"
889e5c31af7Sopenharmony_ci		"%BP_in_position_2 = OpLoad %v4f32 %BP_gl_in_2_gl_position \n"
890e5c31af7Sopenharmony_ci
891e5c31af7Sopenharmony_ci		"%BP_in_color_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
892e5c31af7Sopenharmony_ci		"%BP_in_color_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
893e5c31af7Sopenharmony_ci		"%BP_in_color_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
894e5c31af7Sopenharmony_ci
895e5c31af7Sopenharmony_ci		"%BP_in_color_0 = OpLoad %v4f32 %BP_in_color_0_ptr\n"
896e5c31af7Sopenharmony_ci		"%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n"
897e5c31af7Sopenharmony_ci		"%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n"
898e5c31af7Sopenharmony_ci
899e5c31af7Sopenharmony_ci		"OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_0\n"
900e5c31af7Sopenharmony_ci		"%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n"
901e5c31af7Sopenharmony_ci		"OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_1\n"
902e5c31af7Sopenharmony_ci		"%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n"
903e5c31af7Sopenharmony_ci		"OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_2\n"
904e5c31af7Sopenharmony_ci		"%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n"
905e5c31af7Sopenharmony_ci
906e5c31af7Sopenharmony_ci
907e5c31af7Sopenharmony_ci		"OpStore %BP_out_gl_position %BP_in_position_0\n"
908e5c31af7Sopenharmony_ci		"OpStore %BP_out_color %BP_transformed_in_color_0\n"
909e5c31af7Sopenharmony_ci		"OpEmitVertex\n"
910e5c31af7Sopenharmony_ci
911e5c31af7Sopenharmony_ci		"OpStore %BP_out_gl_position %BP_in_position_1\n"
912e5c31af7Sopenharmony_ci		"OpStore %BP_out_color %BP_transformed_in_color_1\n"
913e5c31af7Sopenharmony_ci		"OpEmitVertex\n"
914e5c31af7Sopenharmony_ci
915e5c31af7Sopenharmony_ci		"OpStore %BP_out_gl_position %BP_in_position_2\n"
916e5c31af7Sopenharmony_ci		"OpStore %BP_out_color %BP_transformed_in_color_2\n"
917e5c31af7Sopenharmony_ci		"OpEmitVertex\n"
918e5c31af7Sopenharmony_ci
919e5c31af7Sopenharmony_ci		"OpEndPrimitive\n"
920e5c31af7Sopenharmony_ci		"OpReturn\n"
921e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
922e5c31af7Sopenharmony_ci		"${interface_op_func:opt}\n"
923e5c31af7Sopenharmony_ci
924e5c31af7Sopenharmony_ci		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
925e5c31af7Sopenharmony_ci		"%getId_label = OpLabel\n"
926e5c31af7Sopenharmony_ci		"%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n"
927e5c31af7Sopenharmony_ci		"%addr_vertexIdInCurrentPatch = OpAccessChain %BP_pp_i32 %BP_vertexIdInCurrentPatch %primitive_id\n"
928e5c31af7Sopenharmony_ci		"%vertexIdInCurrentPatch = OpLoad %i32 %addr_vertexIdInCurrentPatch\n"
929e5c31af7Sopenharmony_ci		"%is_primitive_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
930e5c31af7Sopenharmony_ci		"%is_vertex_0 = OpIEqual %bool %vertexIdInCurrentPatch %c_i32_0\n"
931e5c31af7Sopenharmony_ci		"%is_unique_id_0 = OpLogicalAnd %bool %is_primitive_0 %is_vertex_0\n"
932e5c31af7Sopenharmony_ci		"OpReturnValue %is_unique_id_0\n"
933e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
934e5c31af7Sopenharmony_ci
935e5c31af7Sopenharmony_ci		"${testfun}\n";
936e5c31af7Sopenharmony_ci	return tcu::StringTemplate(geometryShaderBoilerplate).specialize(fragments);
937e5c31af7Sopenharmony_ci}
938e5c31af7Sopenharmony_ci
939e5c31af7Sopenharmony_ci// Creates fragment-shader assembly by specializing a boilerplate StringTemplate
940e5c31af7Sopenharmony_ci// on fragments, which must (at least) map "testfun" to an OpFunction definition
941e5c31af7Sopenharmony_ci// for %test_code that takes and returns a %v4f32.  Boilerplate IDs are prefixed
942e5c31af7Sopenharmony_ci// with "BP_" to avoid collisions with fragments.
943e5c31af7Sopenharmony_ci//
944e5c31af7Sopenharmony_ci// Derived from this GLSL:
945e5c31af7Sopenharmony_ci//
946e5c31af7Sopenharmony_ci// layout(location = 1) in highp vec4 vtxColor;
947e5c31af7Sopenharmony_ci// layout(location = 0) out highp vec4 fragColor;
948e5c31af7Sopenharmony_ci// highp vec4 testfun(highp vec4 x) { return x; }
949e5c31af7Sopenharmony_ci// void main(void) { fragColor = testfun(vtxColor); }
950e5c31af7Sopenharmony_ci//
951e5c31af7Sopenharmony_ci// with modifications including passing vtxColor by value and ripping out
952e5c31af7Sopenharmony_ci// testfun() definition.
953e5c31af7Sopenharmony_cistring makeFragmentShaderAssembly (const map<string, string>& fragments)
954e5c31af7Sopenharmony_ci{
955e5c31af7Sopenharmony_ci	static const char fragmentShaderBoilerplate[] =
956e5c31af7Sopenharmony_ci		"OpCapability Shader\n"
957e5c31af7Sopenharmony_ci		"${capability:opt}\n"
958e5c31af7Sopenharmony_ci		"${extension:opt}\n"
959e5c31af7Sopenharmony_ci		"OpMemoryModel Logical GLSL450\n"
960e5c31af7Sopenharmony_ci		"OpEntryPoint Fragment %BP_main \"main\" %BP_vtxColor %BP_fragColor %BP_gl_FragCoord ${IF_entrypoint:opt} \n"
961e5c31af7Sopenharmony_ci		"OpExecutionMode %BP_main OriginUpperLeft\n"
962e5c31af7Sopenharmony_ci		"${execution_mode:opt}\n"
963e5c31af7Sopenharmony_ci		"${debug:opt}\n"
964e5c31af7Sopenharmony_ci		"${moduleprocessed:opt}\n"
965e5c31af7Sopenharmony_ci		"OpDecorate %BP_fragColor Location 0\n"
966e5c31af7Sopenharmony_ci		"OpDecorate %BP_vtxColor Location 1\n"
967e5c31af7Sopenharmony_ci		"OpDecorate %BP_gl_FragCoord BuiltIn FragCoord\n"
968e5c31af7Sopenharmony_ci		"${IF_decoration:opt}\n"
969e5c31af7Sopenharmony_ci		"${decoration:opt}\n"
970e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_TYPES
971e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_CONSTANTS
972e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_ARRAYS
973e5c31af7Sopenharmony_ci		"%BP_gl_FragCoord = OpVariable %ip_v4f32 Input\n"
974e5c31af7Sopenharmony_ci		"%BP_fragColor = OpVariable %op_v4f32 Output\n"
975e5c31af7Sopenharmony_ci		"%BP_vtxColor = OpVariable %ip_v4f32 Input\n"
976e5c31af7Sopenharmony_ci		"${pre_main:opt}\n"
977e5c31af7Sopenharmony_ci		"${IF_variable:opt}\n"
978e5c31af7Sopenharmony_ci		"%BP_main = OpFunction %void None %voidf\n"
979e5c31af7Sopenharmony_ci		"%BP_label_main = OpLabel\n"
980e5c31af7Sopenharmony_ci		"${IF_carryforward:opt}\n"
981e5c31af7Sopenharmony_ci		"${post_interface_op_frag:opt}\n"
982e5c31af7Sopenharmony_ci		"%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n"
983e5c31af7Sopenharmony_ci		"%BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1\n"
984e5c31af7Sopenharmony_ci		"OpStore %BP_fragColor %BP_tmp2\n"
985e5c31af7Sopenharmony_ci		"OpReturn\n"
986e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
987e5c31af7Sopenharmony_ci		"${interface_op_func:opt}\n"
988e5c31af7Sopenharmony_ci
989e5c31af7Sopenharmony_ci		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
990e5c31af7Sopenharmony_ci		"%getId_label = OpLabel\n"
991e5c31af7Sopenharmony_ci		"%loc_x_coord = OpAccessChain %ip_f32 %BP_gl_FragCoord %c_i32_0\n"
992e5c31af7Sopenharmony_ci		"%loc_y_coord = OpAccessChain %ip_f32 %BP_gl_FragCoord %c_i32_1\n"
993e5c31af7Sopenharmony_ci		"%x_coord = OpLoad %f32 %loc_x_coord\n"
994e5c31af7Sopenharmony_ci		"%y_coord = OpLoad %f32 %loc_y_coord\n"
995e5c31af7Sopenharmony_ci		"%is_x_idx0 = OpFOrdEqual %bool %x_coord %c_f32_0_5\n"
996e5c31af7Sopenharmony_ci		"%is_y_idx0 = OpFOrdEqual %bool %y_coord %c_f32_0_5\n"
997e5c31af7Sopenharmony_ci		"%is_frag_0 = OpLogicalAnd %bool %is_x_idx0 %is_y_idx0\n"
998e5c31af7Sopenharmony_ci		"OpReturnValue %is_frag_0\n"
999e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
1000e5c31af7Sopenharmony_ci
1001e5c31af7Sopenharmony_ci		"${testfun}\n";
1002e5c31af7Sopenharmony_ci	return tcu::StringTemplate(fragmentShaderBoilerplate).specialize(fragments);
1003e5c31af7Sopenharmony_ci}
1004e5c31af7Sopenharmony_ci
1005e5c31af7Sopenharmony_ci// Creates mappings from placeholders to pass-through shader code which copies
1006e5c31af7Sopenharmony_ci// the input to the output faithfully.
1007e5c31af7Sopenharmony_cimap<string, string> passthruInterface (const IFDataType& data_type)
1008e5c31af7Sopenharmony_ci{
1009e5c31af7Sopenharmony_ci	const string		var_type	= data_type.str();
1010e5c31af7Sopenharmony_ci	map<string, string>	fragments	= passthruFragments();
1011e5c31af7Sopenharmony_ci	const string		functype	= string("%") + var_type + "_" + var_type + "_function";
1012e5c31af7Sopenharmony_ci
1013e5c31af7Sopenharmony_ci	fragments["interface_op_call"]  = "OpCopyObject %" + var_type;
1014e5c31af7Sopenharmony_ci	fragments["interface_op_func"]	= "";
1015e5c31af7Sopenharmony_ci	fragments["input_type"]			= var_type;
1016e5c31af7Sopenharmony_ci	fragments["output_type"]		= var_type;
1017e5c31af7Sopenharmony_ci	fragments["pre_main"]			= "";
1018e5c31af7Sopenharmony_ci
1019e5c31af7Sopenharmony_ci	if (!data_type.elementIs32bit())
1020e5c31af7Sopenharmony_ci	{
1021e5c31af7Sopenharmony_ci		if (data_type.elementType == NUMBERTYPE_FLOAT64)
1022e5c31af7Sopenharmony_ci		{
1023e5c31af7Sopenharmony_ci			fragments["capability"]		= "OpCapability Float64\n\n";
1024e5c31af7Sopenharmony_ci			fragments["pre_main"]	+= "%f64 = OpTypeFloat 64\n";
1025e5c31af7Sopenharmony_ci		}
1026e5c31af7Sopenharmony_ci		else if (data_type.elementType == NUMBERTYPE_FLOAT16)
1027e5c31af7Sopenharmony_ci		{
1028e5c31af7Sopenharmony_ci			fragments["capability"]		= "OpCapability StorageInputOutput16\n";
1029e5c31af7Sopenharmony_ci			fragments["extension"]		= "OpExtension \"SPV_KHR_16bit_storage\"\n";
1030e5c31af7Sopenharmony_ci			fragments["pre_main"]	+= "%f16 = OpTypeFloat 16\n";
1031e5c31af7Sopenharmony_ci		}
1032e5c31af7Sopenharmony_ci		else if (data_type.elementType == NUMBERTYPE_INT16)
1033e5c31af7Sopenharmony_ci		{
1034e5c31af7Sopenharmony_ci			fragments["capability"]		= "OpCapability StorageInputOutput16\n";
1035e5c31af7Sopenharmony_ci			fragments["extension"]		= "OpExtension \"SPV_KHR_16bit_storage\"\n";
1036e5c31af7Sopenharmony_ci			fragments["pre_main"]	+= "%i16 = OpTypeInt 16 1\n";
1037e5c31af7Sopenharmony_ci		}
1038e5c31af7Sopenharmony_ci		else if (data_type.elementType == NUMBERTYPE_UINT16)
1039e5c31af7Sopenharmony_ci		{
1040e5c31af7Sopenharmony_ci			fragments["capability"]		= "OpCapability StorageInputOutput16\n";
1041e5c31af7Sopenharmony_ci			fragments["extension"]		= "OpExtension \"SPV_KHR_16bit_storage\"\n";
1042e5c31af7Sopenharmony_ci			fragments["pre_main"]	+= "%u16 = OpTypeInt 16 0\n";
1043e5c31af7Sopenharmony_ci		}
1044e5c31af7Sopenharmony_ci		else
1045e5c31af7Sopenharmony_ci		{
1046e5c31af7Sopenharmony_ci			DE_ASSERT(0 && "unhandled type");
1047e5c31af7Sopenharmony_ci		}
1048e5c31af7Sopenharmony_ci
1049e5c31af7Sopenharmony_ci		if (data_type.isVector())
1050e5c31af7Sopenharmony_ci		{
1051e5c31af7Sopenharmony_ci			fragments["pre_main"]	+= "%" + var_type + " = OpTypeVector %" + IFDataType(1, data_type.elementType).str() + " " + numberToString(data_type.numElements) + "\n";
1052e5c31af7Sopenharmony_ci		}
1053e5c31af7Sopenharmony_ci
1054e5c31af7Sopenharmony_ci		fragments["pre_main"]		+=
1055e5c31af7Sopenharmony_ci			"%ip_" + var_type + " = OpTypePointer Input %" + var_type + "\n"
1056e5c31af7Sopenharmony_ci			"%op_" + var_type + " = OpTypePointer Output %" + var_type + "\n";
1057e5c31af7Sopenharmony_ci	}
1058e5c31af7Sopenharmony_ci
1059e5c31af7Sopenharmony_ci	if (strcmp(var_type.c_str(), "v4f32") != 0)
1060e5c31af7Sopenharmony_ci		fragments["pre_main"]		+=
1061e5c31af7Sopenharmony_ci			functype + " = OpTypeFunction %" + var_type + " %" + var_type + "\n"
1062e5c31af7Sopenharmony_ci			"%a3" + var_type + " = OpTypeArray %" + var_type + " %c_i32_3\n"
1063e5c31af7Sopenharmony_ci			"%ip_a3" + var_type + " = OpTypePointer Input %a3" + var_type + "\n"
1064e5c31af7Sopenharmony_ci			"%op_a3" + var_type + " = OpTypePointer Output %a3" + var_type + "\n";
1065e5c31af7Sopenharmony_ci
1066e5c31af7Sopenharmony_ci	return fragments;
1067e5c31af7Sopenharmony_ci}
1068e5c31af7Sopenharmony_ci
1069e5c31af7Sopenharmony_ci// Returns mappings from interface placeholders to their concrete values.
1070e5c31af7Sopenharmony_ci//
1071e5c31af7Sopenharmony_ci// The concrete values should be specialized again to provide ${input_type}
1072e5c31af7Sopenharmony_ci// and ${output_type}.
1073e5c31af7Sopenharmony_ci//
1074e5c31af7Sopenharmony_ci// %ip_${input_type} and %op_${output_type} should also be defined in the final code.
1075e5c31af7Sopenharmony_cimap<string, string> fillInterfacePlaceholderVert (void)
1076e5c31af7Sopenharmony_ci{
1077e5c31af7Sopenharmony_ci	map<string, string>	fragments;
1078e5c31af7Sopenharmony_ci
1079e5c31af7Sopenharmony_ci	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
1080e5c31af7Sopenharmony_ci	fragments["IF_variable"]		=
1081e5c31af7Sopenharmony_ci		" %IF_input = OpVariable %ip_${input_type} Input\n"
1082e5c31af7Sopenharmony_ci		"%IF_output = OpVariable %op_${output_type} Output\n";
1083e5c31af7Sopenharmony_ci	fragments["IF_decoration"]		=
1084e5c31af7Sopenharmony_ci		"OpDecorate  %IF_input Location 2\n"
1085e5c31af7Sopenharmony_ci		"OpDecorate %IF_output Location 2\n";
1086e5c31af7Sopenharmony_ci	fragments["IF_carryforward"]	=
1087e5c31af7Sopenharmony_ci		"%IF_input_val = OpLoad %${input_type} %IF_input\n"
1088e5c31af7Sopenharmony_ci		"   %IF_result = ${interface_op_call} %IF_input_val\n"
1089e5c31af7Sopenharmony_ci		"                OpStore %IF_output %IF_result\n";
1090e5c31af7Sopenharmony_ci
1091e5c31af7Sopenharmony_ci	// Make sure the rest still need to be instantialized.
1092e5c31af7Sopenharmony_ci	fragments["capability"]				= "${capability:opt}";
1093e5c31af7Sopenharmony_ci	fragments["extension"]				= "${extension:opt}";
1094e5c31af7Sopenharmony_ci	fragments["execution_mode"]			= "${execution_mode:opt}";
1095e5c31af7Sopenharmony_ci	fragments["debug"]					= "${debug:opt}";
1096e5c31af7Sopenharmony_ci	fragments["decoration"]				= "${decoration:opt}";
1097e5c31af7Sopenharmony_ci	fragments["pre_main"]				= "${pre_main:opt}";
1098e5c31af7Sopenharmony_ci	fragments["testfun"]				= "${testfun}";
1099e5c31af7Sopenharmony_ci	fragments["interface_op_call"]    = "${interface_op_call}";
1100e5c31af7Sopenharmony_ci	fragments["interface_op_func"]		= "${interface_op_func}";
1101e5c31af7Sopenharmony_ci	fragments["post_interface_op_vert"]	= "${post_interface_op_vert:opt}";
1102e5c31af7Sopenharmony_ci
1103e5c31af7Sopenharmony_ci	return fragments;
1104e5c31af7Sopenharmony_ci}
1105e5c31af7Sopenharmony_ci
1106e5c31af7Sopenharmony_ci// Returns mappings from interface placeholders to their concrete values.
1107e5c31af7Sopenharmony_ci//
1108e5c31af7Sopenharmony_ci// The concrete values should be specialized again to provide ${input_type}
1109e5c31af7Sopenharmony_ci// and ${output_type}.
1110e5c31af7Sopenharmony_ci//
1111e5c31af7Sopenharmony_ci// %ip_${input_type} and %op_${output_type} should also be defined in the final code.
1112e5c31af7Sopenharmony_cimap<string, string> fillInterfacePlaceholderFrag (void)
1113e5c31af7Sopenharmony_ci{
1114e5c31af7Sopenharmony_ci	map<string, string>	fragments;
1115e5c31af7Sopenharmony_ci
1116e5c31af7Sopenharmony_ci	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
1117e5c31af7Sopenharmony_ci	fragments["IF_variable"]		=
1118e5c31af7Sopenharmony_ci		" %IF_input = OpVariable %ip_${input_type} Input\n"
1119e5c31af7Sopenharmony_ci		"%IF_output = OpVariable %op_${output_type} Output\n";
1120e5c31af7Sopenharmony_ci	fragments["IF_decoration"]		=
1121e5c31af7Sopenharmony_ci		"OpDecorate %IF_input Flat\n"
1122e5c31af7Sopenharmony_ci		"OpDecorate %IF_input Location 2\n"
1123e5c31af7Sopenharmony_ci		"OpDecorate %IF_output Location 1\n";  // Fragment shader should write to location #1.
1124e5c31af7Sopenharmony_ci	fragments["IF_carryforward"]	=
1125e5c31af7Sopenharmony_ci		"%IF_input_val = OpLoad %${input_type} %IF_input\n"
1126e5c31af7Sopenharmony_ci		"   %IF_result = ${interface_op_call} %IF_input_val\n"
1127e5c31af7Sopenharmony_ci		"                OpStore %IF_output %IF_result\n";
1128e5c31af7Sopenharmony_ci
1129e5c31af7Sopenharmony_ci	// Make sure the rest still need to be instantialized.
1130e5c31af7Sopenharmony_ci	fragments["capability"]				= "${capability:opt}";
1131e5c31af7Sopenharmony_ci	fragments["extension"]				= "${extension:opt}";
1132e5c31af7Sopenharmony_ci	fragments["execution_mode"]			= "${execution_mode:opt}";
1133e5c31af7Sopenharmony_ci	fragments["debug"]					= "${debug:opt}";
1134e5c31af7Sopenharmony_ci	fragments["decoration"]				= "${decoration:opt}";
1135e5c31af7Sopenharmony_ci	fragments["pre_main"]				= "${pre_main:opt}";
1136e5c31af7Sopenharmony_ci	fragments["testfun"]				= "${testfun}";
1137e5c31af7Sopenharmony_ci	fragments["interface_op_call"]		= "${interface_op_call}";
1138e5c31af7Sopenharmony_ci	fragments["interface_op_func"]		= "${interface_op_func}";
1139e5c31af7Sopenharmony_ci	fragments["post_interface_op_frag"]	= "${post_interface_op_frag:opt}";
1140e5c31af7Sopenharmony_ci
1141e5c31af7Sopenharmony_ci	return fragments;
1142e5c31af7Sopenharmony_ci}
1143e5c31af7Sopenharmony_ci
1144e5c31af7Sopenharmony_ci// Returns mappings from interface placeholders to their concrete values.
1145e5c31af7Sopenharmony_ci//
1146e5c31af7Sopenharmony_ci// The concrete values should be specialized again to provide ${input_type}
1147e5c31af7Sopenharmony_ci// and ${output_type}.
1148e5c31af7Sopenharmony_ci//
1149e5c31af7Sopenharmony_ci// %ip_${input_type}, %op_${output_type}, %ip_a3${input_type}, and $op_a3${output_type}
1150e5c31af7Sopenharmony_ci// should also be defined in the final code.
1151e5c31af7Sopenharmony_cimap<string, string> fillInterfacePlaceholderTessCtrl (void)
1152e5c31af7Sopenharmony_ci{
1153e5c31af7Sopenharmony_ci	map<string, string>	fragments;
1154e5c31af7Sopenharmony_ci
1155e5c31af7Sopenharmony_ci	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
1156e5c31af7Sopenharmony_ci	fragments["IF_variable"]		=
1157e5c31af7Sopenharmony_ci		" %IF_input = OpVariable %ip_a3${input_type} Input\n"
1158e5c31af7Sopenharmony_ci		"%IF_output = OpVariable %op_a3${output_type} Output\n";
1159e5c31af7Sopenharmony_ci	fragments["IF_decoration"]		=
1160e5c31af7Sopenharmony_ci		"OpDecorate  %IF_input Location 2\n"
1161e5c31af7Sopenharmony_ci		"OpDecorate %IF_output Location 2\n";
1162e5c31af7Sopenharmony_ci	fragments["IF_carryforward"]	=
1163e5c31af7Sopenharmony_ci		" %IF_input_ptr0 = OpAccessChain %ip_${input_type} %IF_input %c_i32_0\n"
1164e5c31af7Sopenharmony_ci		" %IF_input_ptr1 = OpAccessChain %ip_${input_type} %IF_input %c_i32_1\n"
1165e5c31af7Sopenharmony_ci		" %IF_input_ptr2 = OpAccessChain %ip_${input_type} %IF_input %c_i32_2\n"
1166e5c31af7Sopenharmony_ci		"%IF_output_ptr0 = OpAccessChain %op_${output_type} %IF_output %c_i32_0\n"
1167e5c31af7Sopenharmony_ci		"%IF_output_ptr1 = OpAccessChain %op_${output_type} %IF_output %c_i32_1\n"
1168e5c31af7Sopenharmony_ci		"%IF_output_ptr2 = OpAccessChain %op_${output_type} %IF_output %c_i32_2\n"
1169e5c31af7Sopenharmony_ci		"%IF_input_val0 = OpLoad %${input_type} %IF_input_ptr0\n"
1170e5c31af7Sopenharmony_ci		"%IF_input_val1 = OpLoad %${input_type} %IF_input_ptr1\n"
1171e5c31af7Sopenharmony_ci		"%IF_input_val2 = OpLoad %${input_type} %IF_input_ptr2\n"
1172e5c31af7Sopenharmony_ci		"%IF_input_res0 = ${interface_op_call} %IF_input_val0\n"
1173e5c31af7Sopenharmony_ci		"%IF_input_res1 = ${interface_op_call} %IF_input_val1\n"
1174e5c31af7Sopenharmony_ci		"%IF_input_res2 = ${interface_op_call} %IF_input_val2\n"
1175e5c31af7Sopenharmony_ci		"OpStore %IF_output_ptr0 %IF_input_res0\n"
1176e5c31af7Sopenharmony_ci		"OpStore %IF_output_ptr1 %IF_input_res1\n"
1177e5c31af7Sopenharmony_ci		"OpStore %IF_output_ptr2 %IF_input_res2\n";
1178e5c31af7Sopenharmony_ci
1179e5c31af7Sopenharmony_ci	// Make sure the rest still need to be instantialized.
1180e5c31af7Sopenharmony_ci	fragments["capability"]					= "${capability:opt}";
1181e5c31af7Sopenharmony_ci	fragments["extension"]					= "${extension:opt}";
1182e5c31af7Sopenharmony_ci	fragments["execution_mode"]				= "${execution_mode:opt}";
1183e5c31af7Sopenharmony_ci	fragments["debug"]						= "${debug:opt}";
1184e5c31af7Sopenharmony_ci	fragments["decoration"]					= "${decoration:opt}";
1185e5c31af7Sopenharmony_ci	fragments["decoration_tessc"]			= "${decoration_tessc:opt}";
1186e5c31af7Sopenharmony_ci	fragments["pre_main"]					= "${pre_main:opt}";
1187e5c31af7Sopenharmony_ci	fragments["testfun"]					= "${testfun}";
1188e5c31af7Sopenharmony_ci	fragments["interface_op_call"]			= "${interface_op_call}";
1189e5c31af7Sopenharmony_ci	fragments["interface_op_func"]			= "${interface_op_func}";
1190e5c31af7Sopenharmony_ci	fragments["post_interface_op_tessc"]	= "${post_interface_op_tessc:opt}";
1191e5c31af7Sopenharmony_ci
1192e5c31af7Sopenharmony_ci	return fragments;
1193e5c31af7Sopenharmony_ci}
1194e5c31af7Sopenharmony_ci
1195e5c31af7Sopenharmony_ci// Returns mappings from interface placeholders to their concrete values.
1196e5c31af7Sopenharmony_ci//
1197e5c31af7Sopenharmony_ci// The concrete values should be specialized again to provide ${input_type}
1198e5c31af7Sopenharmony_ci// and ${output_type}.
1199e5c31af7Sopenharmony_ci//
1200e5c31af7Sopenharmony_ci// %ip_${input_type}, %op_${output_type}, %ip_a3${input_type}, and $op_a3${output_type}
1201e5c31af7Sopenharmony_ci// should also be defined in the final code.
1202e5c31af7Sopenharmony_cimap<string, string> fillInterfacePlaceholderTessEvalGeom (void)
1203e5c31af7Sopenharmony_ci{
1204e5c31af7Sopenharmony_ci	map<string, string>	fragments;
1205e5c31af7Sopenharmony_ci
1206e5c31af7Sopenharmony_ci	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
1207e5c31af7Sopenharmony_ci	fragments["IF_variable"]		=
1208e5c31af7Sopenharmony_ci		" %IF_input = OpVariable %ip_a3${input_type} Input\n"
1209e5c31af7Sopenharmony_ci		"%IF_output = OpVariable %op_${output_type} Output\n";
1210e5c31af7Sopenharmony_ci	fragments["IF_decoration"]		=
1211e5c31af7Sopenharmony_ci		"OpDecorate  %IF_input Location 2\n"
1212e5c31af7Sopenharmony_ci		"OpDecorate %IF_output Location 2\n";
1213e5c31af7Sopenharmony_ci	fragments["IF_carryforward"]	=
1214e5c31af7Sopenharmony_ci		// Only get the first value since all three values are the same anyway.
1215e5c31af7Sopenharmony_ci		" %IF_input_ptr0 = OpAccessChain %ip_${input_type} %IF_input %c_i32_0\n"
1216e5c31af7Sopenharmony_ci		" %IF_input_val0 = OpLoad %${input_type} %IF_input_ptr0\n"
1217e5c31af7Sopenharmony_ci		" %IF_input_res0 = ${interface_op_call} %IF_input_val0\n"
1218e5c31af7Sopenharmony_ci		"OpStore %IF_output %IF_input_res0\n";
1219e5c31af7Sopenharmony_ci
1220e5c31af7Sopenharmony_ci	// Make sure the rest still need to be instantialized.
1221e5c31af7Sopenharmony_ci	fragments["capability"]					= "${capability:opt}";
1222e5c31af7Sopenharmony_ci	fragments["extension"]					= "${extension:opt}";
1223e5c31af7Sopenharmony_ci	fragments["execution_mode"]				= "${execution_mode:opt}";
1224e5c31af7Sopenharmony_ci	fragments["debug"]						= "${debug:opt}";
1225e5c31af7Sopenharmony_ci	fragments["decoration"]					= "${decoration:opt}";
1226e5c31af7Sopenharmony_ci	fragments["pre_main"]					= "${pre_main:opt}";
1227e5c31af7Sopenharmony_ci	fragments["testfun"]					= "${testfun}";
1228e5c31af7Sopenharmony_ci	fragments["interface_op_call"]			= "${interface_op_call}";
1229e5c31af7Sopenharmony_ci	fragments["interface_op_func"]			= "${interface_op_func}";
1230e5c31af7Sopenharmony_ci	fragments["post_interface_op_tesse"]	= "${post_interface_op_tesse:opt}";
1231e5c31af7Sopenharmony_ci	fragments["post_interface_op_geom"]		= "${post_interface_op_geom:opt}";
1232e5c31af7Sopenharmony_ci
1233e5c31af7Sopenharmony_ci	return fragments;
1234e5c31af7Sopenharmony_ci}
1235e5c31af7Sopenharmony_ci
1236e5c31af7Sopenharmony_cimap<string, string> passthruFragments (void)
1237e5c31af7Sopenharmony_ci{
1238e5c31af7Sopenharmony_ci	map<string, string> fragments;
1239e5c31af7Sopenharmony_ci	fragments["testfun"] =
1240e5c31af7Sopenharmony_ci		// A %test_code function that returns its argument unchanged.
1241e5c31af7Sopenharmony_ci		"%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
1242e5c31af7Sopenharmony_ci		"%param1 = OpFunctionParameter %v4f32\n"
1243e5c31af7Sopenharmony_ci		"%label_testfun = OpLabel\n"
1244e5c31af7Sopenharmony_ci		"OpReturnValue %param1\n"
1245e5c31af7Sopenharmony_ci		"OpFunctionEnd\n";
1246e5c31af7Sopenharmony_ci	return fragments;
1247e5c31af7Sopenharmony_ci}
1248e5c31af7Sopenharmony_ci
1249e5c31af7Sopenharmony_ci// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
1250e5c31af7Sopenharmony_ci// Vertex shader gets custom code from context, the rest are pass-through.
1251e5c31af7Sopenharmony_civoid addShaderCodeCustomVertex (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
1252e5c31af7Sopenharmony_ci{
1253e5c31af7Sopenharmony_ci	const deUint32 vulkanVersion = dst.usedVulkanVersion;
1254e5c31af7Sopenharmony_ci	SpirvVersion targetSpirvVersion;
1255e5c31af7Sopenharmony_ci
1256e5c31af7Sopenharmony_ci	if (spirVAsmBuildOptions == DE_NULL)
1257e5c31af7Sopenharmony_ci		targetSpirvVersion = context.resources.spirvVersion;
1258e5c31af7Sopenharmony_ci	else
1259e5c31af7Sopenharmony_ci		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
1260e5c31af7Sopenharmony_ci
1261e5c31af7Sopenharmony_ci	if (!context.interfaces.empty())
1262e5c31af7Sopenharmony_ci	{
1263e5c31af7Sopenharmony_ci		// Inject boilerplate code to wire up additional input/output variables between stages.
1264e5c31af7Sopenharmony_ci		// Just copy the contents in input variable to output variable in all stages except
1265e5c31af7Sopenharmony_ci		// the customized stage.
1266e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1267e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1268e5c31af7Sopenharmony_ci	} else {
1269e5c31af7Sopenharmony_ci		map<string, string> passthru = passthruFragments();
1270e5c31af7Sopenharmony_ci
1271e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1272e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1273e5c31af7Sopenharmony_ci	}
1274e5c31af7Sopenharmony_ci}
1275e5c31af7Sopenharmony_ci
1276e5c31af7Sopenharmony_civoid addShaderCodeCustomVertex (vk::SourceCollections& dst, InstanceContext context)
1277e5c31af7Sopenharmony_ci{
1278e5c31af7Sopenharmony_ci	addShaderCodeCustomVertex(dst, context, DE_NULL);
1279e5c31af7Sopenharmony_ci}
1280e5c31af7Sopenharmony_ci
1281e5c31af7Sopenharmony_ci// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
1282e5c31af7Sopenharmony_ci// Tessellation control shader gets custom code from context, the rest are
1283e5c31af7Sopenharmony_ci// pass-through.
1284e5c31af7Sopenharmony_civoid addShaderCodeCustomTessControl (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
1285e5c31af7Sopenharmony_ci{
1286e5c31af7Sopenharmony_ci	const deUint32 vulkanVersion = dst.usedVulkanVersion;
1287e5c31af7Sopenharmony_ci	SpirvVersion targetSpirvVersion;
1288e5c31af7Sopenharmony_ci
1289e5c31af7Sopenharmony_ci	if (spirVAsmBuildOptions == DE_NULL)
1290e5c31af7Sopenharmony_ci		targetSpirvVersion = context.resources.spirvVersion;
1291e5c31af7Sopenharmony_ci	else
1292e5c31af7Sopenharmony_ci		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
1293e5c31af7Sopenharmony_ci
1294e5c31af7Sopenharmony_ci	if (!context.interfaces.empty())
1295e5c31af7Sopenharmony_ci	{
1296e5c31af7Sopenharmony_ci		// Inject boilerplate code to wire up additional input/output variables between stages.
1297e5c31af7Sopenharmony_ci		// Just copy the contents in input variable to output variable in all stages except
1298e5c31af7Sopenharmony_ci		// the customized stage.
1299e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1300e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1301e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1302e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1303e5c31af7Sopenharmony_ci	}
1304e5c31af7Sopenharmony_ci	else
1305e5c31af7Sopenharmony_ci	{
1306e5c31af7Sopenharmony_ci		map<string, string> passthru = passthruFragments();
1307e5c31af7Sopenharmony_ci
1308e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1309e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << makeTessControlShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1310e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << makeTessEvalShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1311e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1312e5c31af7Sopenharmony_ci	}
1313e5c31af7Sopenharmony_ci}
1314e5c31af7Sopenharmony_ci
1315e5c31af7Sopenharmony_civoid addShaderCodeCustomTessControl (vk::SourceCollections& dst, InstanceContext context)
1316e5c31af7Sopenharmony_ci{
1317e5c31af7Sopenharmony_ci	addShaderCodeCustomTessControl(dst, context, DE_NULL);
1318e5c31af7Sopenharmony_ci}
1319e5c31af7Sopenharmony_ci
1320e5c31af7Sopenharmony_ci// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
1321e5c31af7Sopenharmony_ci// Tessellation evaluation shader gets custom code from context, the rest are
1322e5c31af7Sopenharmony_ci// pass-through.
1323e5c31af7Sopenharmony_civoid addShaderCodeCustomTessEval (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
1324e5c31af7Sopenharmony_ci{
1325e5c31af7Sopenharmony_ci	const deUint32 vulkanVersion = dst.usedVulkanVersion;
1326e5c31af7Sopenharmony_ci	SpirvVersion targetSpirvVersion;
1327e5c31af7Sopenharmony_ci
1328e5c31af7Sopenharmony_ci	if (spirVAsmBuildOptions == DE_NULL)
1329e5c31af7Sopenharmony_ci		targetSpirvVersion = context.resources.spirvVersion;
1330e5c31af7Sopenharmony_ci	else
1331e5c31af7Sopenharmony_ci		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
1332e5c31af7Sopenharmony_ci
1333e5c31af7Sopenharmony_ci	if (!context.interfaces.empty())
1334e5c31af7Sopenharmony_ci	{
1335e5c31af7Sopenharmony_ci		// Inject boilerplate code to wire up additional input/output variables between stages.
1336e5c31af7Sopenharmony_ci		// Just copy the contents in input variable to output variable in all stages except
1337e5c31af7Sopenharmony_ci		// the customized stage.
1338e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1339e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1340e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1341e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1342e5c31af7Sopenharmony_ci	}
1343e5c31af7Sopenharmony_ci	else
1344e5c31af7Sopenharmony_ci	{
1345e5c31af7Sopenharmony_ci		map<string, string> passthru = passthruFragments();
1346e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1347e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << makeTessControlShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1348e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << makeTessEvalShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1349e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1350e5c31af7Sopenharmony_ci	}
1351e5c31af7Sopenharmony_ci}
1352e5c31af7Sopenharmony_ci
1353e5c31af7Sopenharmony_civoid addShaderCodeCustomTessEval (vk::SourceCollections& dst, InstanceContext context)
1354e5c31af7Sopenharmony_ci{
1355e5c31af7Sopenharmony_ci	addShaderCodeCustomTessEval(dst, context, DE_NULL);
1356e5c31af7Sopenharmony_ci}
1357e5c31af7Sopenharmony_ci
1358e5c31af7Sopenharmony_ci// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
1359e5c31af7Sopenharmony_ci// Geometry shader gets custom code from context, the rest are pass-through.
1360e5c31af7Sopenharmony_civoid addShaderCodeCustomGeometry (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
1361e5c31af7Sopenharmony_ci{
1362e5c31af7Sopenharmony_ci	const deUint32 vulkanVersion = dst.usedVulkanVersion;
1363e5c31af7Sopenharmony_ci	SpirvVersion targetSpirvVersion;
1364e5c31af7Sopenharmony_ci
1365e5c31af7Sopenharmony_ci	if (spirVAsmBuildOptions == DE_NULL)
1366e5c31af7Sopenharmony_ci		targetSpirvVersion = context.resources.spirvVersion;
1367e5c31af7Sopenharmony_ci	else
1368e5c31af7Sopenharmony_ci		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
1369e5c31af7Sopenharmony_ci
1370e5c31af7Sopenharmony_ci	if (!context.interfaces.empty())
1371e5c31af7Sopenharmony_ci	{
1372e5c31af7Sopenharmony_ci		// Inject boilerplate code to wire up additional input/output variables between stages.
1373e5c31af7Sopenharmony_ci		// Just copy the contents in input variable to output variable in all stages except
1374e5c31af7Sopenharmony_ci		// the customized stage.
1375e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1376e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("geom", spirVAsmBuildOptions) << StringTemplate(makeGeometryShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1377e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1378e5c31af7Sopenharmony_ci	}
1379e5c31af7Sopenharmony_ci	else
1380e5c31af7Sopenharmony_ci	{
1381e5c31af7Sopenharmony_ci		map<string, string> passthru = passthruFragments();
1382e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1383e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("geom", spirVAsmBuildOptions) << makeGeometryShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1384e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1385e5c31af7Sopenharmony_ci	}
1386e5c31af7Sopenharmony_ci}
1387e5c31af7Sopenharmony_ci
1388e5c31af7Sopenharmony_civoid addShaderCodeCustomGeometry (vk::SourceCollections& dst, InstanceContext context)
1389e5c31af7Sopenharmony_ci{
1390e5c31af7Sopenharmony_ci	addShaderCodeCustomGeometry(dst, context, DE_NULL);
1391e5c31af7Sopenharmony_ci}
1392e5c31af7Sopenharmony_ci
1393e5c31af7Sopenharmony_ci// Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
1394e5c31af7Sopenharmony_ci// Fragment shader gets custom code from context, the rest are pass-through.
1395e5c31af7Sopenharmony_civoid addShaderCodeCustomFragment (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
1396e5c31af7Sopenharmony_ci{
1397e5c31af7Sopenharmony_ci	const deUint32 vulkanVersion = dst.usedVulkanVersion;
1398e5c31af7Sopenharmony_ci	SpirvVersion targetSpirvVersion;
1399e5c31af7Sopenharmony_ci
1400e5c31af7Sopenharmony_ci	if (spirVAsmBuildOptions == DE_NULL)
1401e5c31af7Sopenharmony_ci		targetSpirvVersion = context.resources.spirvVersion;
1402e5c31af7Sopenharmony_ci	else
1403e5c31af7Sopenharmony_ci		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
1404e5c31af7Sopenharmony_ci
1405e5c31af7Sopenharmony_ci	if (!context.interfaces.empty())
1406e5c31af7Sopenharmony_ci	{
1407e5c31af7Sopenharmony_ci		// Inject boilerplate code to wire up additional input/output variables between stages.
1408e5c31af7Sopenharmony_ci		// Just copy the contents in input variable to output variable in all stages except
1409e5c31af7Sopenharmony_ci		// the customized stage.
1410e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1411e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1412e5c31af7Sopenharmony_ci	}
1413e5c31af7Sopenharmony_ci	else
1414e5c31af7Sopenharmony_ci	{
1415e5c31af7Sopenharmony_ci		map<string, string> passthru = passthruFragments();
1416e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1417e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1418e5c31af7Sopenharmony_ci	}
1419e5c31af7Sopenharmony_ci}
1420e5c31af7Sopenharmony_ci
1421e5c31af7Sopenharmony_civoid addShaderCodeCustomFragment (vk::SourceCollections& dst, InstanceContext context)
1422e5c31af7Sopenharmony_ci{
1423e5c31af7Sopenharmony_ci	addShaderCodeCustomFragment(dst, context, DE_NULL);
1424e5c31af7Sopenharmony_ci}
1425e5c31af7Sopenharmony_ci
1426e5c31af7Sopenharmony_civoid createCombinedModule (vk::SourceCollections& dst, InstanceContext ctx)
1427e5c31af7Sopenharmony_ci{
1428e5c31af7Sopenharmony_ci	const bool			useTessellation	(ctx.requiredStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
1429e5c31af7Sopenharmony_ci	const bool			useGeometry		(ctx.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT);
1430e5c31af7Sopenharmony_ci	std::stringstream	combinedModule;
1431e5c31af7Sopenharmony_ci	std::stringstream	opCapabilities;
1432e5c31af7Sopenharmony_ci	std::stringstream	opEntryPoints;
1433e5c31af7Sopenharmony_ci
1434e5c31af7Sopenharmony_ci	// opCapabilities
1435e5c31af7Sopenharmony_ci	{
1436e5c31af7Sopenharmony_ci		opCapabilities << "OpCapability Shader\n";
1437e5c31af7Sopenharmony_ci
1438e5c31af7Sopenharmony_ci		if (useGeometry)
1439e5c31af7Sopenharmony_ci			opCapabilities << "OpCapability Geometry\n";
1440e5c31af7Sopenharmony_ci
1441e5c31af7Sopenharmony_ci		if (useTessellation)
1442e5c31af7Sopenharmony_ci			opCapabilities << "OpCapability Tessellation\n";
1443e5c31af7Sopenharmony_ci	}
1444e5c31af7Sopenharmony_ci
1445e5c31af7Sopenharmony_ci	// opEntryPoints
1446e5c31af7Sopenharmony_ci	{
1447e5c31af7Sopenharmony_ci		if (useTessellation)
1448e5c31af7Sopenharmony_ci			opEntryPoints << "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_vtxPosition %vert_vertex_id %vert_instance_id\n";
1449e5c31af7Sopenharmony_ci		else
1450e5c31af7Sopenharmony_ci			opEntryPoints << "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_glPerVertex %vert_vertex_id %vert_instance_id\n";
1451e5c31af7Sopenharmony_ci
1452e5c31af7Sopenharmony_ci		if (useGeometry)
1453e5c31af7Sopenharmony_ci			opEntryPoints << "OpEntryPoint Geometry %geom_main \"main\" %geom_out_gl_position %geom_gl_in %geom_out_color %geom_in_color\n";
1454e5c31af7Sopenharmony_ci
1455e5c31af7Sopenharmony_ci		if (useTessellation)
1456e5c31af7Sopenharmony_ci		{
1457e5c31af7Sopenharmony_ci			opEntryPoints <<	"OpEntryPoint TessellationControl %tessc_main \"main\" %tessc_out_color %tessc_gl_InvocationID %tessc_in_color %tessc_out_position %tessc_in_position %tessc_gl_TessLevelOuter %tessc_gl_TessLevelInner\n"
1458e5c31af7Sopenharmony_ci								"OpEntryPoint TessellationEvaluation %tesse_main \"main\" %tesse_stream %tesse_gl_tessCoord %tesse_in_position %tesse_out_color %tesse_in_color \n";
1459e5c31af7Sopenharmony_ci		}
1460e5c31af7Sopenharmony_ci
1461e5c31af7Sopenharmony_ci		opEntryPoints << "OpEntryPoint Fragment %frag_main \"main\" %frag_vtxColor %frag_fragColor\n";
1462e5c31af7Sopenharmony_ci	}
1463e5c31af7Sopenharmony_ci
1464e5c31af7Sopenharmony_ci	combinedModule	<<	opCapabilities.str()
1465e5c31af7Sopenharmony_ci					<<	"OpMemoryModel Logical GLSL450\n"
1466e5c31af7Sopenharmony_ci					<<	opEntryPoints.str();
1467e5c31af7Sopenharmony_ci
1468e5c31af7Sopenharmony_ci	if (useGeometry)
1469e5c31af7Sopenharmony_ci	{
1470e5c31af7Sopenharmony_ci		combinedModule <<	"OpExecutionMode %geom_main Triangles\n"
1471e5c31af7Sopenharmony_ci							"OpExecutionMode %geom_main Invocations 1\n"
1472e5c31af7Sopenharmony_ci							"OpExecutionMode %geom_main OutputTriangleStrip\n"
1473e5c31af7Sopenharmony_ci							"OpExecutionMode %geom_main OutputVertices 3\n";
1474e5c31af7Sopenharmony_ci	}
1475e5c31af7Sopenharmony_ci
1476e5c31af7Sopenharmony_ci	if (useTessellation)
1477e5c31af7Sopenharmony_ci	{
1478e5c31af7Sopenharmony_ci		combinedModule <<	"OpExecutionMode %tessc_main OutputVertices 3\n"
1479e5c31af7Sopenharmony_ci							"OpExecutionMode %tesse_main Triangles\n"
1480e5c31af7Sopenharmony_ci							"OpExecutionMode %tesse_main SpacingEqual\n"
1481e5c31af7Sopenharmony_ci							"OpExecutionMode %tesse_main VertexOrderCcw\n";
1482e5c31af7Sopenharmony_ci	}
1483e5c31af7Sopenharmony_ci
1484e5c31af7Sopenharmony_ci	combinedModule <<	"OpExecutionMode %frag_main OriginUpperLeft\n"
1485e5c31af7Sopenharmony_ci
1486e5c31af7Sopenharmony_ci						"; Vertex decorations\n"
1487e5c31af7Sopenharmony_ci						"OpDecorate %vert_Position Location 0\n"
1488e5c31af7Sopenharmony_ci						"OpDecorate %vert_vtxColor Location 1\n"
1489e5c31af7Sopenharmony_ci						"OpDecorate %vert_color Location 1\n"
1490e5c31af7Sopenharmony_ci						"OpDecorate %vert_vertex_id BuiltIn VertexIndex\n"
1491e5c31af7Sopenharmony_ci						"OpDecorate %vert_instance_id BuiltIn InstanceIndex\n";
1492e5c31af7Sopenharmony_ci
1493e5c31af7Sopenharmony_ci	// If tessellation is used, vertex position is written by tessellation stage.
1494e5c31af7Sopenharmony_ci	// Otherwise it will be written by vertex stage.
1495e5c31af7Sopenharmony_ci	if (useTessellation)
1496e5c31af7Sopenharmony_ci		combinedModule <<	"OpDecorate %vert_vtxPosition Location 2\n";
1497e5c31af7Sopenharmony_ci	else
1498e5c31af7Sopenharmony_ci	{
1499e5c31af7Sopenharmony_ci		combinedModule <<	"OpMemberDecorate %vert_per_vertex_out 0 BuiltIn Position\n"
1500e5c31af7Sopenharmony_ci							"OpMemberDecorate %vert_per_vertex_out 1 BuiltIn PointSize\n"
1501e5c31af7Sopenharmony_ci							"OpMemberDecorate %vert_per_vertex_out 2 BuiltIn ClipDistance\n"
1502e5c31af7Sopenharmony_ci							"OpMemberDecorate %vert_per_vertex_out 3 BuiltIn CullDistance\n"
1503e5c31af7Sopenharmony_ci							"OpDecorate %vert_per_vertex_out Block\n";
1504e5c31af7Sopenharmony_ci	}
1505e5c31af7Sopenharmony_ci
1506e5c31af7Sopenharmony_ci	if (useGeometry)
1507e5c31af7Sopenharmony_ci	{
1508e5c31af7Sopenharmony_ci		combinedModule <<	"; Geometry decorations\n"
1509e5c31af7Sopenharmony_ci							"OpDecorate %geom_out_gl_position BuiltIn Position\n"
1510e5c31af7Sopenharmony_ci							"OpMemberDecorate %geom_per_vertex_in 0 BuiltIn Position\n"
1511e5c31af7Sopenharmony_ci							"OpMemberDecorate %geom_per_vertex_in 1 BuiltIn PointSize\n"
1512e5c31af7Sopenharmony_ci							"OpMemberDecorate %geom_per_vertex_in 2 BuiltIn ClipDistance\n"
1513e5c31af7Sopenharmony_ci							"OpMemberDecorate %geom_per_vertex_in 3 BuiltIn CullDistance\n"
1514e5c31af7Sopenharmony_ci							"OpDecorate %geom_per_vertex_in Block\n"
1515e5c31af7Sopenharmony_ci							"OpDecorate %geom_out_color Location 1\n"
1516e5c31af7Sopenharmony_ci							"OpDecorate %geom_in_color Location 1\n";
1517e5c31af7Sopenharmony_ci	}
1518e5c31af7Sopenharmony_ci
1519e5c31af7Sopenharmony_ci	if (useTessellation)
1520e5c31af7Sopenharmony_ci	{
1521e5c31af7Sopenharmony_ci		combinedModule <<	"; Tessellation Control decorations\n"
1522e5c31af7Sopenharmony_ci							"OpDecorate %tessc_out_color Location 1\n"
1523e5c31af7Sopenharmony_ci							"OpDecorate %tessc_gl_InvocationID BuiltIn InvocationId\n"
1524e5c31af7Sopenharmony_ci							"OpDecorate %tessc_in_color Location 1\n"
1525e5c31af7Sopenharmony_ci							"OpDecorate %tessc_out_position Location 2\n"
1526e5c31af7Sopenharmony_ci							"OpDecorate %tessc_in_position Location 2\n"
1527e5c31af7Sopenharmony_ci							"OpDecorate %tessc_gl_TessLevelOuter Patch\n"
1528e5c31af7Sopenharmony_ci							"OpDecorate %tessc_gl_TessLevelOuter BuiltIn TessLevelOuter\n"
1529e5c31af7Sopenharmony_ci							"OpDecorate %tessc_gl_TessLevelInner Patch\n"
1530e5c31af7Sopenharmony_ci							"OpDecorate %tessc_gl_TessLevelInner BuiltIn TessLevelInner\n"
1531e5c31af7Sopenharmony_ci
1532e5c31af7Sopenharmony_ci							"; Tessellation Evaluation decorations\n"
1533e5c31af7Sopenharmony_ci							"OpMemberDecorate %tesse_per_vertex_out 0 BuiltIn Position\n"
1534e5c31af7Sopenharmony_ci							"OpMemberDecorate %tesse_per_vertex_out 1 BuiltIn PointSize\n"
1535e5c31af7Sopenharmony_ci							"OpMemberDecorate %tesse_per_vertex_out 2 BuiltIn ClipDistance\n"
1536e5c31af7Sopenharmony_ci							"OpMemberDecorate %tesse_per_vertex_out 3 BuiltIn CullDistance\n"
1537e5c31af7Sopenharmony_ci							"OpDecorate %tesse_per_vertex_out Block\n"
1538e5c31af7Sopenharmony_ci							"OpDecorate %tesse_gl_tessCoord BuiltIn TessCoord\n"
1539e5c31af7Sopenharmony_ci							"OpDecorate %tesse_in_position Location 2\n"
1540e5c31af7Sopenharmony_ci							"OpDecorate %tesse_out_color Location 1\n"
1541e5c31af7Sopenharmony_ci							"OpDecorate %tesse_in_color Location 1\n";
1542e5c31af7Sopenharmony_ci	}
1543e5c31af7Sopenharmony_ci
1544e5c31af7Sopenharmony_ci	combinedModule <<	"; Fragment decorations\n"
1545e5c31af7Sopenharmony_ci						"OpDecorate %frag_fragColor Location 0\n"
1546e5c31af7Sopenharmony_ci						"OpDecorate %frag_vtxColor Location 1\n"
1547e5c31af7Sopenharmony_ci
1548e5c31af7Sopenharmony_ci						SPIRV_ASSEMBLY_TYPES
1549e5c31af7Sopenharmony_ci						SPIRV_ASSEMBLY_CONSTANTS
1550e5c31af7Sopenharmony_ci						SPIRV_ASSEMBLY_ARRAYS
1551e5c31af7Sopenharmony_ci
1552e5c31af7Sopenharmony_ci						"; Vertex Variables\n"
1553e5c31af7Sopenharmony_ci						"%vert_Position = OpVariable %ip_v4f32 Input\n"
1554e5c31af7Sopenharmony_ci						"%vert_vtxColor = OpVariable %op_v4f32 Output\n"
1555e5c31af7Sopenharmony_ci						"%vert_color = OpVariable %ip_v4f32 Input\n"
1556e5c31af7Sopenharmony_ci						"%vert_vertex_id = OpVariable %ip_i32 Input\n"
1557e5c31af7Sopenharmony_ci						"%vert_instance_id = OpVariable %ip_i32 Input\n";
1558e5c31af7Sopenharmony_ci
1559e5c31af7Sopenharmony_ci	if (useTessellation)
1560e5c31af7Sopenharmony_ci		combinedModule <<	"%vert_vtxPosition = OpVariable %op_v4f32 Output\n";
1561e5c31af7Sopenharmony_ci	else
1562e5c31af7Sopenharmony_ci	{
1563e5c31af7Sopenharmony_ci		combinedModule <<	"%vert_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
1564e5c31af7Sopenharmony_ci							"%vert_op_per_vertex_out = OpTypePointer Output %vert_per_vertex_out\n"
1565e5c31af7Sopenharmony_ci							"%vert_glPerVertex = OpVariable %vert_op_per_vertex_out Output\n";
1566e5c31af7Sopenharmony_ci	}
1567e5c31af7Sopenharmony_ci
1568e5c31af7Sopenharmony_ci	if (useGeometry)
1569e5c31af7Sopenharmony_ci	{
1570e5c31af7Sopenharmony_ci		combinedModule <<	"; Geometry Variables\n"
1571e5c31af7Sopenharmony_ci							"%geom_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
1572e5c31af7Sopenharmony_ci							"%geom_a3_per_vertex_in = OpTypeArray %geom_per_vertex_in %c_u32_3\n"
1573e5c31af7Sopenharmony_ci							"%geom_ip_a3_per_vertex_in = OpTypePointer Input %geom_a3_per_vertex_in\n"
1574e5c31af7Sopenharmony_ci							"%geom_gl_in = OpVariable %geom_ip_a3_per_vertex_in Input\n"
1575e5c31af7Sopenharmony_ci							"%geom_out_color = OpVariable %op_v4f32 Output\n"
1576e5c31af7Sopenharmony_ci							"%geom_in_color = OpVariable %ip_a3v4f32 Input\n"
1577e5c31af7Sopenharmony_ci							"%geom_out_gl_position = OpVariable %op_v4f32 Output\n";
1578e5c31af7Sopenharmony_ci	}
1579e5c31af7Sopenharmony_ci
1580e5c31af7Sopenharmony_ci	if (useTessellation)
1581e5c31af7Sopenharmony_ci	{
1582e5c31af7Sopenharmony_ci		combinedModule <<	"; Tessellation Control Variables\n"
1583e5c31af7Sopenharmony_ci							"%tessc_out_color = OpVariable %op_a3v4f32 Output\n"
1584e5c31af7Sopenharmony_ci							"%tessc_gl_InvocationID = OpVariable %ip_i32 Input\n"
1585e5c31af7Sopenharmony_ci							"%tessc_in_color = OpVariable %ip_a32v4f32 Input\n"
1586e5c31af7Sopenharmony_ci							"%tessc_out_position = OpVariable %op_a3v4f32 Output\n"
1587e5c31af7Sopenharmony_ci							"%tessc_in_position = OpVariable %ip_a32v4f32 Input\n"
1588e5c31af7Sopenharmony_ci							"%tessc_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
1589e5c31af7Sopenharmony_ci							"%tessc_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
1590e5c31af7Sopenharmony_ci
1591e5c31af7Sopenharmony_ci							"; Tessellation Evaluation Decorations\n"
1592e5c31af7Sopenharmony_ci							"%tesse_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
1593e5c31af7Sopenharmony_ci							"%tesse_op_per_vertex_out = OpTypePointer Output %tesse_per_vertex_out\n"
1594e5c31af7Sopenharmony_ci							"%tesse_stream = OpVariable %tesse_op_per_vertex_out Output\n"
1595e5c31af7Sopenharmony_ci							"%tesse_gl_tessCoord = OpVariable %ip_v3f32 Input\n"
1596e5c31af7Sopenharmony_ci							"%tesse_in_position = OpVariable %ip_a32v4f32 Input\n"
1597e5c31af7Sopenharmony_ci							"%tesse_out_color = OpVariable %op_v4f32 Output\n"
1598e5c31af7Sopenharmony_ci							"%tesse_in_color = OpVariable %ip_a32v4f32 Input\n";
1599e5c31af7Sopenharmony_ci	}
1600e5c31af7Sopenharmony_ci
1601e5c31af7Sopenharmony_ci	combinedModule	<<	"; Fragment Variables\n"
1602e5c31af7Sopenharmony_ci						"%frag_fragColor = OpVariable %op_v4f32 Output\n"
1603e5c31af7Sopenharmony_ci						"%frag_vtxColor = OpVariable %ip_v4f32 Input\n"
1604e5c31af7Sopenharmony_ci
1605e5c31af7Sopenharmony_ci						"; Vertex Entry\n"
1606e5c31af7Sopenharmony_ci						"%vert_main = OpFunction %void None %voidf\n"
1607e5c31af7Sopenharmony_ci						"%vert_label = OpLabel\n"
1608e5c31af7Sopenharmony_ci						"%vert_tmp_position = OpLoad %v4f32 %vert_Position\n";
1609e5c31af7Sopenharmony_ci
1610e5c31af7Sopenharmony_ci	if (useTessellation)
1611e5c31af7Sopenharmony_ci		combinedModule <<	"OpStore %vert_vtxPosition %vert_tmp_position\n";
1612e5c31af7Sopenharmony_ci	else
1613e5c31af7Sopenharmony_ci	{
1614e5c31af7Sopenharmony_ci		combinedModule <<	"%vert_out_pos_ptr = OpAccessChain %op_v4f32 %vert_glPerVertex %c_i32_0\n"
1615e5c31af7Sopenharmony_ci							"OpStore %vert_out_pos_ptr %vert_tmp_position\n";
1616e5c31af7Sopenharmony_ci	}
1617e5c31af7Sopenharmony_ci
1618e5c31af7Sopenharmony_ci	combinedModule <<	"%vert_tmp_color = OpLoad %v4f32 %vert_color\n"
1619e5c31af7Sopenharmony_ci						"OpStore %vert_vtxColor %vert_tmp_color\n"
1620e5c31af7Sopenharmony_ci						"OpReturn\n"
1621e5c31af7Sopenharmony_ci						"OpFunctionEnd\n";
1622e5c31af7Sopenharmony_ci
1623e5c31af7Sopenharmony_ci	if (useGeometry)
1624e5c31af7Sopenharmony_ci	{
1625e5c31af7Sopenharmony_ci		combinedModule <<	"; Geometry Entry\n"
1626e5c31af7Sopenharmony_ci							"%geom_main = OpFunction %void None %voidf\n"
1627e5c31af7Sopenharmony_ci							"%geom_label = OpLabel\n"
1628e5c31af7Sopenharmony_ci							"%geom_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_0 %c_i32_0\n"
1629e5c31af7Sopenharmony_ci							"%geom_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_1 %c_i32_0\n"
1630e5c31af7Sopenharmony_ci							"%geom_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_2 %c_i32_0\n"
1631e5c31af7Sopenharmony_ci							"%geom_in_position_0 = OpLoad %v4f32 %geom_gl_in_0_gl_position\n"
1632e5c31af7Sopenharmony_ci							"%geom_in_position_1 = OpLoad %v4f32 %geom_gl_in_1_gl_position\n"
1633e5c31af7Sopenharmony_ci							"%geom_in_position_2 = OpLoad %v4f32 %geom_gl_in_2_gl_position \n"
1634e5c31af7Sopenharmony_ci							"%geom_in_color_0_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_0\n"
1635e5c31af7Sopenharmony_ci							"%geom_in_color_1_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_1\n"
1636e5c31af7Sopenharmony_ci							"%geom_in_color_2_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_2\n"
1637e5c31af7Sopenharmony_ci							"%geom_in_color_0 = OpLoad %v4f32 %geom_in_color_0_ptr\n"
1638e5c31af7Sopenharmony_ci							"%geom_in_color_1 = OpLoad %v4f32 %geom_in_color_1_ptr\n"
1639e5c31af7Sopenharmony_ci							"%geom_in_color_2 = OpLoad %v4f32 %geom_in_color_2_ptr\n"
1640e5c31af7Sopenharmony_ci							"OpStore %geom_out_gl_position %geom_in_position_0\n"
1641e5c31af7Sopenharmony_ci							"OpStore %geom_out_color %geom_in_color_0\n"
1642e5c31af7Sopenharmony_ci							"OpEmitVertex\n"
1643e5c31af7Sopenharmony_ci							"OpStore %geom_out_gl_position %geom_in_position_1\n"
1644e5c31af7Sopenharmony_ci							"OpStore %geom_out_color %geom_in_color_1\n"
1645e5c31af7Sopenharmony_ci							"OpEmitVertex\n"
1646e5c31af7Sopenharmony_ci							"OpStore %geom_out_gl_position %geom_in_position_2\n"
1647e5c31af7Sopenharmony_ci							"OpStore %geom_out_color %geom_in_color_2\n"
1648e5c31af7Sopenharmony_ci							"OpEmitVertex\n"
1649e5c31af7Sopenharmony_ci							"OpEndPrimitive\n"
1650e5c31af7Sopenharmony_ci							"OpReturn\n"
1651e5c31af7Sopenharmony_ci							"OpFunctionEnd\n";
1652e5c31af7Sopenharmony_ci	}
1653e5c31af7Sopenharmony_ci
1654e5c31af7Sopenharmony_ci	if (useTessellation)
1655e5c31af7Sopenharmony_ci	{
1656e5c31af7Sopenharmony_ci		combinedModule <<	"; Tessellation Control Entry\n"
1657e5c31af7Sopenharmony_ci							"%tessc_main = OpFunction %void None %voidf\n"
1658e5c31af7Sopenharmony_ci							"%tessc_label = OpLabel\n"
1659e5c31af7Sopenharmony_ci							"%tessc_invocation_id = OpLoad %i32 %tessc_gl_InvocationID\n"
1660e5c31af7Sopenharmony_ci							"%tessc_in_color_ptr = OpAccessChain %ip_v4f32 %tessc_in_color %tessc_invocation_id\n"
1661e5c31af7Sopenharmony_ci							"%tessc_in_position_ptr = OpAccessChain %ip_v4f32 %tessc_in_position %tessc_invocation_id\n"
1662e5c31af7Sopenharmony_ci							"%tessc_in_color_val = OpLoad %v4f32 %tessc_in_color_ptr\n"
1663e5c31af7Sopenharmony_ci							"%tessc_in_position_val = OpLoad %v4f32 %tessc_in_position_ptr\n"
1664e5c31af7Sopenharmony_ci							"%tessc_out_color_ptr = OpAccessChain %op_v4f32 %tessc_out_color %tessc_invocation_id\n"
1665e5c31af7Sopenharmony_ci							"%tessc_out_position_ptr = OpAccessChain %op_v4f32 %tessc_out_position %tessc_invocation_id\n"
1666e5c31af7Sopenharmony_ci							"OpStore %tessc_out_color_ptr %tessc_in_color_val\n"
1667e5c31af7Sopenharmony_ci							"OpStore %tessc_out_position_ptr %tessc_in_position_val\n"
1668e5c31af7Sopenharmony_ci							"%tessc_is_first_invocation = OpIEqual %bool %tessc_invocation_id %c_i32_0\n"
1669e5c31af7Sopenharmony_ci							"OpSelectionMerge %tessc_merge_label None\n"
1670e5c31af7Sopenharmony_ci							"OpBranchConditional %tessc_is_first_invocation %tessc_first_invocation %tessc_merge_label\n"
1671e5c31af7Sopenharmony_ci							"%tessc_first_invocation = OpLabel\n"
1672e5c31af7Sopenharmony_ci							"%tessc_tess_outer_0 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_0\n"
1673e5c31af7Sopenharmony_ci							"%tessc_tess_outer_1 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_1\n"
1674e5c31af7Sopenharmony_ci							"%tessc_tess_outer_2 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_2\n"
1675e5c31af7Sopenharmony_ci							"%tessc_tess_inner = OpAccessChain %op_f32 %tessc_gl_TessLevelInner %c_i32_0\n"
1676e5c31af7Sopenharmony_ci							"OpStore %tessc_tess_outer_0 %c_f32_1\n"
1677e5c31af7Sopenharmony_ci							"OpStore %tessc_tess_outer_1 %c_f32_1\n"
1678e5c31af7Sopenharmony_ci							"OpStore %tessc_tess_outer_2 %c_f32_1\n"
1679e5c31af7Sopenharmony_ci							"OpStore %tessc_tess_inner %c_f32_1\n"
1680e5c31af7Sopenharmony_ci							"OpBranch %tessc_merge_label\n"
1681e5c31af7Sopenharmony_ci							"%tessc_merge_label = OpLabel\n"
1682e5c31af7Sopenharmony_ci							"OpReturn\n"
1683e5c31af7Sopenharmony_ci							"OpFunctionEnd\n"
1684e5c31af7Sopenharmony_ci
1685e5c31af7Sopenharmony_ci							"; Tessellation Evaluation Entry\n"
1686e5c31af7Sopenharmony_ci							"%tesse_main = OpFunction %void None %voidf\n"
1687e5c31af7Sopenharmony_ci							"%tesse_label = OpLabel\n"
1688e5c31af7Sopenharmony_ci							"%tesse_tc_0_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_0\n"
1689e5c31af7Sopenharmony_ci							"%tesse_tc_1_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_1\n"
1690e5c31af7Sopenharmony_ci							"%tesse_tc_2_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_2\n"
1691e5c31af7Sopenharmony_ci							"%tesse_tc_0 = OpLoad %f32 %tesse_tc_0_ptr\n"
1692e5c31af7Sopenharmony_ci							"%tesse_tc_1 = OpLoad %f32 %tesse_tc_1_ptr\n"
1693e5c31af7Sopenharmony_ci							"%tesse_tc_2 = OpLoad %f32 %tesse_tc_2_ptr\n"
1694e5c31af7Sopenharmony_ci							"%tesse_in_pos_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_0\n"
1695e5c31af7Sopenharmony_ci							"%tesse_in_pos_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_1\n"
1696e5c31af7Sopenharmony_ci							"%tesse_in_pos_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_2\n"
1697e5c31af7Sopenharmony_ci							"%tesse_in_pos_0 = OpLoad %v4f32 %tesse_in_pos_0_ptr\n"
1698e5c31af7Sopenharmony_ci							"%tesse_in_pos_1 = OpLoad %v4f32 %tesse_in_pos_1_ptr\n"
1699e5c31af7Sopenharmony_ci							"%tesse_in_pos_2 = OpLoad %v4f32 %tesse_in_pos_2_ptr\n"
1700e5c31af7Sopenharmony_ci							"%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_0 %tesse_tc_0\n"
1701e5c31af7Sopenharmony_ci							"%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_1 %tesse_tc_1\n"
1702e5c31af7Sopenharmony_ci							"%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_2 %tesse_tc_2\n"
1703e5c31af7Sopenharmony_ci							"%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n"
1704e5c31af7Sopenharmony_ci							"%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n"
1705e5c31af7Sopenharmony_ci							"%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n"
1706e5c31af7Sopenharmony_ci							"OpStore %tesse_out_pos_ptr %tesse_computed_out\n"
1707e5c31af7Sopenharmony_ci							"%tesse_in_clr_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_0\n"
1708e5c31af7Sopenharmony_ci							"%tesse_in_clr_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_1\n"
1709e5c31af7Sopenharmony_ci							"%tesse_in_clr_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_2\n"
1710e5c31af7Sopenharmony_ci							"%tesse_in_clr_0 = OpLoad %v4f32 %tesse_in_clr_0_ptr\n"
1711e5c31af7Sopenharmony_ci							"%tesse_in_clr_1 = OpLoad %v4f32 %tesse_in_clr_1_ptr\n"
1712e5c31af7Sopenharmony_ci							"%tesse_in_clr_2 = OpLoad %v4f32 %tesse_in_clr_2_ptr\n"
1713e5c31af7Sopenharmony_ci							"%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_0 %tesse_tc_0\n"
1714e5c31af7Sopenharmony_ci							"%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_1 %tesse_tc_1\n"
1715e5c31af7Sopenharmony_ci							"%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_2 %tesse_tc_2\n"
1716e5c31af7Sopenharmony_ci							"%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n"
1717e5c31af7Sopenharmony_ci							"%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n"
1718e5c31af7Sopenharmony_ci							"OpStore %tesse_out_color %tesse_computed_clr\n"
1719e5c31af7Sopenharmony_ci							"OpReturn\n"
1720e5c31af7Sopenharmony_ci							"OpFunctionEnd\n";
1721e5c31af7Sopenharmony_ci	}
1722e5c31af7Sopenharmony_ci
1723e5c31af7Sopenharmony_ci	combinedModule	<<	"; Fragment Entry\n"
1724e5c31af7Sopenharmony_ci						"%frag_main = OpFunction %void None %voidf\n"
1725e5c31af7Sopenharmony_ci						"%frag_label_main = OpLabel\n"
1726e5c31af7Sopenharmony_ci						"%frag_tmp1 = OpLoad %v4f32 %frag_vtxColor\n"
1727e5c31af7Sopenharmony_ci						"OpStore %frag_fragColor %frag_tmp1\n"
1728e5c31af7Sopenharmony_ci						"OpReturn\n"
1729e5c31af7Sopenharmony_ci						"OpFunctionEnd\n";
1730e5c31af7Sopenharmony_ci
1731e5c31af7Sopenharmony_ci	dst.spirvAsmSources.add("module") << combinedModule.str();
1732e5c31af7Sopenharmony_ci}
1733e5c31af7Sopenharmony_ci
1734e5c31af7Sopenharmony_civoid createUnusedVariableModules (vk::SourceCollections& dst, UnusedVariableContext ctx)
1735e5c31af7Sopenharmony_ci{
1736e5c31af7Sopenharmony_ci	if (ctx.shaderTasks[SHADER_TASK_INDEX_VERTEX] != SHADER_TASK_NONE)
1737e5c31af7Sopenharmony_ci	{
1738e5c31af7Sopenharmony_ci		std::ostringstream	shader;
1739e5c31af7Sopenharmony_ci		bool				tessellation = (ctx.shaderTasks[SHADER_TASK_INDEX_TESS_CONTROL] != SHADER_TASK_NONE
1740e5c31af7Sopenharmony_ci											|| ctx.shaderTasks[SHADER_TASK_INDEX_TESS_EVAL] != SHADER_TASK_NONE);
1741e5c31af7Sopenharmony_ci		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_VERTEX];
1742e5c31af7Sopenharmony_ci
1743e5c31af7Sopenharmony_ci		shader	<< "OpCapability Shader\n"
1744e5c31af7Sopenharmony_ci				<< "OpMemoryModel Logical GLSL450\n";
1745e5c31af7Sopenharmony_ci
1746e5c31af7Sopenharmony_ci		// Entry point depends on if tessellation is enabled or not to provide the vertex position.
1747e5c31af7Sopenharmony_ci		shader	<< "OpEntryPoint Vertex %main \"main\" %Position %vtxColor %color "
1748e5c31af7Sopenharmony_ci				<< (tessellation ? "%vtxPosition" : "%vtx_glPerVertex")
1749e5c31af7Sopenharmony_ci				<< " %vertex_id %instance_id\n";
1750e5c31af7Sopenharmony_ci		if (task == SHADER_TASK_UNUSED_FUNC)
1751e5c31af7Sopenharmony_ci		{
1752e5c31af7Sopenharmony_ci			shader << getUnusedEntryPoint();
1753e5c31af7Sopenharmony_ci		}
1754e5c31af7Sopenharmony_ci
1755e5c31af7Sopenharmony_ci		// Decorations.
1756e5c31af7Sopenharmony_ci		shader	<< "OpDecorate %Position Location 0\n"
1757e5c31af7Sopenharmony_ci				<< "OpDecorate %vtxColor Location 1\n"
1758e5c31af7Sopenharmony_ci				<< "OpDecorate %color Location 1\n"
1759e5c31af7Sopenharmony_ci				<< "OpDecorate %vertex_id BuiltIn VertexIndex\n"
1760e5c31af7Sopenharmony_ci				<< "OpDecorate %instance_id BuiltIn InstanceIndex\n";
1761e5c31af7Sopenharmony_ci		if (tessellation)
1762e5c31af7Sopenharmony_ci		{
1763e5c31af7Sopenharmony_ci			shader	<< "OpDecorate %vtxPosition Location 2\n";
1764e5c31af7Sopenharmony_ci		}
1765e5c31af7Sopenharmony_ci		else
1766e5c31af7Sopenharmony_ci		{
1767e5c31af7Sopenharmony_ci			shader	<< "OpMemberDecorate %vert_per_vertex_out 0 BuiltIn Position\n"
1768e5c31af7Sopenharmony_ci					<< "OpMemberDecorate %vert_per_vertex_out 1 BuiltIn PointSize\n"
1769e5c31af7Sopenharmony_ci					<< "OpMemberDecorate %vert_per_vertex_out 2 BuiltIn ClipDistance\n"
1770e5c31af7Sopenharmony_ci					<< "OpMemberDecorate %vert_per_vertex_out 3 BuiltIn CullDistance\n"
1771e5c31af7Sopenharmony_ci					<< "OpDecorate %vert_per_vertex_out Block\n";
1772e5c31af7Sopenharmony_ci		}
1773e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
1774e5c31af7Sopenharmony_ci		{
1775e5c31af7Sopenharmony_ci			shader	<< getUnusedDecorations(ctx.variableLocation);
1776e5c31af7Sopenharmony_ci		}
1777e5c31af7Sopenharmony_ci
1778e5c31af7Sopenharmony_ci		// Standard types, constants and arrays.
1779e5c31af7Sopenharmony_ci		shader	<< "; Start of standard types, constants and arrays\n"
1780e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_TYPES
1781e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_CONSTANTS
1782e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_ARRAYS
1783e5c31af7Sopenharmony_ci				<< "; End of standard types, constants and arrays\n";
1784e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
1785e5c31af7Sopenharmony_ci		{
1786e5c31af7Sopenharmony_ci			shader	<< getUnusedTypesAndConstants();
1787e5c31af7Sopenharmony_ci		}
1788e5c31af7Sopenharmony_ci
1789e5c31af7Sopenharmony_ci		// Variables.
1790e5c31af7Sopenharmony_ci		if (tessellation)
1791e5c31af7Sopenharmony_ci		{
1792e5c31af7Sopenharmony_ci			shader	<< "%vtxPosition = OpVariable %op_v4f32 Output\n";
1793e5c31af7Sopenharmony_ci		}
1794e5c31af7Sopenharmony_ci		else
1795e5c31af7Sopenharmony_ci		{
1796e5c31af7Sopenharmony_ci			shader	<< "%vert_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
1797e5c31af7Sopenharmony_ci					<< "%vert_op_per_vertex_out = OpTypePointer Output %vert_per_vertex_out\n"
1798e5c31af7Sopenharmony_ci					<< "%vtx_glPerVertex = OpVariable %vert_op_per_vertex_out Output\n";
1799e5c31af7Sopenharmony_ci		}
1800e5c31af7Sopenharmony_ci		shader	<< "%Position = OpVariable %ip_v4f32 Input\n"
1801e5c31af7Sopenharmony_ci				<< "%vtxColor = OpVariable %op_v4f32 Output\n"
1802e5c31af7Sopenharmony_ci				<< "%color = OpVariable %ip_v4f32 Input\n"
1803e5c31af7Sopenharmony_ci				<< "%vertex_id = OpVariable %ip_i32 Input\n"
1804e5c31af7Sopenharmony_ci				<< "%instance_id = OpVariable %ip_i32 Input\n";
1805e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
1806e5c31af7Sopenharmony_ci		{
1807e5c31af7Sopenharmony_ci			shader	<< getUnusedBuffer();
1808e5c31af7Sopenharmony_ci		}
1809e5c31af7Sopenharmony_ci
1810e5c31af7Sopenharmony_ci		// Vertex main function.
1811e5c31af7Sopenharmony_ci		shader	<< "%main = OpFunction %void None %voidf\n"
1812e5c31af7Sopenharmony_ci				<< "%label = OpLabel\n"
1813e5c31af7Sopenharmony_ci				<< "%tmp_position = OpLoad %v4f32 %Position\n";
1814e5c31af7Sopenharmony_ci		if (tessellation)
1815e5c31af7Sopenharmony_ci		{
1816e5c31af7Sopenharmony_ci			shader	<< "OpStore %vtxPosition %tmp_position\n";
1817e5c31af7Sopenharmony_ci		}
1818e5c31af7Sopenharmony_ci		else
1819e5c31af7Sopenharmony_ci		{
1820e5c31af7Sopenharmony_ci			shader	<< "%vert_out_pos_ptr = OpAccessChain %op_v4f32 %vtx_glPerVertex %c_i32_0\n"
1821e5c31af7Sopenharmony_ci					<< "OpStore %vert_out_pos_ptr %tmp_position\n";
1822e5c31af7Sopenharmony_ci		}
1823e5c31af7Sopenharmony_ci		shader	<< "%tmp_color = OpLoad %v4f32 %color\n"
1824e5c31af7Sopenharmony_ci				<< "OpStore %vtxColor %tmp_color\n"
1825e5c31af7Sopenharmony_ci				<< "OpReturn\n"
1826e5c31af7Sopenharmony_ci				<< "OpFunctionEnd\n";
1827e5c31af7Sopenharmony_ci		if (task == SHADER_TASK_UNUSED_FUNC)
1828e5c31af7Sopenharmony_ci		{
1829e5c31af7Sopenharmony_ci			shader	<< getUnusedFunctionBody();
1830e5c31af7Sopenharmony_ci		}
1831e5c31af7Sopenharmony_ci
1832e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("vert") << shader.str();
1833e5c31af7Sopenharmony_ci	}
1834e5c31af7Sopenharmony_ci
1835e5c31af7Sopenharmony_ci	if (ctx.shaderTasks[SHADER_TASK_INDEX_GEOMETRY] != SHADER_TASK_NONE)
1836e5c31af7Sopenharmony_ci	{
1837e5c31af7Sopenharmony_ci		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_GEOMETRY];
1838e5c31af7Sopenharmony_ci		std::ostringstream	shader;
1839e5c31af7Sopenharmony_ci
1840e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
1841e5c31af7Sopenharmony_ci		{
1842e5c31af7Sopenharmony_ci			shader << getOpCapabilityShader();
1843e5c31af7Sopenharmony_ci		}
1844e5c31af7Sopenharmony_ci		shader	<< "OpCapability Geometry\n"
1845e5c31af7Sopenharmony_ci				<< "OpMemoryModel Logical GLSL450\n";
1846e5c31af7Sopenharmony_ci
1847e5c31af7Sopenharmony_ci		// Entry points.
1848e5c31af7Sopenharmony_ci		shader	<< "OpEntryPoint Geometry %geom1_main \"main\" %out_gl_position %gl_in %out_color %in_color\n";
1849e5c31af7Sopenharmony_ci		if (task == SHADER_TASK_UNUSED_FUNC)
1850e5c31af7Sopenharmony_ci		{
1851e5c31af7Sopenharmony_ci			shader	<< getUnusedEntryPoint();
1852e5c31af7Sopenharmony_ci		}
1853e5c31af7Sopenharmony_ci		shader	<< "OpExecutionMode %geom1_main Triangles\n"
1854e5c31af7Sopenharmony_ci				<< "OpExecutionMode %geom1_main OutputTriangleStrip\n"
1855e5c31af7Sopenharmony_ci				<< "OpExecutionMode %geom1_main OutputVertices 3\n"
1856e5c31af7Sopenharmony_ci				<< "OpExecutionMode %geom1_main Invocations 1\n";
1857e5c31af7Sopenharmony_ci
1858e5c31af7Sopenharmony_ci		// Decorations.
1859e5c31af7Sopenharmony_ci		shader	<< "OpDecorate %out_gl_position BuiltIn Position\n"
1860e5c31af7Sopenharmony_ci				<< "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n"
1861e5c31af7Sopenharmony_ci				<< "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n"
1862e5c31af7Sopenharmony_ci				<< "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n"
1863e5c31af7Sopenharmony_ci				<< "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n"
1864e5c31af7Sopenharmony_ci				<< "OpDecorate %per_vertex_in Block\n"
1865e5c31af7Sopenharmony_ci				<< "OpDecorate %out_color Location 1\n"
1866e5c31af7Sopenharmony_ci				<< "OpDecorate %in_color Location 1\n";
1867e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
1868e5c31af7Sopenharmony_ci		{
1869e5c31af7Sopenharmony_ci			shader	<< getUnusedDecorations(ctx.variableLocation);
1870e5c31af7Sopenharmony_ci		}
1871e5c31af7Sopenharmony_ci
1872e5c31af7Sopenharmony_ci		// Standard types, constants and arrays.
1873e5c31af7Sopenharmony_ci		shader	<< "; Start of standard types, constants and arrays\n"
1874e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_TYPES
1875e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_CONSTANTS
1876e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_ARRAYS
1877e5c31af7Sopenharmony_ci				<< "; End of standard types, constants and arrays\n";
1878e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
1879e5c31af7Sopenharmony_ci		{
1880e5c31af7Sopenharmony_ci			shader	<< getUnusedTypesAndConstants();
1881e5c31af7Sopenharmony_ci		}
1882e5c31af7Sopenharmony_ci
1883e5c31af7Sopenharmony_ci		// Variables.
1884e5c31af7Sopenharmony_ci		shader	<< "%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
1885e5c31af7Sopenharmony_ci				<< "%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n"
1886e5c31af7Sopenharmony_ci				<< "%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n"
1887e5c31af7Sopenharmony_ci				<< "%gl_in = OpVariable %ip_a3_per_vertex_in Input\n"
1888e5c31af7Sopenharmony_ci				<< "%out_color = OpVariable %op_v4f32 Output\n"
1889e5c31af7Sopenharmony_ci				<< "%in_color = OpVariable %ip_a3v4f32 Input\n"
1890e5c31af7Sopenharmony_ci				<< "%out_gl_position = OpVariable %op_v4f32 Output\n";
1891e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
1892e5c31af7Sopenharmony_ci		{
1893e5c31af7Sopenharmony_ci			shader << getUnusedBuffer();
1894e5c31af7Sopenharmony_ci		}
1895e5c31af7Sopenharmony_ci
1896e5c31af7Sopenharmony_ci		// Main function.
1897e5c31af7Sopenharmony_ci		shader	<< "%geom1_main = OpFunction %void None %voidf\n"
1898e5c31af7Sopenharmony_ci				<< "%geom1_label = OpLabel\n"
1899e5c31af7Sopenharmony_ci				<< "%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
1900e5c31af7Sopenharmony_ci				<< "%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
1901e5c31af7Sopenharmony_ci				<< "%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
1902e5c31af7Sopenharmony_ci				<< "%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n"
1903e5c31af7Sopenharmony_ci				<< "%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n"
1904e5c31af7Sopenharmony_ci				<< "%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n"
1905e5c31af7Sopenharmony_ci				<< "%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
1906e5c31af7Sopenharmony_ci				<< "%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
1907e5c31af7Sopenharmony_ci				<< "%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
1908e5c31af7Sopenharmony_ci				<< "%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n"
1909e5c31af7Sopenharmony_ci				<< "%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n"
1910e5c31af7Sopenharmony_ci				<< "%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n"
1911e5c31af7Sopenharmony_ci				<< "OpStore %out_gl_position %geom1_in_position_0\n"
1912e5c31af7Sopenharmony_ci				<< "OpStore %out_color %geom1_in_color_0\n"
1913e5c31af7Sopenharmony_ci				<< "OpEmitVertex\n"
1914e5c31af7Sopenharmony_ci				<< "OpStore %out_gl_position %geom1_in_position_1\n"
1915e5c31af7Sopenharmony_ci				<< "OpStore %out_color %geom1_in_color_1\n"
1916e5c31af7Sopenharmony_ci				<< "OpEmitVertex\n"
1917e5c31af7Sopenharmony_ci				<< "OpStore %out_gl_position %geom1_in_position_2\n"
1918e5c31af7Sopenharmony_ci				<< "OpStore %out_color %geom1_in_color_2\n"
1919e5c31af7Sopenharmony_ci				<< "OpEmitVertex\n"
1920e5c31af7Sopenharmony_ci				<< "OpEndPrimitive\n"
1921e5c31af7Sopenharmony_ci				<< "OpReturn\n"
1922e5c31af7Sopenharmony_ci				<< "OpFunctionEnd\n";
1923e5c31af7Sopenharmony_ci		if (task == SHADER_TASK_UNUSED_FUNC)
1924e5c31af7Sopenharmony_ci		{
1925e5c31af7Sopenharmony_ci			shader	<< getUnusedFunctionBody();
1926e5c31af7Sopenharmony_ci		}
1927e5c31af7Sopenharmony_ci
1928e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("geom") << shader.str();
1929e5c31af7Sopenharmony_ci	}
1930e5c31af7Sopenharmony_ci
1931e5c31af7Sopenharmony_ci	if (ctx.shaderTasks[SHADER_TASK_INDEX_TESS_CONTROL]	!= SHADER_TASK_NONE)
1932e5c31af7Sopenharmony_ci	{
1933e5c31af7Sopenharmony_ci		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_TESS_CONTROL];
1934e5c31af7Sopenharmony_ci		std::ostringstream	shader;
1935e5c31af7Sopenharmony_ci
1936e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
1937e5c31af7Sopenharmony_ci		{
1938e5c31af7Sopenharmony_ci			shader	<< getOpCapabilityShader();
1939e5c31af7Sopenharmony_ci		}
1940e5c31af7Sopenharmony_ci		shader	<< "OpCapability Tessellation\n"
1941e5c31af7Sopenharmony_ci				<< "OpMemoryModel Logical GLSL450\n";
1942e5c31af7Sopenharmony_ci
1943e5c31af7Sopenharmony_ci		// Entry point.
1944e5c31af7Sopenharmony_ci		shader	<< "OpEntryPoint TessellationControl %tessc1_main \"main\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n";
1945e5c31af7Sopenharmony_ci		if (task == SHADER_TASK_UNUSED_FUNC)
1946e5c31af7Sopenharmony_ci		{
1947e5c31af7Sopenharmony_ci			shader	<< getUnusedEntryPoint();
1948e5c31af7Sopenharmony_ci		}
1949e5c31af7Sopenharmony_ci		shader	<< "OpExecutionMode %tessc1_main OutputVertices 3\n";
1950e5c31af7Sopenharmony_ci
1951e5c31af7Sopenharmony_ci		// Decorations.
1952e5c31af7Sopenharmony_ci		shader	<< "OpDecorate %out_color Location 1\n"
1953e5c31af7Sopenharmony_ci				<< "OpDecorate %gl_InvocationID BuiltIn InvocationId\n"
1954e5c31af7Sopenharmony_ci				<< "OpDecorate %in_color Location 1\n"
1955e5c31af7Sopenharmony_ci				<< "OpDecorate %out_position Location 2\n"
1956e5c31af7Sopenharmony_ci				<< "OpDecorate %in_position Location 2\n"
1957e5c31af7Sopenharmony_ci				<< "OpDecorate %gl_TessLevelOuter Patch\n"
1958e5c31af7Sopenharmony_ci				<< "OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n"
1959e5c31af7Sopenharmony_ci				<< "OpDecorate %gl_TessLevelInner Patch\n"
1960e5c31af7Sopenharmony_ci				<< "OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n";
1961e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
1962e5c31af7Sopenharmony_ci		{
1963e5c31af7Sopenharmony_ci			shader	<< getUnusedDecorations(ctx.variableLocation);
1964e5c31af7Sopenharmony_ci		}
1965e5c31af7Sopenharmony_ci
1966e5c31af7Sopenharmony_ci		// Standard types, constants and arrays.
1967e5c31af7Sopenharmony_ci		shader	<< "; Start of standard types, constants and arrays\n"
1968e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_TYPES
1969e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_CONSTANTS
1970e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_ARRAYS
1971e5c31af7Sopenharmony_ci				<< "; End of standard types, constants and arrays\n";
1972e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
1973e5c31af7Sopenharmony_ci		{
1974e5c31af7Sopenharmony_ci			shader	<< getUnusedTypesAndConstants();
1975e5c31af7Sopenharmony_ci		}
1976e5c31af7Sopenharmony_ci
1977e5c31af7Sopenharmony_ci		// Variables.
1978e5c31af7Sopenharmony_ci		shader	<< "%out_color = OpVariable %op_a3v4f32 Output\n"
1979e5c31af7Sopenharmony_ci				<< "%gl_InvocationID = OpVariable %ip_i32 Input\n"
1980e5c31af7Sopenharmony_ci				<< "%in_color = OpVariable %ip_a32v4f32 Input\n"
1981e5c31af7Sopenharmony_ci				<< "%out_position = OpVariable %op_a3v4f32 Output\n"
1982e5c31af7Sopenharmony_ci				<< "%in_position = OpVariable %ip_a32v4f32 Input\n"
1983e5c31af7Sopenharmony_ci				<< "%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
1984e5c31af7Sopenharmony_ci				<< "%gl_TessLevelInner = OpVariable %op_a2f32 Output\n";
1985e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
1986e5c31af7Sopenharmony_ci		{
1987e5c31af7Sopenharmony_ci			shader << getUnusedBuffer();
1988e5c31af7Sopenharmony_ci		}
1989e5c31af7Sopenharmony_ci
1990e5c31af7Sopenharmony_ci		// Main entry point.
1991e5c31af7Sopenharmony_ci		shader	<< "%tessc1_main = OpFunction %void None %voidf\n"
1992e5c31af7Sopenharmony_ci				<< "%tessc1_label = OpLabel\n"
1993e5c31af7Sopenharmony_ci				<< "%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n"
1994e5c31af7Sopenharmony_ci				<< "%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n"
1995e5c31af7Sopenharmony_ci				<< "%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n"
1996e5c31af7Sopenharmony_ci				<< "%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n"
1997e5c31af7Sopenharmony_ci				<< "%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n"
1998e5c31af7Sopenharmony_ci				<< "%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n"
1999e5c31af7Sopenharmony_ci				<< "%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n"
2000e5c31af7Sopenharmony_ci				<< "OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n"
2001e5c31af7Sopenharmony_ci				<< "OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n"
2002e5c31af7Sopenharmony_ci				<< "%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n"
2003e5c31af7Sopenharmony_ci				<< "OpSelectionMerge %tessc1_merge_label None\n"
2004e5c31af7Sopenharmony_ci				<< "OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n"
2005e5c31af7Sopenharmony_ci				<< "%tessc1_first_invocation = OpLabel\n"
2006e5c31af7Sopenharmony_ci				<< "%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
2007e5c31af7Sopenharmony_ci				<< "%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
2008e5c31af7Sopenharmony_ci				<< "%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
2009e5c31af7Sopenharmony_ci				<< "%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n"
2010e5c31af7Sopenharmony_ci				<< "OpStore %tessc1_tess_outer_0 %c_f32_1\n"
2011e5c31af7Sopenharmony_ci				<< "OpStore %tessc1_tess_outer_1 %c_f32_1\n"
2012e5c31af7Sopenharmony_ci				<< "OpStore %tessc1_tess_outer_2 %c_f32_1\n"
2013e5c31af7Sopenharmony_ci				<< "OpStore %tessc1_tess_inner %c_f32_1\n"
2014e5c31af7Sopenharmony_ci				<< "OpBranch %tessc1_merge_label\n"
2015e5c31af7Sopenharmony_ci				<< "%tessc1_merge_label = OpLabel\n"
2016e5c31af7Sopenharmony_ci				<< "OpReturn\n"
2017e5c31af7Sopenharmony_ci				<< "OpFunctionEnd\n";
2018e5c31af7Sopenharmony_ci		if (task == SHADER_TASK_UNUSED_FUNC)
2019e5c31af7Sopenharmony_ci		{
2020e5c31af7Sopenharmony_ci			shader	<< getUnusedFunctionBody();
2021e5c31af7Sopenharmony_ci		}
2022e5c31af7Sopenharmony_ci
2023e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("tessc") << shader.str();
2024e5c31af7Sopenharmony_ci	}
2025e5c31af7Sopenharmony_ci
2026e5c31af7Sopenharmony_ci	if (ctx.shaderTasks[SHADER_TASK_INDEX_TESS_EVAL] != SHADER_TASK_NONE)
2027e5c31af7Sopenharmony_ci	{
2028e5c31af7Sopenharmony_ci		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_TESS_EVAL];
2029e5c31af7Sopenharmony_ci		std::ostringstream	shader;
2030e5c31af7Sopenharmony_ci
2031e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
2032e5c31af7Sopenharmony_ci		{
2033e5c31af7Sopenharmony_ci			shader	<< getOpCapabilityShader();
2034e5c31af7Sopenharmony_ci		}
2035e5c31af7Sopenharmony_ci		shader	<< "OpCapability Tessellation\n"
2036e5c31af7Sopenharmony_ci				<< "OpMemoryModel Logical GLSL450\n";
2037e5c31af7Sopenharmony_ci
2038e5c31af7Sopenharmony_ci		// Entry point.
2039e5c31af7Sopenharmony_ci		shader	<< "OpEntryPoint TessellationEvaluation %tesse1_main \"main\" %stream %gl_tessCoord %in_position %out_color %in_color \n";
2040e5c31af7Sopenharmony_ci		if (task == SHADER_TASK_UNUSED_FUNC)
2041e5c31af7Sopenharmony_ci		{
2042e5c31af7Sopenharmony_ci			shader	<< getUnusedEntryPoint();
2043e5c31af7Sopenharmony_ci		}
2044e5c31af7Sopenharmony_ci		shader	<< "OpExecutionMode %tesse1_main Triangles\n"
2045e5c31af7Sopenharmony_ci				<< "OpExecutionMode %tesse1_main SpacingEqual\n"
2046e5c31af7Sopenharmony_ci				<< "OpExecutionMode %tesse1_main VertexOrderCcw\n";
2047e5c31af7Sopenharmony_ci
2048e5c31af7Sopenharmony_ci		// Decorations.
2049e5c31af7Sopenharmony_ci		shader	<< "OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n"
2050e5c31af7Sopenharmony_ci				<< "OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n"
2051e5c31af7Sopenharmony_ci				<< "OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n"
2052e5c31af7Sopenharmony_ci				<< "OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n"
2053e5c31af7Sopenharmony_ci				<< "OpDecorate %per_vertex_out Block\n"
2054e5c31af7Sopenharmony_ci				<< "OpDecorate %gl_tessCoord BuiltIn TessCoord\n"
2055e5c31af7Sopenharmony_ci				<< "OpDecorate %in_position Location 2\n"
2056e5c31af7Sopenharmony_ci				<< "OpDecorate %out_color Location 1\n"
2057e5c31af7Sopenharmony_ci				<< "OpDecorate %in_color Location 1\n";
2058e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
2059e5c31af7Sopenharmony_ci		{
2060e5c31af7Sopenharmony_ci			shader	<< getUnusedDecorations(ctx.variableLocation);
2061e5c31af7Sopenharmony_ci		}
2062e5c31af7Sopenharmony_ci
2063e5c31af7Sopenharmony_ci		// Standard types, constants and arrays.
2064e5c31af7Sopenharmony_ci		shader	<< "; Start of standard types, constants and arrays\n"
2065e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_TYPES
2066e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_CONSTANTS
2067e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_ARRAYS
2068e5c31af7Sopenharmony_ci				<< "; End of standard types, constants and arrays\n";
2069e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
2070e5c31af7Sopenharmony_ci		{
2071e5c31af7Sopenharmony_ci			shader	<< getUnusedTypesAndConstants();
2072e5c31af7Sopenharmony_ci		}
2073e5c31af7Sopenharmony_ci
2074e5c31af7Sopenharmony_ci		// Variables.
2075e5c31af7Sopenharmony_ci		shader	<< "%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2076e5c31af7Sopenharmony_ci				<< "%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n"
2077e5c31af7Sopenharmony_ci				<< "%stream = OpVariable %op_per_vertex_out Output\n"
2078e5c31af7Sopenharmony_ci				<< "%gl_tessCoord = OpVariable %ip_v3f32 Input\n"
2079e5c31af7Sopenharmony_ci				<< "%in_position = OpVariable %ip_a32v4f32 Input\n"
2080e5c31af7Sopenharmony_ci				<< "%out_color = OpVariable %op_v4f32 Output\n"
2081e5c31af7Sopenharmony_ci				<< "%in_color = OpVariable %ip_a32v4f32 Input\n";
2082e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
2083e5c31af7Sopenharmony_ci		{
2084e5c31af7Sopenharmony_ci			shader << getUnusedBuffer();
2085e5c31af7Sopenharmony_ci		}
2086e5c31af7Sopenharmony_ci
2087e5c31af7Sopenharmony_ci		// Main entry point.
2088e5c31af7Sopenharmony_ci		shader	<< "%tesse1_main = OpFunction %void None %voidf\n"
2089e5c31af7Sopenharmony_ci				<< "%tesse1_label = OpLabel\n"
2090e5c31af7Sopenharmony_ci				<< "%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
2091e5c31af7Sopenharmony_ci				<< "%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
2092e5c31af7Sopenharmony_ci				<< "%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
2093e5c31af7Sopenharmony_ci				<< "%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n"
2094e5c31af7Sopenharmony_ci				<< "%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n"
2095e5c31af7Sopenharmony_ci				<< "%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n"
2096e5c31af7Sopenharmony_ci				<< "%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
2097e5c31af7Sopenharmony_ci				<< "%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
2098e5c31af7Sopenharmony_ci				<< "%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
2099e5c31af7Sopenharmony_ci				<< "%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n"
2100e5c31af7Sopenharmony_ci				<< "%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n"
2101e5c31af7Sopenharmony_ci				<< "%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n"
2102e5c31af7Sopenharmony_ci				<< "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n"
2103e5c31af7Sopenharmony_ci				<< "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n"
2104e5c31af7Sopenharmony_ci				<< "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n"
2105e5c31af7Sopenharmony_ci				<< "%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
2106e5c31af7Sopenharmony_ci				<< "%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n"
2107e5c31af7Sopenharmony_ci				<< "%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n"
2108e5c31af7Sopenharmony_ci				<< "OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n"
2109e5c31af7Sopenharmony_ci				<< "%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2110e5c31af7Sopenharmony_ci				<< "%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2111e5c31af7Sopenharmony_ci				<< "%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2112e5c31af7Sopenharmony_ci				<< "%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n"
2113e5c31af7Sopenharmony_ci				<< "%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n"
2114e5c31af7Sopenharmony_ci				<< "%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n"
2115e5c31af7Sopenharmony_ci				<< "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n"
2116e5c31af7Sopenharmony_ci				<< "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n"
2117e5c31af7Sopenharmony_ci				<< "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n"
2118e5c31af7Sopenharmony_ci				<< "%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n"
2119e5c31af7Sopenharmony_ci				<< "%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n"
2120e5c31af7Sopenharmony_ci				<< "OpStore %out_color %tesse1_computed_clr\n"
2121e5c31af7Sopenharmony_ci				<< "OpReturn\n"
2122e5c31af7Sopenharmony_ci				<< "OpFunctionEnd\n";
2123e5c31af7Sopenharmony_ci		if (task == SHADER_TASK_UNUSED_FUNC)
2124e5c31af7Sopenharmony_ci		{
2125e5c31af7Sopenharmony_ci			shader	<< getUnusedFunctionBody();
2126e5c31af7Sopenharmony_ci		}
2127e5c31af7Sopenharmony_ci
2128e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("tesse") << shader.str();
2129e5c31af7Sopenharmony_ci	}
2130e5c31af7Sopenharmony_ci
2131e5c31af7Sopenharmony_ci	if (ctx.shaderTasks[SHADER_TASK_INDEX_FRAGMENT] != SHADER_TASK_NONE)
2132e5c31af7Sopenharmony_ci	{
2133e5c31af7Sopenharmony_ci		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_FRAGMENT];
2134e5c31af7Sopenharmony_ci		std::ostringstream	shader;
2135e5c31af7Sopenharmony_ci
2136e5c31af7Sopenharmony_ci		shader	<< "OpCapability Shader\n"
2137e5c31af7Sopenharmony_ci				<< "OpMemoryModel Logical GLSL450\n";
2138e5c31af7Sopenharmony_ci
2139e5c31af7Sopenharmony_ci		// Entry point.
2140e5c31af7Sopenharmony_ci		shader	<< "OpEntryPoint Fragment %main \"main\" %vtxColor %fragColor\n";
2141e5c31af7Sopenharmony_ci		if (task == SHADER_TASK_UNUSED_FUNC)
2142e5c31af7Sopenharmony_ci		{
2143e5c31af7Sopenharmony_ci			shader	<< getUnusedEntryPoint();
2144e5c31af7Sopenharmony_ci		}
2145e5c31af7Sopenharmony_ci		shader	<< "OpExecutionMode %main OriginUpperLeft\n";
2146e5c31af7Sopenharmony_ci
2147e5c31af7Sopenharmony_ci		// Decorations.
2148e5c31af7Sopenharmony_ci		shader	<< "OpDecorate %fragColor Location 0\n"
2149e5c31af7Sopenharmony_ci				<< "OpDecorate %vtxColor Location 1\n";
2150e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
2151e5c31af7Sopenharmony_ci		{
2152e5c31af7Sopenharmony_ci			shader	<< getUnusedDecorations(ctx.variableLocation);
2153e5c31af7Sopenharmony_ci		}
2154e5c31af7Sopenharmony_ci
2155e5c31af7Sopenharmony_ci		// Standard types, constants and arrays.
2156e5c31af7Sopenharmony_ci		shader	<< "; Start of standard types, constants and arrays\n"
2157e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_TYPES
2158e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_CONSTANTS
2159e5c31af7Sopenharmony_ci				<< SPIRV_ASSEMBLY_ARRAYS
2160e5c31af7Sopenharmony_ci				<< "; End of standard types, constants and arrays\n";
2161e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
2162e5c31af7Sopenharmony_ci		{
2163e5c31af7Sopenharmony_ci			shader	<< getUnusedTypesAndConstants();
2164e5c31af7Sopenharmony_ci		}
2165e5c31af7Sopenharmony_ci
2166e5c31af7Sopenharmony_ci		// Variables.
2167e5c31af7Sopenharmony_ci		shader	<< "%fragColor = OpVariable %op_v4f32 Output\n"
2168e5c31af7Sopenharmony_ci				<< "%vtxColor = OpVariable %ip_v4f32 Input\n";
2169e5c31af7Sopenharmony_ci		if (task != SHADER_TASK_NORMAL)
2170e5c31af7Sopenharmony_ci		{
2171e5c31af7Sopenharmony_ci			shader << getUnusedBuffer();
2172e5c31af7Sopenharmony_ci		}
2173e5c31af7Sopenharmony_ci
2174e5c31af7Sopenharmony_ci		// Main entry point.
2175e5c31af7Sopenharmony_ci		shader	<< "%main = OpFunction %void None %voidf\n"
2176e5c31af7Sopenharmony_ci				<< "%label_main = OpLabel\n"
2177e5c31af7Sopenharmony_ci				<< "%tmp1 = OpLoad %v4f32 %vtxColor\n"
2178e5c31af7Sopenharmony_ci				<< "OpStore %fragColor %tmp1\n"
2179e5c31af7Sopenharmony_ci				<< "OpReturn\n"
2180e5c31af7Sopenharmony_ci				<< "OpFunctionEnd\n";
2181e5c31af7Sopenharmony_ci		if (task == SHADER_TASK_UNUSED_FUNC)
2182e5c31af7Sopenharmony_ci		{
2183e5c31af7Sopenharmony_ci			shader	<< getUnusedFunctionBody();
2184e5c31af7Sopenharmony_ci		}
2185e5c31af7Sopenharmony_ci
2186e5c31af7Sopenharmony_ci		dst.spirvAsmSources.add("frag") << shader.str();
2187e5c31af7Sopenharmony_ci	}
2188e5c31af7Sopenharmony_ci}
2189e5c31af7Sopenharmony_ci
2190e5c31af7Sopenharmony_civoid createMultipleEntries (vk::SourceCollections& dst, InstanceContext)
2191e5c31af7Sopenharmony_ci{
2192e5c31af7Sopenharmony_ci	dst.spirvAsmSources.add("vert") <<
2193e5c31af7Sopenharmony_ci	// This module contains 2 vertex shaders. One that is a passthrough
2194e5c31af7Sopenharmony_ci	// and a second that inverts the color of the output (1.0 - color).
2195e5c31af7Sopenharmony_ci		"OpCapability Shader\n"
2196e5c31af7Sopenharmony_ci		"OpMemoryModel Logical GLSL450\n"
2197e5c31af7Sopenharmony_ci		"OpEntryPoint Vertex %main \"vert1\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
2198e5c31af7Sopenharmony_ci		"OpEntryPoint Vertex %main2 \"vert2\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
2199e5c31af7Sopenharmony_ci
2200e5c31af7Sopenharmony_ci		"OpDecorate %vtxPosition Location 2\n"
2201e5c31af7Sopenharmony_ci		"OpDecorate %Position Location 0\n"
2202e5c31af7Sopenharmony_ci		"OpDecorate %vtxColor Location 1\n"
2203e5c31af7Sopenharmony_ci		"OpDecorate %color Location 1\n"
2204e5c31af7Sopenharmony_ci		"OpDecorate %vertex_id BuiltIn VertexIndex\n"
2205e5c31af7Sopenharmony_ci		"OpDecorate %instance_id BuiltIn InstanceIndex\n"
2206e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_TYPES
2207e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_CONSTANTS
2208e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_ARRAYS
2209e5c31af7Sopenharmony_ci		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2210e5c31af7Sopenharmony_ci		"%vtxPosition = OpVariable %op_v4f32 Output\n"
2211e5c31af7Sopenharmony_ci		"%Position = OpVariable %ip_v4f32 Input\n"
2212e5c31af7Sopenharmony_ci		"%vtxColor = OpVariable %op_v4f32 Output\n"
2213e5c31af7Sopenharmony_ci		"%color = OpVariable %ip_v4f32 Input\n"
2214e5c31af7Sopenharmony_ci		"%vertex_id = OpVariable %ip_i32 Input\n"
2215e5c31af7Sopenharmony_ci		"%instance_id = OpVariable %ip_i32 Input\n"
2216e5c31af7Sopenharmony_ci
2217e5c31af7Sopenharmony_ci		"%main = OpFunction %void None %voidf\n"
2218e5c31af7Sopenharmony_ci		"%label = OpLabel\n"
2219e5c31af7Sopenharmony_ci		"%tmp_position = OpLoad %v4f32 %Position\n"
2220e5c31af7Sopenharmony_ci		"OpStore %vtxPosition %tmp_position\n"
2221e5c31af7Sopenharmony_ci		"%tmp_color = OpLoad %v4f32 %color\n"
2222e5c31af7Sopenharmony_ci		"OpStore %vtxColor %tmp_color\n"
2223e5c31af7Sopenharmony_ci		"OpReturn\n"
2224e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
2225e5c31af7Sopenharmony_ci
2226e5c31af7Sopenharmony_ci		"%main2 = OpFunction %void None %voidf\n"
2227e5c31af7Sopenharmony_ci		"%label2 = OpLabel\n"
2228e5c31af7Sopenharmony_ci		"%tmp_position2 = OpLoad %v4f32 %Position\n"
2229e5c31af7Sopenharmony_ci		"OpStore %vtxPosition %tmp_position2\n"
2230e5c31af7Sopenharmony_ci		"%tmp_color2 = OpLoad %v4f32 %color\n"
2231e5c31af7Sopenharmony_ci		"%tmp_color3 = OpFSub %v4f32 %cval %tmp_color2\n"
2232e5c31af7Sopenharmony_ci		"%tmp_color4 = OpVectorInsertDynamic %v4f32 %tmp_color3 %c_f32_1 %c_i32_3\n"
2233e5c31af7Sopenharmony_ci		"OpStore %vtxColor %tmp_color4\n"
2234e5c31af7Sopenharmony_ci		"OpReturn\n"
2235e5c31af7Sopenharmony_ci		"OpFunctionEnd\n";
2236e5c31af7Sopenharmony_ci
2237e5c31af7Sopenharmony_ci	dst.spirvAsmSources.add("frag") <<
2238e5c31af7Sopenharmony_ci		// This is a single module that contains 2 fragment shaders.
2239e5c31af7Sopenharmony_ci		// One that passes color through and the other that inverts the output
2240e5c31af7Sopenharmony_ci		// color (1.0 - color).
2241e5c31af7Sopenharmony_ci		"OpCapability Shader\n"
2242e5c31af7Sopenharmony_ci		"OpMemoryModel Logical GLSL450\n"
2243e5c31af7Sopenharmony_ci		"OpEntryPoint Fragment %main \"frag1\" %vtxColor %fragColor\n"
2244e5c31af7Sopenharmony_ci		"OpEntryPoint Fragment %main2 \"frag2\" %vtxColor %fragColor\n"
2245e5c31af7Sopenharmony_ci		"OpExecutionMode %main OriginUpperLeft\n"
2246e5c31af7Sopenharmony_ci		"OpExecutionMode %main2 OriginUpperLeft\n"
2247e5c31af7Sopenharmony_ci
2248e5c31af7Sopenharmony_ci		"OpDecorate %fragColor Location 0\n"
2249e5c31af7Sopenharmony_ci		"OpDecorate %vtxColor Location 1\n"
2250e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_TYPES
2251e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_CONSTANTS
2252e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_ARRAYS
2253e5c31af7Sopenharmony_ci		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2254e5c31af7Sopenharmony_ci		"%fragColor = OpVariable %op_v4f32 Output\n"
2255e5c31af7Sopenharmony_ci		"%vtxColor = OpVariable %ip_v4f32 Input\n"
2256e5c31af7Sopenharmony_ci
2257e5c31af7Sopenharmony_ci		"%main = OpFunction %void None %voidf\n"
2258e5c31af7Sopenharmony_ci		"%label_main = OpLabel\n"
2259e5c31af7Sopenharmony_ci		"%tmp1 = OpLoad %v4f32 %vtxColor\n"
2260e5c31af7Sopenharmony_ci		"OpStore %fragColor %tmp1\n"
2261e5c31af7Sopenharmony_ci		"OpReturn\n"
2262e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
2263e5c31af7Sopenharmony_ci
2264e5c31af7Sopenharmony_ci		"%main2 = OpFunction %void None %voidf\n"
2265e5c31af7Sopenharmony_ci		"%label_main2 = OpLabel\n"
2266e5c31af7Sopenharmony_ci		"%tmp2 = OpLoad %v4f32 %vtxColor\n"
2267e5c31af7Sopenharmony_ci		"%tmp3 = OpFSub %v4f32 %cval %tmp2\n"
2268e5c31af7Sopenharmony_ci		"%tmp4 = OpVectorInsertDynamic %v4f32 %tmp3 %c_f32_1 %c_i32_3\n"
2269e5c31af7Sopenharmony_ci		"OpStore %fragColor %tmp4\n"
2270e5c31af7Sopenharmony_ci		"OpReturn\n"
2271e5c31af7Sopenharmony_ci		"OpFunctionEnd\n";
2272e5c31af7Sopenharmony_ci
2273e5c31af7Sopenharmony_ci	dst.spirvAsmSources.add("geom") <<
2274e5c31af7Sopenharmony_ci		"OpCapability Geometry\n"
2275e5c31af7Sopenharmony_ci		"OpMemoryModel Logical GLSL450\n"
2276e5c31af7Sopenharmony_ci		"OpEntryPoint Geometry %geom1_main \"geom1\" %out_gl_position %gl_in %out_color %in_color\n"
2277e5c31af7Sopenharmony_ci		"OpEntryPoint Geometry %geom2_main \"geom2\" %out_gl_position %gl_in %out_color %in_color\n"
2278e5c31af7Sopenharmony_ci		"OpExecutionMode %geom1_main Triangles\n"
2279e5c31af7Sopenharmony_ci		"OpExecutionMode %geom2_main Triangles\n"
2280e5c31af7Sopenharmony_ci		"OpExecutionMode %geom1_main OutputTriangleStrip\n"
2281e5c31af7Sopenharmony_ci		"OpExecutionMode %geom2_main OutputTriangleStrip\n"
2282e5c31af7Sopenharmony_ci		"OpExecutionMode %geom1_main OutputVertices 3\n"
2283e5c31af7Sopenharmony_ci		"OpExecutionMode %geom2_main OutputVertices 3\n"
2284e5c31af7Sopenharmony_ci		"OpExecutionMode %geom1_main Invocations 1\n"
2285e5c31af7Sopenharmony_ci		"OpExecutionMode %geom2_main Invocations 1\n"
2286e5c31af7Sopenharmony_ci		"OpDecorate %out_gl_position BuiltIn Position\n"
2287e5c31af7Sopenharmony_ci		"OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n"
2288e5c31af7Sopenharmony_ci		"OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n"
2289e5c31af7Sopenharmony_ci		"OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n"
2290e5c31af7Sopenharmony_ci		"OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n"
2291e5c31af7Sopenharmony_ci		"OpDecorate %per_vertex_in Block\n"
2292e5c31af7Sopenharmony_ci		"OpDecorate %out_color Location 1\n"
2293e5c31af7Sopenharmony_ci		"OpDecorate %in_color Location 1\n"
2294e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_TYPES
2295e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_CONSTANTS
2296e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_ARRAYS
2297e5c31af7Sopenharmony_ci		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2298e5c31af7Sopenharmony_ci		"%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2299e5c31af7Sopenharmony_ci		"%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n"
2300e5c31af7Sopenharmony_ci		"%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n"
2301e5c31af7Sopenharmony_ci		"%gl_in = OpVariable %ip_a3_per_vertex_in Input\n"
2302e5c31af7Sopenharmony_ci		"%out_color = OpVariable %op_v4f32 Output\n"
2303e5c31af7Sopenharmony_ci		"%in_color = OpVariable %ip_a3v4f32 Input\n"
2304e5c31af7Sopenharmony_ci		"%out_gl_position = OpVariable %op_v4f32 Output\n"
2305e5c31af7Sopenharmony_ci
2306e5c31af7Sopenharmony_ci		"%geom1_main = OpFunction %void None %voidf\n"
2307e5c31af7Sopenharmony_ci		"%geom1_label = OpLabel\n"
2308e5c31af7Sopenharmony_ci		"%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
2309e5c31af7Sopenharmony_ci		"%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
2310e5c31af7Sopenharmony_ci		"%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
2311e5c31af7Sopenharmony_ci		"%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n"
2312e5c31af7Sopenharmony_ci		"%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n"
2313e5c31af7Sopenharmony_ci		"%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n"
2314e5c31af7Sopenharmony_ci		"%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2315e5c31af7Sopenharmony_ci		"%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2316e5c31af7Sopenharmony_ci		"%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2317e5c31af7Sopenharmony_ci		"%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n"
2318e5c31af7Sopenharmony_ci		"%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n"
2319e5c31af7Sopenharmony_ci		"%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n"
2320e5c31af7Sopenharmony_ci		"OpStore %out_gl_position %geom1_in_position_0\n"
2321e5c31af7Sopenharmony_ci		"OpStore %out_color %geom1_in_color_0\n"
2322e5c31af7Sopenharmony_ci		"OpEmitVertex\n"
2323e5c31af7Sopenharmony_ci		"OpStore %out_gl_position %geom1_in_position_1\n"
2324e5c31af7Sopenharmony_ci		"OpStore %out_color %geom1_in_color_1\n"
2325e5c31af7Sopenharmony_ci		"OpEmitVertex\n"
2326e5c31af7Sopenharmony_ci		"OpStore %out_gl_position %geom1_in_position_2\n"
2327e5c31af7Sopenharmony_ci		"OpStore %out_color %geom1_in_color_2\n"
2328e5c31af7Sopenharmony_ci		"OpEmitVertex\n"
2329e5c31af7Sopenharmony_ci		"OpEndPrimitive\n"
2330e5c31af7Sopenharmony_ci		"OpReturn\n"
2331e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
2332e5c31af7Sopenharmony_ci
2333e5c31af7Sopenharmony_ci		"%geom2_main = OpFunction %void None %voidf\n"
2334e5c31af7Sopenharmony_ci		"%geom2_label = OpLabel\n"
2335e5c31af7Sopenharmony_ci		"%geom2_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
2336e5c31af7Sopenharmony_ci		"%geom2_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
2337e5c31af7Sopenharmony_ci		"%geom2_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
2338e5c31af7Sopenharmony_ci		"%geom2_in_position_0 = OpLoad %v4f32 %geom2_gl_in_0_gl_position\n"
2339e5c31af7Sopenharmony_ci		"%geom2_in_position_1 = OpLoad %v4f32 %geom2_gl_in_1_gl_position\n"
2340e5c31af7Sopenharmony_ci		"%geom2_in_position_2 = OpLoad %v4f32 %geom2_gl_in_2_gl_position \n"
2341e5c31af7Sopenharmony_ci		"%geom2_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2342e5c31af7Sopenharmony_ci		"%geom2_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2343e5c31af7Sopenharmony_ci		"%geom2_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2344e5c31af7Sopenharmony_ci		"%geom2_in_color_0 = OpLoad %v4f32 %geom2_in_color_0_ptr\n"
2345e5c31af7Sopenharmony_ci		"%geom2_in_color_1 = OpLoad %v4f32 %geom2_in_color_1_ptr\n"
2346e5c31af7Sopenharmony_ci		"%geom2_in_color_2 = OpLoad %v4f32 %geom2_in_color_2_ptr\n"
2347e5c31af7Sopenharmony_ci		"%geom2_transformed_in_color_0 = OpFSub %v4f32 %cval %geom2_in_color_0\n"
2348e5c31af7Sopenharmony_ci		"%geom2_transformed_in_color_1 = OpFSub %v4f32 %cval %geom2_in_color_1\n"
2349e5c31af7Sopenharmony_ci		"%geom2_transformed_in_color_2 = OpFSub %v4f32 %cval %geom2_in_color_2\n"
2350e5c31af7Sopenharmony_ci		"%geom2_transformed_in_color_0_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_0 %c_f32_1 %c_i32_3\n"
2351e5c31af7Sopenharmony_ci		"%geom2_transformed_in_color_1_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_1 %c_f32_1 %c_i32_3\n"
2352e5c31af7Sopenharmony_ci		"%geom2_transformed_in_color_2_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_2 %c_f32_1 %c_i32_3\n"
2353e5c31af7Sopenharmony_ci		"OpStore %out_gl_position %geom2_in_position_0\n"
2354e5c31af7Sopenharmony_ci		"OpStore %out_color %geom2_transformed_in_color_0_a\n"
2355e5c31af7Sopenharmony_ci		"OpEmitVertex\n"
2356e5c31af7Sopenharmony_ci		"OpStore %out_gl_position %geom2_in_position_1\n"
2357e5c31af7Sopenharmony_ci		"OpStore %out_color %geom2_transformed_in_color_1_a\n"
2358e5c31af7Sopenharmony_ci		"OpEmitVertex\n"
2359e5c31af7Sopenharmony_ci		"OpStore %out_gl_position %geom2_in_position_2\n"
2360e5c31af7Sopenharmony_ci		"OpStore %out_color %geom2_transformed_in_color_2_a\n"
2361e5c31af7Sopenharmony_ci		"OpEmitVertex\n"
2362e5c31af7Sopenharmony_ci		"OpEndPrimitive\n"
2363e5c31af7Sopenharmony_ci		"OpReturn\n"
2364e5c31af7Sopenharmony_ci		"OpFunctionEnd\n";
2365e5c31af7Sopenharmony_ci
2366e5c31af7Sopenharmony_ci	dst.spirvAsmSources.add("tessc") <<
2367e5c31af7Sopenharmony_ci		"OpCapability Tessellation\n"
2368e5c31af7Sopenharmony_ci		"OpMemoryModel Logical GLSL450\n"
2369e5c31af7Sopenharmony_ci		"OpEntryPoint TessellationControl %tessc1_main \"tessc1\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
2370e5c31af7Sopenharmony_ci		"OpEntryPoint TessellationControl %tessc2_main \"tessc2\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
2371e5c31af7Sopenharmony_ci		"OpExecutionMode %tessc1_main OutputVertices 3\n"
2372e5c31af7Sopenharmony_ci		"OpExecutionMode %tessc2_main OutputVertices 3\n"
2373e5c31af7Sopenharmony_ci		"OpDecorate %out_color Location 1\n"
2374e5c31af7Sopenharmony_ci		"OpDecorate %gl_InvocationID BuiltIn InvocationId\n"
2375e5c31af7Sopenharmony_ci		"OpDecorate %in_color Location 1\n"
2376e5c31af7Sopenharmony_ci		"OpDecorate %out_position Location 2\n"
2377e5c31af7Sopenharmony_ci		"OpDecorate %in_position Location 2\n"
2378e5c31af7Sopenharmony_ci		"OpDecorate %gl_TessLevelOuter Patch\n"
2379e5c31af7Sopenharmony_ci		"OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n"
2380e5c31af7Sopenharmony_ci		"OpDecorate %gl_TessLevelInner Patch\n"
2381e5c31af7Sopenharmony_ci		"OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n"
2382e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_TYPES
2383e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_CONSTANTS
2384e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_ARRAYS
2385e5c31af7Sopenharmony_ci		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2386e5c31af7Sopenharmony_ci		"%out_color = OpVariable %op_a3v4f32 Output\n"
2387e5c31af7Sopenharmony_ci		"%gl_InvocationID = OpVariable %ip_i32 Input\n"
2388e5c31af7Sopenharmony_ci		"%in_color = OpVariable %ip_a32v4f32 Input\n"
2389e5c31af7Sopenharmony_ci		"%out_position = OpVariable %op_a3v4f32 Output\n"
2390e5c31af7Sopenharmony_ci		"%in_position = OpVariable %ip_a32v4f32 Input\n"
2391e5c31af7Sopenharmony_ci		"%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
2392e5c31af7Sopenharmony_ci		"%gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
2393e5c31af7Sopenharmony_ci
2394e5c31af7Sopenharmony_ci		"%tessc1_main = OpFunction %void None %voidf\n"
2395e5c31af7Sopenharmony_ci		"%tessc1_label = OpLabel\n"
2396e5c31af7Sopenharmony_ci		"%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n"
2397e5c31af7Sopenharmony_ci		"%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n"
2398e5c31af7Sopenharmony_ci		"%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n"
2399e5c31af7Sopenharmony_ci		"%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n"
2400e5c31af7Sopenharmony_ci		"%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n"
2401e5c31af7Sopenharmony_ci		"%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n"
2402e5c31af7Sopenharmony_ci		"%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n"
2403e5c31af7Sopenharmony_ci		"OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n"
2404e5c31af7Sopenharmony_ci		"OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n"
2405e5c31af7Sopenharmony_ci		"%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n"
2406e5c31af7Sopenharmony_ci		"OpSelectionMerge %tessc1_merge_label None\n"
2407e5c31af7Sopenharmony_ci		"OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n"
2408e5c31af7Sopenharmony_ci		"%tessc1_first_invocation = OpLabel\n"
2409e5c31af7Sopenharmony_ci		"%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
2410e5c31af7Sopenharmony_ci		"%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
2411e5c31af7Sopenharmony_ci		"%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
2412e5c31af7Sopenharmony_ci		"%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n"
2413e5c31af7Sopenharmony_ci		"OpStore %tessc1_tess_outer_0 %c_f32_1\n"
2414e5c31af7Sopenharmony_ci		"OpStore %tessc1_tess_outer_1 %c_f32_1\n"
2415e5c31af7Sopenharmony_ci		"OpStore %tessc1_tess_outer_2 %c_f32_1\n"
2416e5c31af7Sopenharmony_ci		"OpStore %tessc1_tess_inner %c_f32_1\n"
2417e5c31af7Sopenharmony_ci		"OpBranch %tessc1_merge_label\n"
2418e5c31af7Sopenharmony_ci		"%tessc1_merge_label = OpLabel\n"
2419e5c31af7Sopenharmony_ci		"OpReturn\n"
2420e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
2421e5c31af7Sopenharmony_ci
2422e5c31af7Sopenharmony_ci		"%tessc2_main = OpFunction %void None %voidf\n"
2423e5c31af7Sopenharmony_ci		"%tessc2_label = OpLabel\n"
2424e5c31af7Sopenharmony_ci		"%tessc2_invocation_id = OpLoad %i32 %gl_InvocationID\n"
2425e5c31af7Sopenharmony_ci		"%tessc2_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc2_invocation_id\n"
2426e5c31af7Sopenharmony_ci		"%tessc2_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc2_invocation_id\n"
2427e5c31af7Sopenharmony_ci		"%tessc2_in_color_val = OpLoad %v4f32 %tessc2_in_color_ptr\n"
2428e5c31af7Sopenharmony_ci		"%tessc2_in_position_val = OpLoad %v4f32 %tessc2_in_position_ptr\n"
2429e5c31af7Sopenharmony_ci		"%tessc2_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc2_invocation_id\n"
2430e5c31af7Sopenharmony_ci		"%tessc2_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc2_invocation_id\n"
2431e5c31af7Sopenharmony_ci		"%tessc2_transformed_color = OpFSub %v4f32 %cval %tessc2_in_color_val\n"
2432e5c31af7Sopenharmony_ci		"%tessc2_transformed_color_a = OpVectorInsertDynamic %v4f32 %tessc2_transformed_color %c_f32_1 %c_i32_3\n"
2433e5c31af7Sopenharmony_ci		"OpStore %tessc2_out_color_ptr %tessc2_transformed_color_a\n"
2434e5c31af7Sopenharmony_ci		"OpStore %tessc2_out_position_ptr %tessc2_in_position_val\n"
2435e5c31af7Sopenharmony_ci		"%tessc2_is_first_invocation = OpIEqual %bool %tessc2_invocation_id %c_i32_0\n"
2436e5c31af7Sopenharmony_ci		"OpSelectionMerge %tessc2_merge_label None\n"
2437e5c31af7Sopenharmony_ci		"OpBranchConditional %tessc2_is_first_invocation %tessc2_first_invocation %tessc2_merge_label\n"
2438e5c31af7Sopenharmony_ci		"%tessc2_first_invocation = OpLabel\n"
2439e5c31af7Sopenharmony_ci		"%tessc2_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
2440e5c31af7Sopenharmony_ci		"%tessc2_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
2441e5c31af7Sopenharmony_ci		"%tessc2_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
2442e5c31af7Sopenharmony_ci		"%tessc2_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n"
2443e5c31af7Sopenharmony_ci		"OpStore %tessc2_tess_outer_0 %c_f32_1\n"
2444e5c31af7Sopenharmony_ci		"OpStore %tessc2_tess_outer_1 %c_f32_1\n"
2445e5c31af7Sopenharmony_ci		"OpStore %tessc2_tess_outer_2 %c_f32_1\n"
2446e5c31af7Sopenharmony_ci		"OpStore %tessc2_tess_inner %c_f32_1\n"
2447e5c31af7Sopenharmony_ci		"OpBranch %tessc2_merge_label\n"
2448e5c31af7Sopenharmony_ci		"%tessc2_merge_label = OpLabel\n"
2449e5c31af7Sopenharmony_ci		"OpReturn\n"
2450e5c31af7Sopenharmony_ci		"OpFunctionEnd\n";
2451e5c31af7Sopenharmony_ci
2452e5c31af7Sopenharmony_ci	dst.spirvAsmSources.add("tesse") <<
2453e5c31af7Sopenharmony_ci		"OpCapability Tessellation\n"
2454e5c31af7Sopenharmony_ci		"OpMemoryModel Logical GLSL450\n"
2455e5c31af7Sopenharmony_ci		"OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
2456e5c31af7Sopenharmony_ci		"OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
2457e5c31af7Sopenharmony_ci		"OpExecutionMode %tesse1_main Triangles\n"
2458e5c31af7Sopenharmony_ci		"OpExecutionMode %tesse1_main SpacingEqual\n"
2459e5c31af7Sopenharmony_ci		"OpExecutionMode %tesse1_main VertexOrderCcw\n"
2460e5c31af7Sopenharmony_ci		"OpExecutionMode %tesse2_main Triangles\n"
2461e5c31af7Sopenharmony_ci		"OpExecutionMode %tesse2_main SpacingEqual\n"
2462e5c31af7Sopenharmony_ci		"OpExecutionMode %tesse2_main VertexOrderCcw\n"
2463e5c31af7Sopenharmony_ci		"OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n"
2464e5c31af7Sopenharmony_ci		"OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n"
2465e5c31af7Sopenharmony_ci		"OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n"
2466e5c31af7Sopenharmony_ci		"OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n"
2467e5c31af7Sopenharmony_ci		"OpDecorate %per_vertex_out Block\n"
2468e5c31af7Sopenharmony_ci		"OpDecorate %gl_tessCoord BuiltIn TessCoord\n"
2469e5c31af7Sopenharmony_ci		"OpDecorate %in_position Location 2\n"
2470e5c31af7Sopenharmony_ci		"OpDecorate %out_color Location 1\n"
2471e5c31af7Sopenharmony_ci		"OpDecorate %in_color Location 1\n"
2472e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_TYPES
2473e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_CONSTANTS
2474e5c31af7Sopenharmony_ci		SPIRV_ASSEMBLY_ARRAYS
2475e5c31af7Sopenharmony_ci		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2476e5c31af7Sopenharmony_ci		"%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2477e5c31af7Sopenharmony_ci		"%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n"
2478e5c31af7Sopenharmony_ci		"%stream = OpVariable %op_per_vertex_out Output\n"
2479e5c31af7Sopenharmony_ci		"%gl_tessCoord = OpVariable %ip_v3f32 Input\n"
2480e5c31af7Sopenharmony_ci		"%in_position = OpVariable %ip_a32v4f32 Input\n"
2481e5c31af7Sopenharmony_ci		"%out_color = OpVariable %op_v4f32 Output\n"
2482e5c31af7Sopenharmony_ci		"%in_color = OpVariable %ip_a32v4f32 Input\n"
2483e5c31af7Sopenharmony_ci
2484e5c31af7Sopenharmony_ci		"%tesse1_main = OpFunction %void None %voidf\n"
2485e5c31af7Sopenharmony_ci		"%tesse1_label = OpLabel\n"
2486e5c31af7Sopenharmony_ci		"%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
2487e5c31af7Sopenharmony_ci		"%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
2488e5c31af7Sopenharmony_ci		"%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
2489e5c31af7Sopenharmony_ci		"%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n"
2490e5c31af7Sopenharmony_ci		"%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n"
2491e5c31af7Sopenharmony_ci		"%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n"
2492e5c31af7Sopenharmony_ci		"%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
2493e5c31af7Sopenharmony_ci		"%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
2494e5c31af7Sopenharmony_ci		"%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
2495e5c31af7Sopenharmony_ci		"%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n"
2496e5c31af7Sopenharmony_ci		"%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n"
2497e5c31af7Sopenharmony_ci		"%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n"
2498e5c31af7Sopenharmony_ci		"%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n"
2499e5c31af7Sopenharmony_ci		"%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n"
2500e5c31af7Sopenharmony_ci		"%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n"
2501e5c31af7Sopenharmony_ci		"%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
2502e5c31af7Sopenharmony_ci		"%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n"
2503e5c31af7Sopenharmony_ci		"%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n"
2504e5c31af7Sopenharmony_ci		"OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n"
2505e5c31af7Sopenharmony_ci		"%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2506e5c31af7Sopenharmony_ci		"%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2507e5c31af7Sopenharmony_ci		"%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2508e5c31af7Sopenharmony_ci		"%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n"
2509e5c31af7Sopenharmony_ci		"%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n"
2510e5c31af7Sopenharmony_ci		"%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n"
2511e5c31af7Sopenharmony_ci		"%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n"
2512e5c31af7Sopenharmony_ci		"%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n"
2513e5c31af7Sopenharmony_ci		"%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n"
2514e5c31af7Sopenharmony_ci		"%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n"
2515e5c31af7Sopenharmony_ci		"%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n"
2516e5c31af7Sopenharmony_ci		"OpStore %out_color %tesse1_computed_clr\n"
2517e5c31af7Sopenharmony_ci		"OpReturn\n"
2518e5c31af7Sopenharmony_ci		"OpFunctionEnd\n"
2519e5c31af7Sopenharmony_ci
2520e5c31af7Sopenharmony_ci		"%tesse2_main = OpFunction %void None %voidf\n"
2521e5c31af7Sopenharmony_ci		"%tesse2_label = OpLabel\n"
2522e5c31af7Sopenharmony_ci		"%tesse2_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
2523e5c31af7Sopenharmony_ci		"%tesse2_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
2524e5c31af7Sopenharmony_ci		"%tesse2_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
2525e5c31af7Sopenharmony_ci		"%tesse2_tc_0 = OpLoad %f32 %tesse2_tc_0_ptr\n"
2526e5c31af7Sopenharmony_ci		"%tesse2_tc_1 = OpLoad %f32 %tesse2_tc_1_ptr\n"
2527e5c31af7Sopenharmony_ci		"%tesse2_tc_2 = OpLoad %f32 %tesse2_tc_2_ptr\n"
2528e5c31af7Sopenharmony_ci		"%tesse2_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
2529e5c31af7Sopenharmony_ci		"%tesse2_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
2530e5c31af7Sopenharmony_ci		"%tesse2_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
2531e5c31af7Sopenharmony_ci		"%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n"
2532e5c31af7Sopenharmony_ci		"%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n"
2533e5c31af7Sopenharmony_ci		"%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n"
2534e5c31af7Sopenharmony_ci		"%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_0 %tesse2_tc_0\n"
2535e5c31af7Sopenharmony_ci		"%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_1 %tesse2_tc_1\n"
2536e5c31af7Sopenharmony_ci		"%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_2 %tesse2_tc_2\n"
2537e5c31af7Sopenharmony_ci		"%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
2538e5c31af7Sopenharmony_ci		"%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n"
2539e5c31af7Sopenharmony_ci		"%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n"
2540e5c31af7Sopenharmony_ci		"OpStore %tesse2_out_pos_ptr %tesse2_computed_out\n"
2541e5c31af7Sopenharmony_ci		"%tesse2_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2542e5c31af7Sopenharmony_ci		"%tesse2_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2543e5c31af7Sopenharmony_ci		"%tesse2_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2544e5c31af7Sopenharmony_ci		"%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n"
2545e5c31af7Sopenharmony_ci		"%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n"
2546e5c31af7Sopenharmony_ci		"%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n"
2547e5c31af7Sopenharmony_ci		"%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_0 %tesse2_tc_0\n"
2548e5c31af7Sopenharmony_ci		"%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_1 %tesse2_tc_1\n"
2549e5c31af7Sopenharmony_ci		"%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_2 %tesse2_tc_2\n"
2550e5c31af7Sopenharmony_ci		"%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n"
2551e5c31af7Sopenharmony_ci		"%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n"
2552e5c31af7Sopenharmony_ci		"%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n"
2553e5c31af7Sopenharmony_ci		"%tesse2_clr_transformed_a = OpVectorInsertDynamic %v4f32 %tesse2_clr_transformed %c_f32_1 %c_i32_3\n"
2554e5c31af7Sopenharmony_ci		"OpStore %out_color %tesse2_clr_transformed_a\n"
2555e5c31af7Sopenharmony_ci		"OpReturn\n"
2556e5c31af7Sopenharmony_ci		"OpFunctionEnd\n";
2557e5c31af7Sopenharmony_ci}
2558e5c31af7Sopenharmony_ci
2559e5c31af7Sopenharmony_cibool compare16BitFloat (float original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log)
2560e5c31af7Sopenharmony_ci{
2561e5c31af7Sopenharmony_ci	// We only support RTE, RTZ, or both.
2562e5c31af7Sopenharmony_ci	DE_ASSERT(static_cast<int>(flags) > 0 && static_cast<int>(flags) < 4);
2563e5c31af7Sopenharmony_ci
2564e5c31af7Sopenharmony_ci	const Float32	originalFloat	(original);
2565e5c31af7Sopenharmony_ci	const Float16	returnedFloat	(returned);
2566e5c31af7Sopenharmony_ci
2567e5c31af7Sopenharmony_ci	// Zero are turned into zero under both RTE and RTZ.
2568e5c31af7Sopenharmony_ci	if (originalFloat.isZero())
2569e5c31af7Sopenharmony_ci	{
2570e5c31af7Sopenharmony_ci		if (returnedFloat.isZero())
2571e5c31af7Sopenharmony_ci			return true;
2572e5c31af7Sopenharmony_ci
2573e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2574e5c31af7Sopenharmony_ci		return false;
2575e5c31af7Sopenharmony_ci	}
2576e5c31af7Sopenharmony_ci
2577e5c31af7Sopenharmony_ci	// Any denormalized value input into a shader may be flushed to 0.
2578e5c31af7Sopenharmony_ci	if (originalFloat.isDenorm() && returnedFloat.isZero())
2579e5c31af7Sopenharmony_ci		return true;
2580e5c31af7Sopenharmony_ci
2581e5c31af7Sopenharmony_ci	// Inf are always turned into Inf with the same sign, too.
2582e5c31af7Sopenharmony_ci	if (originalFloat.isInf())
2583e5c31af7Sopenharmony_ci	{
2584e5c31af7Sopenharmony_ci		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2585e5c31af7Sopenharmony_ci			return true;
2586e5c31af7Sopenharmony_ci
2587e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2588e5c31af7Sopenharmony_ci		return false;
2589e5c31af7Sopenharmony_ci	}
2590e5c31af7Sopenharmony_ci
2591e5c31af7Sopenharmony_ci	// NaN are always turned into NaN, too.
2592e5c31af7Sopenharmony_ci	if (originalFloat.isNaN())
2593e5c31af7Sopenharmony_ci	{
2594e5c31af7Sopenharmony_ci		if (returnedFloat.isNaN())
2595e5c31af7Sopenharmony_ci			return true;
2596e5c31af7Sopenharmony_ci
2597e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2598e5c31af7Sopenharmony_ci		return false;
2599e5c31af7Sopenharmony_ci	}
2600e5c31af7Sopenharmony_ci
2601e5c31af7Sopenharmony_ci	// Check all rounding modes
2602e5c31af7Sopenharmony_ci	for (int bitNdx = 0; bitNdx < 2; ++bitNdx)
2603e5c31af7Sopenharmony_ci	{
2604e5c31af7Sopenharmony_ci		if ((flags & (1u << bitNdx)) == 0)
2605e5c31af7Sopenharmony_ci			continue;	// This rounding mode is not selected.
2606e5c31af7Sopenharmony_ci
2607e5c31af7Sopenharmony_ci		const Float16	expectedFloat	(deFloat32To16Round(original, deRoundingMode(bitNdx)));
2608e5c31af7Sopenharmony_ci
2609e5c31af7Sopenharmony_ci		// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2610e5c31af7Sopenharmony_ci		if (expectedFloat.isDenorm() && returnedFloat.isZero())
2611e5c31af7Sopenharmony_ci			return true;
2612e5c31af7Sopenharmony_ci
2613e5c31af7Sopenharmony_ci		// If not matched in the above cases, they should have the same bit pattern.
2614e5c31af7Sopenharmony_ci		if (expectedFloat.bits() == returnedFloat.bits())
2615e5c31af7Sopenharmony_ci			return true;
2616e5c31af7Sopenharmony_ci	}
2617e5c31af7Sopenharmony_ci
2618e5c31af7Sopenharmony_ci	log << TestLog::Message << "Error: found unmatched 32-bit and 16-bit floats: " << originalFloat.bits() << " vs " << returned << TestLog::EndMessage;
2619e5c31af7Sopenharmony_ci	return false;
2620e5c31af7Sopenharmony_ci}
2621e5c31af7Sopenharmony_ci
2622e5c31af7Sopenharmony_cibool compare16BitFloat (deUint16 original, deUint16 returned, tcu::TestLog& log)
2623e5c31af7Sopenharmony_ci{
2624e5c31af7Sopenharmony_ci	const Float16	originalFloat	(original);
2625e5c31af7Sopenharmony_ci	const Float16	returnedFloat	(returned);
2626e5c31af7Sopenharmony_ci
2627e5c31af7Sopenharmony_ci	if (originalFloat.isZero())
2628e5c31af7Sopenharmony_ci	{
2629e5c31af7Sopenharmony_ci		if (returnedFloat.isZero())
2630e5c31af7Sopenharmony_ci			return true;
2631e5c31af7Sopenharmony_ci
2632e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2633e5c31af7Sopenharmony_ci		return false;
2634e5c31af7Sopenharmony_ci	}
2635e5c31af7Sopenharmony_ci
2636e5c31af7Sopenharmony_ci	// Any denormalized value input into a shader or potentially generated by any instruction in a shader
2637e5c31af7Sopenharmony_ci	// may be flushed to 0.
2638e5c31af7Sopenharmony_ci	if (originalFloat.isDenorm() && returnedFloat.isZero())
2639e5c31af7Sopenharmony_ci		return true;
2640e5c31af7Sopenharmony_ci
2641e5c31af7Sopenharmony_ci	// Inf are always turned into Inf with the same sign, too.
2642e5c31af7Sopenharmony_ci	if (originalFloat.isInf())
2643e5c31af7Sopenharmony_ci	{
2644e5c31af7Sopenharmony_ci		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2645e5c31af7Sopenharmony_ci			return true;
2646e5c31af7Sopenharmony_ci
2647e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2648e5c31af7Sopenharmony_ci		return false;
2649e5c31af7Sopenharmony_ci	}
2650e5c31af7Sopenharmony_ci
2651e5c31af7Sopenharmony_ci	// NaN are always turned into NaN, too.
2652e5c31af7Sopenharmony_ci	if (originalFloat.isNaN())
2653e5c31af7Sopenharmony_ci	{
2654e5c31af7Sopenharmony_ci		if (returnedFloat.isNaN())
2655e5c31af7Sopenharmony_ci			return true;
2656e5c31af7Sopenharmony_ci
2657e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2658e5c31af7Sopenharmony_ci		return false;
2659e5c31af7Sopenharmony_ci	}
2660e5c31af7Sopenharmony_ci
2661e5c31af7Sopenharmony_ci	// If not matched in the above cases, they should have the same bit pattern.
2662e5c31af7Sopenharmony_ci	if (originalFloat.bits() == returnedFloat.bits())
2663e5c31af7Sopenharmony_ci		return true;
2664e5c31af7Sopenharmony_ci
2665e5c31af7Sopenharmony_ci	log << TestLog::Message << "Error: found unmatched 16-bit and 16-bit floats: " << original << " vs " << returned << TestLog::EndMessage;
2666e5c31af7Sopenharmony_ci	return false;
2667e5c31af7Sopenharmony_ci}
2668e5c31af7Sopenharmony_ci
2669e5c31af7Sopenharmony_cibool compare16BitFloat(deUint16 original, float returned, tcu::TestLog & log)
2670e5c31af7Sopenharmony_ci{
2671e5c31af7Sopenharmony_ci	const Float16	originalFloat	(original);
2672e5c31af7Sopenharmony_ci	const Float32	returnedFloat	(returned);
2673e5c31af7Sopenharmony_ci
2674e5c31af7Sopenharmony_ci	// Zero are turned into zero under both RTE and RTZ.
2675e5c31af7Sopenharmony_ci	if (originalFloat.isZero())
2676e5c31af7Sopenharmony_ci	{
2677e5c31af7Sopenharmony_ci		if (returnedFloat.isZero())
2678e5c31af7Sopenharmony_ci			return true;
2679e5c31af7Sopenharmony_ci
2680e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2681e5c31af7Sopenharmony_ci		return false;
2682e5c31af7Sopenharmony_ci	}
2683e5c31af7Sopenharmony_ci
2684e5c31af7Sopenharmony_ci	// Any denormalized value input into a shader may be flushed to 0.
2685e5c31af7Sopenharmony_ci	if (originalFloat.isDenorm() && returnedFloat.isZero())
2686e5c31af7Sopenharmony_ci		return true;
2687e5c31af7Sopenharmony_ci
2688e5c31af7Sopenharmony_ci	// Inf are always turned into Inf with the same sign, too.
2689e5c31af7Sopenharmony_ci	if (originalFloat.isInf())
2690e5c31af7Sopenharmony_ci	{
2691e5c31af7Sopenharmony_ci		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2692e5c31af7Sopenharmony_ci			return true;
2693e5c31af7Sopenharmony_ci
2694e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2695e5c31af7Sopenharmony_ci		return false;
2696e5c31af7Sopenharmony_ci	}
2697e5c31af7Sopenharmony_ci
2698e5c31af7Sopenharmony_ci	// NaN are always turned into NaN, too.
2699e5c31af7Sopenharmony_ci	if (originalFloat.isNaN())
2700e5c31af7Sopenharmony_ci	{
2701e5c31af7Sopenharmony_ci		if (returnedFloat.isNaN())
2702e5c31af7Sopenharmony_ci			return true;
2703e5c31af7Sopenharmony_ci
2704e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2705e5c31af7Sopenharmony_ci		return false;
2706e5c31af7Sopenharmony_ci	}
2707e5c31af7Sopenharmony_ci
2708e5c31af7Sopenharmony_ci	// In all other cases, conversion should be exact.
2709e5c31af7Sopenharmony_ci	const Float32 expectedFloat (deFloat16To32(original));
2710e5c31af7Sopenharmony_ci	if (expectedFloat.bits() == returnedFloat.bits())
2711e5c31af7Sopenharmony_ci		return true;
2712e5c31af7Sopenharmony_ci
2713e5c31af7Sopenharmony_ci	log << TestLog::Message << "Error: found unmatched 16-bit and 32-bit floats: " << original << " vs " << returnedFloat.bits() << TestLog::EndMessage;
2714e5c31af7Sopenharmony_ci	return false;
2715e5c31af7Sopenharmony_ci}
2716e5c31af7Sopenharmony_ci
2717e5c31af7Sopenharmony_cibool compare16BitFloat (deFloat16 original, deFloat16 returned, std::string& error)
2718e5c31af7Sopenharmony_ci{
2719e5c31af7Sopenharmony_ci	std::ostringstream	log;
2720e5c31af7Sopenharmony_ci	const Float16		originalFloat	(original);
2721e5c31af7Sopenharmony_ci	const Float16		returnedFloat	(returned);
2722e5c31af7Sopenharmony_ci
2723e5c31af7Sopenharmony_ci	if (originalFloat.isZero())
2724e5c31af7Sopenharmony_ci	{
2725e5c31af7Sopenharmony_ci		if (returnedFloat.isZero())
2726e5c31af7Sopenharmony_ci			return true;
2727e5c31af7Sopenharmony_ci
2728e5c31af7Sopenharmony_ci		log << "Error: expected zero but returned " << std::hex << "0x" << returned << " (" << returnedFloat.asFloat() << ")";
2729e5c31af7Sopenharmony_ci		error = log.str();
2730e5c31af7Sopenharmony_ci		return false;
2731e5c31af7Sopenharmony_ci	}
2732e5c31af7Sopenharmony_ci
2733e5c31af7Sopenharmony_ci	// Any denormalized value input into a shader may be flushed to 0.
2734e5c31af7Sopenharmony_ci	if (originalFloat.isDenorm() && returnedFloat.isZero())
2735e5c31af7Sopenharmony_ci		return true;
2736e5c31af7Sopenharmony_ci
2737e5c31af7Sopenharmony_ci	// Inf are always turned into Inf with the same sign, too.
2738e5c31af7Sopenharmony_ci	if (originalFloat.isInf())
2739e5c31af7Sopenharmony_ci	{
2740e5c31af7Sopenharmony_ci		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2741e5c31af7Sopenharmony_ci			return true;
2742e5c31af7Sopenharmony_ci
2743e5c31af7Sopenharmony_ci		log << "Error: expected Inf but returned " << std::hex << "0x" << returned << " (" << returnedFloat.asFloat() << ")";
2744e5c31af7Sopenharmony_ci		error = log.str();
2745e5c31af7Sopenharmony_ci		return false;
2746e5c31af7Sopenharmony_ci	}
2747e5c31af7Sopenharmony_ci
2748e5c31af7Sopenharmony_ci	// NaN are always turned into NaN, too.
2749e5c31af7Sopenharmony_ci	if (originalFloat.isNaN())
2750e5c31af7Sopenharmony_ci	{
2751e5c31af7Sopenharmony_ci		if (returnedFloat.isNaN())
2752e5c31af7Sopenharmony_ci			return true;
2753e5c31af7Sopenharmony_ci
2754e5c31af7Sopenharmony_ci		log << "Error: expected NaN but returned " << std::hex << "0x" << returned << " (" << returnedFloat.asFloat() << ")";
2755e5c31af7Sopenharmony_ci		error = log.str();
2756e5c31af7Sopenharmony_ci		return false;
2757e5c31af7Sopenharmony_ci	}
2758e5c31af7Sopenharmony_ci
2759e5c31af7Sopenharmony_ci	// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2760e5c31af7Sopenharmony_ci	if (originalFloat.isDenorm() && returnedFloat.isZero())
2761e5c31af7Sopenharmony_ci		return true;
2762e5c31af7Sopenharmony_ci
2763e5c31af7Sopenharmony_ci	// If not matched in the above cases, they should have the same bit pattern.
2764e5c31af7Sopenharmony_ci	if (originalFloat.bits() == returnedFloat.bits())
2765e5c31af7Sopenharmony_ci		return true;
2766e5c31af7Sopenharmony_ci
2767e5c31af7Sopenharmony_ci	log << "Error: found unmatched 16-bit and 16-bit floats: 0x"
2768e5c31af7Sopenharmony_ci		<< std::hex << original << " <=> 0x" << returned
2769e5c31af7Sopenharmony_ci		<< " (" << originalFloat.asFloat() << " <=> " << returnedFloat.asFloat() << ")";
2770e5c31af7Sopenharmony_ci	error = log.str();
2771e5c31af7Sopenharmony_ci	return false;
2772e5c31af7Sopenharmony_ci}
2773e5c31af7Sopenharmony_ci
2774e5c31af7Sopenharmony_cibool compare16BitFloat64 (double original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log)
2775e5c31af7Sopenharmony_ci{
2776e5c31af7Sopenharmony_ci	// We only support RTE, RTZ, or both.
2777e5c31af7Sopenharmony_ci	DE_ASSERT(static_cast<int>(flags) > 0 && static_cast<int>(flags) < 4);
2778e5c31af7Sopenharmony_ci
2779e5c31af7Sopenharmony_ci	const Float64	originalFloat	(original);
2780e5c31af7Sopenharmony_ci	const Float16	returnedFloat	(returned);
2781e5c31af7Sopenharmony_ci
2782e5c31af7Sopenharmony_ci	// Zero are turned into zero under both RTE and RTZ.
2783e5c31af7Sopenharmony_ci	if (originalFloat.isZero())
2784e5c31af7Sopenharmony_ci	{
2785e5c31af7Sopenharmony_ci		if (returnedFloat.isZero())
2786e5c31af7Sopenharmony_ci			return true;
2787e5c31af7Sopenharmony_ci
2788e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2789e5c31af7Sopenharmony_ci		return false;
2790e5c31af7Sopenharmony_ci	}
2791e5c31af7Sopenharmony_ci
2792e5c31af7Sopenharmony_ci	// Any denormalized value input into a shader may be flushed to 0.
2793e5c31af7Sopenharmony_ci	if (originalFloat.isDenorm() && returnedFloat.isZero())
2794e5c31af7Sopenharmony_ci		return true;
2795e5c31af7Sopenharmony_ci
2796e5c31af7Sopenharmony_ci	// Inf are always turned into Inf with the same sign, too.
2797e5c31af7Sopenharmony_ci	if (originalFloat.isInf())
2798e5c31af7Sopenharmony_ci	{
2799e5c31af7Sopenharmony_ci		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2800e5c31af7Sopenharmony_ci			return true;
2801e5c31af7Sopenharmony_ci
2802e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2803e5c31af7Sopenharmony_ci		return false;
2804e5c31af7Sopenharmony_ci	}
2805e5c31af7Sopenharmony_ci
2806e5c31af7Sopenharmony_ci	// NaN are always turned into NaN, too.
2807e5c31af7Sopenharmony_ci	if (originalFloat.isNaN())
2808e5c31af7Sopenharmony_ci	{
2809e5c31af7Sopenharmony_ci		if (returnedFloat.isNaN())
2810e5c31af7Sopenharmony_ci			return true;
2811e5c31af7Sopenharmony_ci
2812e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2813e5c31af7Sopenharmony_ci		return false;
2814e5c31af7Sopenharmony_ci	}
2815e5c31af7Sopenharmony_ci
2816e5c31af7Sopenharmony_ci	// Check all rounding modes
2817e5c31af7Sopenharmony_ci	for (int bitNdx = 0; bitNdx < 2; ++bitNdx)
2818e5c31af7Sopenharmony_ci	{
2819e5c31af7Sopenharmony_ci		if ((flags & (1u << bitNdx)) == 0)
2820e5c31af7Sopenharmony_ci			continue;	// This rounding mode is not selected.
2821e5c31af7Sopenharmony_ci
2822e5c31af7Sopenharmony_ci		const Float16	expectedFloat	(deFloat64To16Round(original, deRoundingMode(bitNdx)));
2823e5c31af7Sopenharmony_ci
2824e5c31af7Sopenharmony_ci		// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2825e5c31af7Sopenharmony_ci		if (expectedFloat.isDenorm() && returnedFloat.isZero())
2826e5c31af7Sopenharmony_ci			return true;
2827e5c31af7Sopenharmony_ci
2828e5c31af7Sopenharmony_ci		// If not matched in the above cases, they should have the same bit pattern.
2829e5c31af7Sopenharmony_ci		if (expectedFloat.bits() == returnedFloat.bits())
2830e5c31af7Sopenharmony_ci			return true;
2831e5c31af7Sopenharmony_ci	}
2832e5c31af7Sopenharmony_ci
2833e5c31af7Sopenharmony_ci	log << TestLog::Message << "Error: found unmatched 64-bit and 16-bit floats: " << originalFloat.bits() << " vs " << returned << TestLog::EndMessage;
2834e5c31af7Sopenharmony_ci	return false;
2835e5c31af7Sopenharmony_ci}
2836e5c31af7Sopenharmony_ci
2837e5c31af7Sopenharmony_cibool compare32BitFloat (float expected, float returned, tcu::TestLog& log)
2838e5c31af7Sopenharmony_ci{
2839e5c31af7Sopenharmony_ci	const Float32	expectedFloat	(expected);
2840e5c31af7Sopenharmony_ci	const Float32	returnedFloat	(returned);
2841e5c31af7Sopenharmony_ci
2842e5c31af7Sopenharmony_ci	// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2843e5c31af7Sopenharmony_ci	if (expectedFloat.isDenorm() && returnedFloat.isZero())
2844e5c31af7Sopenharmony_ci		return true;
2845e5c31af7Sopenharmony_ci
2846e5c31af7Sopenharmony_ci	{
2847e5c31af7Sopenharmony_ci		const Float16	originalFloat	(deFloat32To16(expected));
2848e5c31af7Sopenharmony_ci
2849e5c31af7Sopenharmony_ci		// Any denormalized value input into a shader may be flushed to 0.
2850e5c31af7Sopenharmony_ci		if (originalFloat.isDenorm() && returnedFloat.isZero())
2851e5c31af7Sopenharmony_ci			return true;
2852e5c31af7Sopenharmony_ci	}
2853e5c31af7Sopenharmony_ci
2854e5c31af7Sopenharmony_ci	if (expectedFloat.isNaN())
2855e5c31af7Sopenharmony_ci	{
2856e5c31af7Sopenharmony_ci		if (returnedFloat.isNaN())
2857e5c31af7Sopenharmony_ci			return true;
2858e5c31af7Sopenharmony_ci
2859e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2860e5c31af7Sopenharmony_ci		return false;
2861e5c31af7Sopenharmony_ci	}
2862e5c31af7Sopenharmony_ci
2863e5c31af7Sopenharmony_ci	if (returned == expected)
2864e5c31af7Sopenharmony_ci		return true;
2865e5c31af7Sopenharmony_ci
2866e5c31af7Sopenharmony_ci	log << TestLog::Message << "Error: found unmatched 32-bit float: expected " << expectedFloat.bits() << " vs. returned " << returnedFloat.bits() << TestLog::EndMessage;
2867e5c31af7Sopenharmony_ci	return false;
2868e5c31af7Sopenharmony_ci}
2869e5c31af7Sopenharmony_ci
2870e5c31af7Sopenharmony_cibool compare64BitFloat (double expected, double returned, tcu::TestLog& log)
2871e5c31af7Sopenharmony_ci{
2872e5c31af7Sopenharmony_ci	const Float64	expectedDouble	(expected);
2873e5c31af7Sopenharmony_ci	const Float64	returnedDouble	(returned);
2874e5c31af7Sopenharmony_ci
2875e5c31af7Sopenharmony_ci	// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2876e5c31af7Sopenharmony_ci	if (expectedDouble.isDenorm() && returnedDouble.isZero())
2877e5c31af7Sopenharmony_ci		return true;
2878e5c31af7Sopenharmony_ci
2879e5c31af7Sopenharmony_ci	{
2880e5c31af7Sopenharmony_ci		const Float16	originalDouble	(deFloat64To16(expected));
2881e5c31af7Sopenharmony_ci
2882e5c31af7Sopenharmony_ci		// Any denormalized value input into a shader may be flushed to 0.
2883e5c31af7Sopenharmony_ci		if (originalDouble.isDenorm() && returnedDouble.isZero())
2884e5c31af7Sopenharmony_ci			return true;
2885e5c31af7Sopenharmony_ci	}
2886e5c31af7Sopenharmony_ci
2887e5c31af7Sopenharmony_ci	if (expectedDouble.isNaN())
2888e5c31af7Sopenharmony_ci	{
2889e5c31af7Sopenharmony_ci		if (returnedDouble.isNaN())
2890e5c31af7Sopenharmony_ci			return true;
2891e5c31af7Sopenharmony_ci
2892e5c31af7Sopenharmony_ci		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2893e5c31af7Sopenharmony_ci		return false;
2894e5c31af7Sopenharmony_ci	}
2895e5c31af7Sopenharmony_ci
2896e5c31af7Sopenharmony_ci	if (returned == expected)
2897e5c31af7Sopenharmony_ci		return true;
2898e5c31af7Sopenharmony_ci
2899e5c31af7Sopenharmony_ci	log << TestLog::Message << "Error: found unmatched 64-bit float: expected " << expectedDouble.bits() << " vs. returned " << returnedDouble.bits() << TestLog::EndMessage;
2900e5c31af7Sopenharmony_ci	return false;
2901e5c31af7Sopenharmony_ci}
2902e5c31af7Sopenharmony_ci
2903e5c31af7Sopenharmony_ciMove<VkBuffer> createBufferForResource (const DeviceInterface& vk, const VkDevice vkDevice, const Resource& resource, deUint32 queueFamilyIndex)
2904e5c31af7Sopenharmony_ci{
2905e5c31af7Sopenharmony_ci	const vk::VkDescriptorType resourceType = resource.getDescriptorType();
2906e5c31af7Sopenharmony_ci
2907e5c31af7Sopenharmony_ci	vector<deUint8>	resourceBytes;
2908e5c31af7Sopenharmony_ci	resource.getBytes(resourceBytes);
2909e5c31af7Sopenharmony_ci
2910e5c31af7Sopenharmony_ci	const VkBufferCreateInfo	resourceBufferParams	=
2911e5c31af7Sopenharmony_ci	{
2912e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,								// sType
2913e5c31af7Sopenharmony_ci		DE_NULL,															// pNext
2914e5c31af7Sopenharmony_ci		(VkBufferCreateFlags)0,												// flags
2915e5c31af7Sopenharmony_ci		(VkDeviceSize)resourceBytes.size(),									// size
2916e5c31af7Sopenharmony_ci		(VkBufferUsageFlags)getMatchingBufferUsageFlagBit(resourceType),	// usage
2917e5c31af7Sopenharmony_ci		VK_SHARING_MODE_EXCLUSIVE,											// sharingMode
2918e5c31af7Sopenharmony_ci		1u,																	// queueFamilyCount
2919e5c31af7Sopenharmony_ci		&queueFamilyIndex,													// pQueueFamilyIndices
2920e5c31af7Sopenharmony_ci	};
2921e5c31af7Sopenharmony_ci
2922e5c31af7Sopenharmony_ci	return createBuffer(vk, vkDevice, &resourceBufferParams);
2923e5c31af7Sopenharmony_ci}
2924e5c31af7Sopenharmony_ci
2925e5c31af7Sopenharmony_ciMove<VkImage> createImageForResource (const DeviceInterface& vk, const VkDevice vkDevice, const Resource& resource, VkFormat inputFormat, deUint32 queueFamilyIndex)
2926e5c31af7Sopenharmony_ci{
2927e5c31af7Sopenharmony_ci	const VkImageCreateInfo	resourceImageParams	=
2928e5c31af7Sopenharmony_ci	{
2929e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,								//	VkStructureType		sType;
2930e5c31af7Sopenharmony_ci		DE_NULL,															//	const void*			pNext;
2931e5c31af7Sopenharmony_ci		0u,																	//	VkImageCreateFlags	flags;
2932e5c31af7Sopenharmony_ci		VK_IMAGE_TYPE_2D,													//	VkImageType			imageType;
2933e5c31af7Sopenharmony_ci		inputFormat,														//	VkFormat			format;
2934e5c31af7Sopenharmony_ci		{ 8, 8, 1 },														//	VkExtent3D			extent;
2935e5c31af7Sopenharmony_ci		1u,																	//	deUint32			mipLevels;
2936e5c31af7Sopenharmony_ci		1u,																	//	deUint32			arraySize;
2937e5c31af7Sopenharmony_ci		VK_SAMPLE_COUNT_1_BIT,												//	deUint32			samples;
2938e5c31af7Sopenharmony_ci		VK_IMAGE_TILING_OPTIMAL,											//	VkImageTiling		tiling;
2939e5c31af7Sopenharmony_ci		getMatchingImageUsageFlags(resource.getDescriptorType()),			//	VkImageUsageFlags	usage;
2940e5c31af7Sopenharmony_ci		VK_SHARING_MODE_EXCLUSIVE,											//	VkSharingMode		sharingMode;
2941e5c31af7Sopenharmony_ci		1u,																	//	deUint32			queueFamilyCount;
2942e5c31af7Sopenharmony_ci		&queueFamilyIndex,													//	const deUint32*		pQueueFamilyIndices;
2943e5c31af7Sopenharmony_ci		VK_IMAGE_LAYOUT_UNDEFINED											//	VkImageLayout		initialLayout;
2944e5c31af7Sopenharmony_ci	};
2945e5c31af7Sopenharmony_ci
2946e5c31af7Sopenharmony_ci	return createImage(vk, vkDevice, &resourceImageParams);
2947e5c31af7Sopenharmony_ci}
2948e5c31af7Sopenharmony_ci
2949e5c31af7Sopenharmony_civoid copyBufferToImage (Context& context, const DeviceInterface& vk, const VkDevice& device, const VkQueue& queue, VkCommandPool cmdPool, VkCommandBuffer cmdBuffer, VkBuffer buffer, VkImage image, VkImageAspectFlags aspect)
2950e5c31af7Sopenharmony_ci{
2951e5c31af7Sopenharmony_ci	const VkBufferImageCopy			copyRegion			=
2952e5c31af7Sopenharmony_ci	{
2953e5c31af7Sopenharmony_ci		0u,												// VkDeviceSize				bufferOffset;
2954e5c31af7Sopenharmony_ci		0u,												// deUint32					bufferRowLength;
2955e5c31af7Sopenharmony_ci		0u,												// deUint32					bufferImageHeight;
2956e5c31af7Sopenharmony_ci		{
2957e5c31af7Sopenharmony_ci			aspect,											// VkImageAspectFlags		aspect;
2958e5c31af7Sopenharmony_ci			0u,												// deUint32					mipLevel;
2959e5c31af7Sopenharmony_ci			0u,												// deUint32					baseArrayLayer;
2960e5c31af7Sopenharmony_ci			1u,												// deUint32					layerCount;
2961e5c31af7Sopenharmony_ci		},												// VkImageSubresourceLayers	imageSubresource;
2962e5c31af7Sopenharmony_ci		{ 0, 0, 0 },									// VkOffset3D				imageOffset;
2963e5c31af7Sopenharmony_ci		{ 8, 8, 1 }										// VkExtent3D				imageExtent;
2964e5c31af7Sopenharmony_ci	};
2965e5c31af7Sopenharmony_ci
2966e5c31af7Sopenharmony_ci	// Copy buffer to image
2967e5c31af7Sopenharmony_ci	beginCommandBuffer(vk, cmdBuffer);
2968e5c31af7Sopenharmony_ci
2969e5c31af7Sopenharmony_ci	copyBufferToImage(vk, cmdBuffer, buffer, VK_WHOLE_SIZE, vector<VkBufferImageCopy>(1, copyRegion), aspect, 1u, 1u, image, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
2970e5c31af7Sopenharmony_ci
2971e5c31af7Sopenharmony_ci	endCommandBuffer(vk, cmdBuffer);
2972e5c31af7Sopenharmony_ci
2973e5c31af7Sopenharmony_ci	submitCommandsAndWait(vk, device, queue, cmdBuffer);
2974e5c31af7Sopenharmony_ci	context.resetCommandPoolForVKSC(device, cmdPool);
2975e5c31af7Sopenharmony_ci}
2976e5c31af7Sopenharmony_ci
2977e5c31af7Sopenharmony_ciVkImageAspectFlags getImageAspectFlags (VkFormat format)
2978e5c31af7Sopenharmony_ci{
2979e5c31af7Sopenharmony_ci	const tcu::TextureFormat::ChannelOrder	channelOrder	= vk::mapVkFormat(format).order;
2980e5c31af7Sopenharmony_ci	VkImageAspectFlags						aspectFlags		= (VkImageAspectFlags)0u;
2981e5c31af7Sopenharmony_ci
2982e5c31af7Sopenharmony_ci	if (tcu::hasDepthComponent(channelOrder))
2983e5c31af7Sopenharmony_ci		aspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
2984e5c31af7Sopenharmony_ci
2985e5c31af7Sopenharmony_ci	if (tcu::hasStencilComponent(channelOrder))
2986e5c31af7Sopenharmony_ci		aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
2987e5c31af7Sopenharmony_ci
2988e5c31af7Sopenharmony_ci	if (!aspectFlags)
2989e5c31af7Sopenharmony_ci		aspectFlags |= VK_IMAGE_ASPECT_COLOR_BIT;
2990e5c31af7Sopenharmony_ci
2991e5c31af7Sopenharmony_ci	return aspectFlags;
2992e5c31af7Sopenharmony_ci}
2993e5c31af7Sopenharmony_ci
2994e5c31af7Sopenharmony_ciTestStatus runAndVerifyUnusedVariablePipeline (Context &context, UnusedVariableContext unusedVariableContext)
2995e5c31af7Sopenharmony_ci{
2996e5c31af7Sopenharmony_ci	return runAndVerifyDefaultPipeline(context, unusedVariableContext.instanceContext);
2997e5c31af7Sopenharmony_ci}
2998e5c31af7Sopenharmony_ci
2999e5c31af7Sopenharmony_ciTestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance)
3000e5c31af7Sopenharmony_ci{
3001e5c31af7Sopenharmony_ci	if (getMinRequiredVulkanVersion(instance.resources.spirvVersion) > context.getUsedApiVersion())
3002e5c31af7Sopenharmony_ci	{
3003e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, string("Vulkan higher than or equal to " + getVulkanName(getMinRequiredVulkanVersion(instance.resources.spirvVersion)) + " is required for this test to run").c_str());
3004e5c31af7Sopenharmony_ci	}
3005e5c31af7Sopenharmony_ci
3006e5c31af7Sopenharmony_ci	const DeviceInterface&						vk						= context.getDeviceInterface();
3007e5c31af7Sopenharmony_ci	const InstanceInterface&					vkInstance				= context.getInstanceInterface();
3008e5c31af7Sopenharmony_ci	const VkPhysicalDevice						vkPhysicalDevice		= context.getPhysicalDevice();
3009e5c31af7Sopenharmony_ci	const deUint32								queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
3010e5c31af7Sopenharmony_ci	const VkQueue								queue					= context.getUniversalQueue();
3011e5c31af7Sopenharmony_ci	const VkDevice&								device					= context.getDevice();
3012e5c31af7Sopenharmony_ci	Allocator&									allocator				= context.getDefaultAllocator();
3013e5c31af7Sopenharmony_ci	vector<ModuleHandleSp>						modules;
3014e5c31af7Sopenharmony_ci	map<VkShaderStageFlagBits, VkShaderModule>	moduleByStage;
3015e5c31af7Sopenharmony_ci	const deUint32								fullRenderSize			= 256;
3016e5c31af7Sopenharmony_ci	const deUint32								quarterRenderSize		= 64;
3017e5c31af7Sopenharmony_ci	const tcu::UVec2							renderSize				(fullRenderSize, fullRenderSize);
3018e5c31af7Sopenharmony_ci	const int									testSpecificSeed		= 31354125;
3019e5c31af7Sopenharmony_ci	const int									seed					= context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed;
3020e5c31af7Sopenharmony_ci	bool										supportsGeometry		= false;
3021e5c31af7Sopenharmony_ci	bool										supportsTessellation	= false;
3022e5c31af7Sopenharmony_ci	bool										hasGeometry				= false;
3023e5c31af7Sopenharmony_ci	bool										hasTessellation			= false;
3024e5c31af7Sopenharmony_ci	const bool									hasPushConstants		= !instance.pushConstants.empty();
3025e5c31af7Sopenharmony_ci	const deUint32								numInResources			= static_cast<deUint32>(instance.resources.inputs.size());
3026e5c31af7Sopenharmony_ci	const deUint32								numOutResources			= static_cast<deUint32>(instance.resources.outputs.size());
3027e5c31af7Sopenharmony_ci	const deUint32								numResources			= numInResources + numOutResources;
3028e5c31af7Sopenharmony_ci	const bool									needInterface			= !instance.interfaces.empty();
3029e5c31af7Sopenharmony_ci	const VkPhysicalDeviceFeatures&				features				= context.getDeviceFeatures();
3030e5c31af7Sopenharmony_ci	const Vec4									defaulClearColor		(0.125f, 0.25f, 0.75f, 1.0f);
3031e5c31af7Sopenharmony_ci	bool										splitRenderArea			= instance.splitRenderArea;
3032e5c31af7Sopenharmony_ci
3033e5c31af7Sopenharmony_ci	const deUint32								renderDimension			= splitRenderArea ? quarterRenderSize : fullRenderSize;
3034e5c31af7Sopenharmony_ci	const int									numRenderSegments		= splitRenderArea ? 4 : 1;
3035e5c31af7Sopenharmony_ci
3036e5c31af7Sopenharmony_ci	supportsGeometry		= features.geometryShader == VK_TRUE;
3037e5c31af7Sopenharmony_ci	supportsTessellation	= features.tessellationShader == VK_TRUE;
3038e5c31af7Sopenharmony_ci	hasGeometry				= (instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT);
3039e5c31af7Sopenharmony_ci	hasTessellation			= (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) ||
3040e5c31af7Sopenharmony_ci								(instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3041e5c31af7Sopenharmony_ci
3042e5c31af7Sopenharmony_ci	if (hasGeometry && !supportsGeometry)
3043e5c31af7Sopenharmony_ci	{
3044e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Geometry not supported");
3045e5c31af7Sopenharmony_ci	}
3046e5c31af7Sopenharmony_ci
3047e5c31af7Sopenharmony_ci	if (hasTessellation && !supportsTessellation)
3048e5c31af7Sopenharmony_ci	{
3049e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, "Tessellation not supported");
3050e5c31af7Sopenharmony_ci	}
3051e5c31af7Sopenharmony_ci
3052e5c31af7Sopenharmony_ci	// Check all required extensions are supported
3053e5c31af7Sopenharmony_ci	for (std::vector<std::string>::const_iterator i = instance.requiredDeviceExtensions.begin(); i != instance.requiredDeviceExtensions.end(); ++i)
3054e5c31af7Sopenharmony_ci	{
3055e5c31af7Sopenharmony_ci		if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), *i))
3056e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, (std::string("Extension not supported: ") + *i).c_str());
3057e5c31af7Sopenharmony_ci	}
3058e5c31af7Sopenharmony_ci
3059e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
3060e5c31af7Sopenharmony_ci	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
3061e5c31af7Sopenharmony_ci		!context.getPortabilitySubsetFeatures().mutableComparisonSamplers)
3062e5c31af7Sopenharmony_ci	{
3063e5c31af7Sopenharmony_ci		// In portability when mutableComparisonSamplers is false then
3064e5c31af7Sopenharmony_ci		// VkSamplerCreateInfo can't have compareEnable set to true
3065e5c31af7Sopenharmony_ci		for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
3066e5c31af7Sopenharmony_ci		{
3067e5c31af7Sopenharmony_ci			const Resource&	resource	= instance.resources.inputs[inputNdx];
3068e5c31af7Sopenharmony_ci			const bool		hasSampler	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
3069e5c31af7Sopenharmony_ci										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLER) ||
3070e5c31af7Sopenharmony_ci										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3071e5c31af7Sopenharmony_ci			if (hasSampler &&
3072e5c31af7Sopenharmony_ci				tcu::hasDepthComponent(vk::mapVkFormat(instance.resources.inputFormat).order))
3073e5c31af7Sopenharmony_ci			{
3074e5c31af7Sopenharmony_ci				TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: mutableComparisonSamplers are not supported by this implementation");
3075e5c31af7Sopenharmony_ci			}
3076e5c31af7Sopenharmony_ci		}
3077e5c31af7Sopenharmony_ci	}
3078e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
3079e5c31af7Sopenharmony_ci
3080e5c31af7Sopenharmony_ci	{
3081e5c31af7Sopenharmony_ci		VulkanFeatures localRequired = instance.requestedFeatures;
3082e5c31af7Sopenharmony_ci
3083e5c31af7Sopenharmony_ci		const VkShaderStageFlags		vertexPipelineStoresAndAtomicsAffected	= vk::VK_SHADER_STAGE_VERTEX_BIT
3084e5c31af7Sopenharmony_ci																				| vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT
3085e5c31af7Sopenharmony_ci																				| vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT
3086e5c31af7Sopenharmony_ci																				| vk::VK_SHADER_STAGE_GEOMETRY_BIT;
3087e5c31af7Sopenharmony_ci
3088e5c31af7Sopenharmony_ci		// reset fragment stores and atomics feature requirement
3089e5c31af7Sopenharmony_ci		if ((localRequired.coreFeatures.fragmentStoresAndAtomics != DE_FALSE) &&
3090e5c31af7Sopenharmony_ci			(instance.customizedStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) == 0)
3091e5c31af7Sopenharmony_ci		{
3092e5c31af7Sopenharmony_ci			localRequired.coreFeatures.fragmentStoresAndAtomics = DE_FALSE;
3093e5c31af7Sopenharmony_ci		}
3094e5c31af7Sopenharmony_ci
3095e5c31af7Sopenharmony_ci		// reset vertex pipeline stores and atomics feature requirement
3096e5c31af7Sopenharmony_ci		if (localRequired.coreFeatures.vertexPipelineStoresAndAtomics != DE_FALSE &&
3097e5c31af7Sopenharmony_ci			(instance.customizedStages & vertexPipelineStoresAndAtomicsAffected) == 0)
3098e5c31af7Sopenharmony_ci		{
3099e5c31af7Sopenharmony_ci			localRequired.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE;
3100e5c31af7Sopenharmony_ci		}
3101e5c31af7Sopenharmony_ci
3102e5c31af7Sopenharmony_ci		const char* unsupportedFeature = DE_NULL;
3103e5c31af7Sopenharmony_ci		if (!isVulkanFeaturesSupported(context, localRequired, &unsupportedFeature))
3104e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, std::string("At least following requested feature not supported: ") + unsupportedFeature);
3105e5c31af7Sopenharmony_ci	}
3106e5c31af7Sopenharmony_ci
3107e5c31af7Sopenharmony_ci	// Check Interface Input/Output formats are supported
3108e5c31af7Sopenharmony_ci	if (needInterface)
3109e5c31af7Sopenharmony_ci	{
3110e5c31af7Sopenharmony_ci		VkFormatProperties formatProperties;
3111e5c31af7Sopenharmony_ci		vkInstance.getPhysicalDeviceFormatProperties(vkPhysicalDevice, instance.interfaces.getInputType().getVkFormat(), &formatProperties);
3112e5c31af7Sopenharmony_ci		if ((formatProperties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0)
3113e5c31af7Sopenharmony_ci		{
3114e5c31af7Sopenharmony_ci			std::string	error				= "Interface Input format (";
3115e5c31af7Sopenharmony_ci			const std::string formatName	= getFormatName(instance.interfaces.getInputType().getVkFormat());
3116e5c31af7Sopenharmony_ci			error += formatName + ") not supported";
3117e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, error.c_str());
3118e5c31af7Sopenharmony_ci		}
3119e5c31af7Sopenharmony_ci
3120e5c31af7Sopenharmony_ci		vkInstance.getPhysicalDeviceFormatProperties(vkPhysicalDevice, instance.interfaces.getOutputType().getVkFormat(), &formatProperties);
3121e5c31af7Sopenharmony_ci		if (((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0) ||
3122e5c31af7Sopenharmony_ci			((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0))
3123e5c31af7Sopenharmony_ci		{
3124e5c31af7Sopenharmony_ci			std::string	error				= "Interface Output format (";
3125e5c31af7Sopenharmony_ci			const std::string formatName	= getFormatName(instance.interfaces.getInputType().getVkFormat());
3126e5c31af7Sopenharmony_ci			error += formatName + ") not supported";
3127e5c31af7Sopenharmony_ci			TCU_THROW(NotSupportedError, error.c_str());
3128e5c31af7Sopenharmony_ci		}
3129e5c31af7Sopenharmony_ci	}
3130e5c31af7Sopenharmony_ci
3131e5c31af7Sopenharmony_ci	de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4);
3132e5c31af7Sopenharmony_ci	de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4);
3133e5c31af7Sopenharmony_ci	const Vec4								vertexData[]			=
3134e5c31af7Sopenharmony_ci	{
3135e5c31af7Sopenharmony_ci		// Upper left corner:
3136e5c31af7Sopenharmony_ci		Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),	//1
3137e5c31af7Sopenharmony_ci		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),	//2
3138e5c31af7Sopenharmony_ci		Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(),	//3
3139e5c31af7Sopenharmony_ci
3140e5c31af7Sopenharmony_ci		// Upper right corner:
3141e5c31af7Sopenharmony_ci		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),	//4
3142e5c31af7Sopenharmony_ci		Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),	//5
3143e5c31af7Sopenharmony_ci		Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(),	//6
3144e5c31af7Sopenharmony_ci
3145e5c31af7Sopenharmony_ci		// Lower left corner:
3146e5c31af7Sopenharmony_ci		Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(),	//7
3147e5c31af7Sopenharmony_ci		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),	//8
3148e5c31af7Sopenharmony_ci		Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),	//9
3149e5c31af7Sopenharmony_ci
3150e5c31af7Sopenharmony_ci		// Lower right corner:
3151e5c31af7Sopenharmony_ci		Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(),	//10
3152e5c31af7Sopenharmony_ci		Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(),	//11
3153e5c31af7Sopenharmony_ci		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(),	//12
3154e5c31af7Sopenharmony_ci
3155e5c31af7Sopenharmony_ci		// The rest is used only renderFullSquare specified. Fills area already filled with clear color
3156e5c31af7Sopenharmony_ci		// Left 1
3157e5c31af7Sopenharmony_ci		Vec4(-1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor,					//3
3158e5c31af7Sopenharmony_ci		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//2
3159e5c31af7Sopenharmony_ci		Vec4(-1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor,					//7
3160e5c31af7Sopenharmony_ci
3161e5c31af7Sopenharmony_ci		// Left 2
3162e5c31af7Sopenharmony_ci		Vec4(-1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor,					//7
3163e5c31af7Sopenharmony_ci		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//2
3164e5c31af7Sopenharmony_ci		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//8
3165e5c31af7Sopenharmony_ci
3166e5c31af7Sopenharmony_ci		// Left-Center
3167e5c31af7Sopenharmony_ci		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//8
3168e5c31af7Sopenharmony_ci		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//2
3169e5c31af7Sopenharmony_ci		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//4
3170e5c31af7Sopenharmony_ci
3171e5c31af7Sopenharmony_ci		// Right-Center
3172e5c31af7Sopenharmony_ci		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//4
3173e5c31af7Sopenharmony_ci		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//12
3174e5c31af7Sopenharmony_ci		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//8
3175e5c31af7Sopenharmony_ci
3176e5c31af7Sopenharmony_ci		// Right 2
3177e5c31af7Sopenharmony_ci		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//4
3178e5c31af7Sopenharmony_ci		Vec4(+1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor,					//6
3179e5c31af7Sopenharmony_ci		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//12
3180e5c31af7Sopenharmony_ci
3181e5c31af7Sopenharmony_ci		// Right 1
3182e5c31af7Sopenharmony_ci		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//12
3183e5c31af7Sopenharmony_ci		Vec4(+1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor,					//6
3184e5c31af7Sopenharmony_ci		Vec4(+1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor,					//10
3185e5c31af7Sopenharmony_ci	};
3186e5c31af7Sopenharmony_ci
3187e5c31af7Sopenharmony_ci	const size_t							singleVertexDataSize	= 2 * sizeof(Vec4);
3188e5c31af7Sopenharmony_ci	const size_t							vertexCount				= instance.renderFullSquare ? sizeof(vertexData) / singleVertexDataSize : 4*3;
3189e5c31af7Sopenharmony_ci	const size_t							vertexDataSize			= vertexCount * singleVertexDataSize;
3190e5c31af7Sopenharmony_ci
3191e5c31af7Sopenharmony_ci	Move<VkBuffer>							vertexInputBuffer;
3192e5c31af7Sopenharmony_ci	de::MovePtr<Allocation>					vertexInputMemory;
3193e5c31af7Sopenharmony_ci	Move<VkBuffer>							fragOutputBuffer;
3194e5c31af7Sopenharmony_ci	de::MovePtr<Allocation>					fragOutputMemory;
3195e5c31af7Sopenharmony_ci	Move<VkImage>							fragOutputImage;
3196e5c31af7Sopenharmony_ci	de::MovePtr<Allocation>					fragOutputImageMemory;
3197e5c31af7Sopenharmony_ci	Move<VkImageView>						fragOutputImageView;
3198e5c31af7Sopenharmony_ci
3199e5c31af7Sopenharmony_ci	const VkBufferCreateInfo				vertexBufferParams		=
3200e5c31af7Sopenharmony_ci	{
3201e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	//	VkStructureType		sType;
3202e5c31af7Sopenharmony_ci		DE_NULL,								//	const void*			pNext;
3203e5c31af7Sopenharmony_ci		0u,										//	VkBufferCreateFlags	flags;
3204e5c31af7Sopenharmony_ci		(VkDeviceSize)vertexDataSize,			//	VkDeviceSize		size;
3205e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,		//	VkBufferUsageFlags	usage;
3206e5c31af7Sopenharmony_ci		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode		sharingMode;
3207e5c31af7Sopenharmony_ci		1u,										//	deUint32			queueFamilyCount;
3208e5c31af7Sopenharmony_ci		&queueFamilyIndex,						//	const deUint32*		pQueueFamilyIndices;
3209e5c31af7Sopenharmony_ci	};
3210e5c31af7Sopenharmony_ci	const Unique<VkBuffer>					vertexBuffer			(createBuffer(vk, device, &vertexBufferParams));
3211e5c31af7Sopenharmony_ci	const UniquePtr<Allocation>				vertexBufferMemory		(allocator.allocate(getBufferMemoryRequirements(vk, device, *vertexBuffer), MemoryRequirement::HostVisible));
3212e5c31af7Sopenharmony_ci
3213e5c31af7Sopenharmony_ci	VK_CHECK(vk.bindBufferMemory(device, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
3214e5c31af7Sopenharmony_ci
3215e5c31af7Sopenharmony_ci	const VkDeviceSize						imageSizeBytes			= (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y());
3216e5c31af7Sopenharmony_ci	const VkBufferCreateInfo				readImageBufferParams	=
3217e5c31af7Sopenharmony_ci	{
3218e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
3219e5c31af7Sopenharmony_ci		DE_NULL,									//	const void*			pNext;
3220e5c31af7Sopenharmony_ci		0u,											//	VkBufferCreateFlags	flags;
3221e5c31af7Sopenharmony_ci		imageSizeBytes,								//	VkDeviceSize		size;
3222e5c31af7Sopenharmony_ci		VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//	VkBufferUsageFlags	usage;
3223e5c31af7Sopenharmony_ci		VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
3224e5c31af7Sopenharmony_ci		1u,											//	deUint32			queueFamilyCount;
3225e5c31af7Sopenharmony_ci		&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
3226e5c31af7Sopenharmony_ci	};
3227e5c31af7Sopenharmony_ci	const Unique<VkBuffer>					readImageBuffer			(createBuffer(vk, device, &readImageBufferParams));
3228e5c31af7Sopenharmony_ci	const UniquePtr<Allocation>				readImageBufferMemory	(allocator.allocate(getBufferMemoryRequirements(vk, device, *readImageBuffer), MemoryRequirement::HostVisible));
3229e5c31af7Sopenharmony_ci
3230e5c31af7Sopenharmony_ci	VK_CHECK(vk.bindBufferMemory(device, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
3231e5c31af7Sopenharmony_ci
3232e5c31af7Sopenharmony_ci	VkImageCreateInfo						imageParams				=
3233e5c31af7Sopenharmony_ci	{
3234e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									//	VkStructureType		sType;
3235e5c31af7Sopenharmony_ci		DE_NULL,																//	const void*			pNext;
3236e5c31af7Sopenharmony_ci		0u,																		//	VkImageCreateFlags	flags;
3237e5c31af7Sopenharmony_ci		VK_IMAGE_TYPE_2D,														//	VkImageType			imageType;
3238e5c31af7Sopenharmony_ci		VK_FORMAT_R8G8B8A8_UNORM,												//	VkFormat			format;
3239e5c31af7Sopenharmony_ci		{ renderSize.x(), renderSize.y(), 1 },									//	VkExtent3D			extent;
3240e5c31af7Sopenharmony_ci		1u,																		//	deUint32			mipLevels;
3241e5c31af7Sopenharmony_ci		1u,																		//	deUint32			arraySize;
3242e5c31af7Sopenharmony_ci		VK_SAMPLE_COUNT_1_BIT,													//	deUint32			samples;
3243e5c31af7Sopenharmony_ci		VK_IMAGE_TILING_OPTIMAL,												//	VkImageTiling		tiling;
3244e5c31af7Sopenharmony_ci		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	//	VkImageUsageFlags	usage;
3245e5c31af7Sopenharmony_ci		VK_SHARING_MODE_EXCLUSIVE,												//	VkSharingMode		sharingMode;
3246e5c31af7Sopenharmony_ci		1u,																		//	deUint32			queueFamilyCount;
3247e5c31af7Sopenharmony_ci		&queueFamilyIndex,														//	const deUint32*		pQueueFamilyIndices;
3248e5c31af7Sopenharmony_ci		VK_IMAGE_LAYOUT_UNDEFINED,												//	VkImageLayout		initialLayout;
3249e5c31af7Sopenharmony_ci	};
3250e5c31af7Sopenharmony_ci
3251e5c31af7Sopenharmony_ci	const Unique<VkImage>					image					(createImage(vk, device, &imageParams));
3252e5c31af7Sopenharmony_ci	const UniquePtr<Allocation>				imageMemory				(allocator.allocate(getImageMemoryRequirements(vk, device, *image), MemoryRequirement::Any));
3253e5c31af7Sopenharmony_ci
3254e5c31af7Sopenharmony_ci	VK_CHECK(vk.bindImageMemory(device, *image, imageMemory->getMemory(), imageMemory->getOffset()));
3255e5c31af7Sopenharmony_ci
3256e5c31af7Sopenharmony_ci	if (needInterface)
3257e5c31af7Sopenharmony_ci	{
3258e5c31af7Sopenharmony_ci		// The pipeline renders four triangles, each with three vertexes.
3259e5c31af7Sopenharmony_ci		// Test instantialization only provides four data points, each
3260e5c31af7Sopenharmony_ci		// for one triangle. So we need allocate space of three times of
3261e5c31af7Sopenharmony_ci		// input buffer's size.
3262e5c31af7Sopenharmony_ci		vector<deUint8>							inputBufferBytes;
3263e5c31af7Sopenharmony_ci		instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
3264e5c31af7Sopenharmony_ci
3265e5c31af7Sopenharmony_ci		const deUint32							inputNumBytes			= deUint32(inputBufferBytes.size() * 3);
3266e5c31af7Sopenharmony_ci		// Create an additional buffer and backing memory for one input variable.
3267e5c31af7Sopenharmony_ci		const VkBufferCreateInfo				vertexInputParams		=
3268e5c31af7Sopenharmony_ci		{
3269e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
3270e5c31af7Sopenharmony_ci			DE_NULL,									//	const void*			pNext;
3271e5c31af7Sopenharmony_ci			0u,											//	VkBufferCreateFlags	flags;
3272e5c31af7Sopenharmony_ci			inputNumBytes,								//	VkDeviceSize		size;
3273e5c31af7Sopenharmony_ci			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			//	VkBufferUsageFlags	usage;
3274e5c31af7Sopenharmony_ci			VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
3275e5c31af7Sopenharmony_ci			1u,											//	deUint32			queueFamilyCount;
3276e5c31af7Sopenharmony_ci			&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
3277e5c31af7Sopenharmony_ci		};
3278e5c31af7Sopenharmony_ci
3279e5c31af7Sopenharmony_ci		vertexInputBuffer = createBuffer(vk, device, &vertexInputParams);
3280e5c31af7Sopenharmony_ci		vertexInputMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *vertexInputBuffer), MemoryRequirement::HostVisible);
3281e5c31af7Sopenharmony_ci		VK_CHECK(vk.bindBufferMemory(device, *vertexInputBuffer, vertexInputMemory->getMemory(), vertexInputMemory->getOffset()));
3282e5c31af7Sopenharmony_ci
3283e5c31af7Sopenharmony_ci		// Create an additional buffer and backing memory for an output variable.
3284e5c31af7Sopenharmony_ci		const VkDeviceSize						fragOutputImgSize		= (VkDeviceSize)(instance.interfaces.getOutputType().getNumBytes() * renderSize.x() * renderSize.y());
3285e5c31af7Sopenharmony_ci		const VkBufferCreateInfo				fragOutputParams		=
3286e5c31af7Sopenharmony_ci		{
3287e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
3288e5c31af7Sopenharmony_ci			DE_NULL,									//	const void*			pNext;
3289e5c31af7Sopenharmony_ci			0u,											//	VkBufferCreateFlags	flags;
3290e5c31af7Sopenharmony_ci			fragOutputImgSize,							//	VkDeviceSize		size;
3291e5c31af7Sopenharmony_ci			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//	VkBufferUsageFlags	usage;
3292e5c31af7Sopenharmony_ci			VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
3293e5c31af7Sopenharmony_ci			1u,											//	deUint32			queueFamilyCount;
3294e5c31af7Sopenharmony_ci			&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
3295e5c31af7Sopenharmony_ci		};
3296e5c31af7Sopenharmony_ci		fragOutputBuffer = createBuffer(vk, device, &fragOutputParams);
3297e5c31af7Sopenharmony_ci		fragOutputMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *fragOutputBuffer), MemoryRequirement::HostVisible);
3298e5c31af7Sopenharmony_ci		VK_CHECK(vk.bindBufferMemory(device, *fragOutputBuffer, fragOutputMemory->getMemory(), fragOutputMemory->getOffset()));
3299e5c31af7Sopenharmony_ci
3300e5c31af7Sopenharmony_ci		// Create an additional image and backing memory for attachment.
3301e5c31af7Sopenharmony_ci		// Reuse the previous imageParams since we only need to change the image format.
3302e5c31af7Sopenharmony_ci		imageParams.format		= instance.interfaces.getOutputType().getVkFormat();
3303e5c31af7Sopenharmony_ci
3304e5c31af7Sopenharmony_ci		// Check the usage bits on the given image format are supported.
3305e5c31af7Sopenharmony_ci		requireFormatUsageSupport(vkInstance, vkPhysicalDevice, imageParams.format, imageParams.tiling, imageParams.usage);
3306e5c31af7Sopenharmony_ci
3307e5c31af7Sopenharmony_ci		fragOutputImage			= createImage(vk, device, &imageParams);
3308e5c31af7Sopenharmony_ci		fragOutputImageMemory	= allocator.allocate(getImageMemoryRequirements(vk, device, *fragOutputImage), MemoryRequirement::Any);
3309e5c31af7Sopenharmony_ci
3310e5c31af7Sopenharmony_ci		VK_CHECK(vk.bindImageMemory(device, *fragOutputImage, fragOutputImageMemory->getMemory(), fragOutputImageMemory->getOffset()));
3311e5c31af7Sopenharmony_ci	}
3312e5c31af7Sopenharmony_ci
3313e5c31af7Sopenharmony_ci	vector<VkAttachmentDescription>			colorAttDescs;
3314e5c31af7Sopenharmony_ci	vector<VkAttachmentReference>			colorAttRefs;
3315e5c31af7Sopenharmony_ci	{
3316e5c31af7Sopenharmony_ci		const VkAttachmentDescription		attDesc					=
3317e5c31af7Sopenharmony_ci		{
3318e5c31af7Sopenharmony_ci			0u,												//	VkAttachmentDescriptionFlags	flags;
3319e5c31af7Sopenharmony_ci			VK_FORMAT_R8G8B8A8_UNORM,						//	VkFormat						format;
3320e5c31af7Sopenharmony_ci			VK_SAMPLE_COUNT_1_BIT,							//	deUint32						samples;
3321e5c31af7Sopenharmony_ci			VK_ATTACHMENT_LOAD_OP_CLEAR,					//	VkAttachmentLoadOp				loadOp;
3322e5c31af7Sopenharmony_ci			VK_ATTACHMENT_STORE_OP_STORE,					//	VkAttachmentStoreOp				storeOp;
3323e5c31af7Sopenharmony_ci			VK_ATTACHMENT_LOAD_OP_DONT_CARE,				//	VkAttachmentLoadOp				stencilLoadOp;
3324e5c31af7Sopenharmony_ci			VK_ATTACHMENT_STORE_OP_DONT_CARE,				//	VkAttachmentStoreOp				stencilStoreOp;
3325e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout					initialLayout;
3326e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout					finalLayout;
3327e5c31af7Sopenharmony_ci		};
3328e5c31af7Sopenharmony_ci		colorAttDescs.push_back(attDesc);
3329e5c31af7Sopenharmony_ci
3330e5c31af7Sopenharmony_ci		const VkAttachmentReference			attRef					=
3331e5c31af7Sopenharmony_ci		{
3332e5c31af7Sopenharmony_ci			0u,												//	deUint32		attachment;
3333e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout	layout;
3334e5c31af7Sopenharmony_ci		};
3335e5c31af7Sopenharmony_ci		colorAttRefs.push_back(attRef);
3336e5c31af7Sopenharmony_ci	}
3337e5c31af7Sopenharmony_ci
3338e5c31af7Sopenharmony_ci	if (needInterface)
3339e5c31af7Sopenharmony_ci	{
3340e5c31af7Sopenharmony_ci		const VkAttachmentDescription		attDesc					=
3341e5c31af7Sopenharmony_ci		{
3342e5c31af7Sopenharmony_ci			0u,													//	VkAttachmentDescriptionFlags	flags;
3343e5c31af7Sopenharmony_ci			instance.interfaces.getOutputType().getVkFormat(),	//	VkFormat						format;
3344e5c31af7Sopenharmony_ci			VK_SAMPLE_COUNT_1_BIT,								//	deUint32						samples;
3345e5c31af7Sopenharmony_ci			VK_ATTACHMENT_LOAD_OP_CLEAR,						//	VkAttachmentLoadOp				loadOp;
3346e5c31af7Sopenharmony_ci			VK_ATTACHMENT_STORE_OP_STORE,						//	VkAttachmentStoreOp				storeOp;
3347e5c31af7Sopenharmony_ci			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					//	VkAttachmentLoadOp				stencilLoadOp;
3348e5c31af7Sopenharmony_ci			VK_ATTACHMENT_STORE_OP_DONT_CARE,					//	VkAttachmentStoreOp				stencilStoreOp;
3349e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			//	VkImageLayout					initialLayout;
3350e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			//	VkImageLayout					finalLayout;
3351e5c31af7Sopenharmony_ci		};
3352e5c31af7Sopenharmony_ci		colorAttDescs.push_back(attDesc);
3353e5c31af7Sopenharmony_ci
3354e5c31af7Sopenharmony_ci		const VkAttachmentReference			attRef					=
3355e5c31af7Sopenharmony_ci		{
3356e5c31af7Sopenharmony_ci			1u,												//	deUint32		attachment;
3357e5c31af7Sopenharmony_ci			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout	layout;
3358e5c31af7Sopenharmony_ci		};
3359e5c31af7Sopenharmony_ci		colorAttRefs.push_back(attRef);
3360e5c31af7Sopenharmony_ci	}
3361e5c31af7Sopenharmony_ci
3362e5c31af7Sopenharmony_ci	VkSubpassDescription					subpassDesc				=
3363e5c31af7Sopenharmony_ci	{
3364e5c31af7Sopenharmony_ci		0u,												//	VkSubpassDescriptionFlags		flags;
3365e5c31af7Sopenharmony_ci		VK_PIPELINE_BIND_POINT_GRAPHICS,				//	VkPipelineBindPoint				pipelineBindPoint;
3366e5c31af7Sopenharmony_ci		0u,												//	deUint32						inputCount;
3367e5c31af7Sopenharmony_ci		DE_NULL,										//	const VkAttachmentReference*	pInputAttachments;
3368e5c31af7Sopenharmony_ci		1u,												//	deUint32						colorCount;
3369e5c31af7Sopenharmony_ci		colorAttRefs.data(),							//	const VkAttachmentReference*	pColorAttachments;
3370e5c31af7Sopenharmony_ci		DE_NULL,										//	const VkAttachmentReference*	pResolveAttachments;
3371e5c31af7Sopenharmony_ci		DE_NULL,										//	const VkAttachmentReference*	pDepthStencilAttachment;
3372e5c31af7Sopenharmony_ci		0u,												//	deUint32						preserveCount;
3373e5c31af7Sopenharmony_ci		DE_NULL,										//	const VkAttachmentReference*	pPreserveAttachments;
3374e5c31af7Sopenharmony_ci
3375e5c31af7Sopenharmony_ci	};
3376e5c31af7Sopenharmony_ci	VkRenderPassCreateInfo					renderPassParams		=
3377e5c31af7Sopenharmony_ci	{
3378e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,		//	VkStructureType					sType;
3379e5c31af7Sopenharmony_ci		DE_NULL,										//	const void*						pNext;
3380e5c31af7Sopenharmony_ci		(VkRenderPassCreateFlags)0,
3381e5c31af7Sopenharmony_ci		1u,												//	deUint32						attachmentCount;
3382e5c31af7Sopenharmony_ci		colorAttDescs.data(),							//	const VkAttachmentDescription*	pAttachments;
3383e5c31af7Sopenharmony_ci		1u,												//	deUint32						subpassCount;
3384e5c31af7Sopenharmony_ci		&subpassDesc,									//	const VkSubpassDescription*		pSubpasses;
3385e5c31af7Sopenharmony_ci		0u,												//	deUint32						dependencyCount;
3386e5c31af7Sopenharmony_ci		DE_NULL,										//	const VkSubpassDependency*		pDependencies;
3387e5c31af7Sopenharmony_ci	};
3388e5c31af7Sopenharmony_ci
3389e5c31af7Sopenharmony_ci	if (needInterface)
3390e5c31af7Sopenharmony_ci	{
3391e5c31af7Sopenharmony_ci		subpassDesc.colorAttachmentCount += 1;
3392e5c31af7Sopenharmony_ci		renderPassParams.attachmentCount += 1;
3393e5c31af7Sopenharmony_ci	}
3394e5c31af7Sopenharmony_ci
3395e5c31af7Sopenharmony_ci	const Unique<VkRenderPass>				renderPass				(createRenderPass(vk, device, &renderPassParams));
3396e5c31af7Sopenharmony_ci
3397e5c31af7Sopenharmony_ci	const VkImageViewCreateInfo				colorAttViewParams		=
3398e5c31af7Sopenharmony_ci	{
3399e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		//	VkStructureType				sType;
3400e5c31af7Sopenharmony_ci		DE_NULL,										//	const void*					pNext;
3401e5c31af7Sopenharmony_ci		0u,												//	VkImageViewCreateFlags		flags;
3402e5c31af7Sopenharmony_ci		*image,											//	VkImage						image;
3403e5c31af7Sopenharmony_ci		VK_IMAGE_VIEW_TYPE_2D,							//	VkImageViewType				viewType;
3404e5c31af7Sopenharmony_ci		VK_FORMAT_R8G8B8A8_UNORM,						//	VkFormat					format;
3405e5c31af7Sopenharmony_ci		{
3406e5c31af7Sopenharmony_ci			VK_COMPONENT_SWIZZLE_R,
3407e5c31af7Sopenharmony_ci			VK_COMPONENT_SWIZZLE_G,
3408e5c31af7Sopenharmony_ci			VK_COMPONENT_SWIZZLE_B,
3409e5c31af7Sopenharmony_ci			VK_COMPONENT_SWIZZLE_A
3410e5c31af7Sopenharmony_ci		},												//	VkChannelMapping			channels;
3411e5c31af7Sopenharmony_ci		{
3412e5c31af7Sopenharmony_ci			VK_IMAGE_ASPECT_COLOR_BIT,						//	VkImageAspectFlags	aspectMask;
3413e5c31af7Sopenharmony_ci			0u,												//	deUint32			baseMipLevel;
3414e5c31af7Sopenharmony_ci			1u,												//	deUint32			mipLevels;
3415e5c31af7Sopenharmony_ci			0u,												//	deUint32			baseArrayLayer;
3416e5c31af7Sopenharmony_ci			1u,												//	deUint32			arraySize;
3417e5c31af7Sopenharmony_ci		},												//	VkImageSubresourceRange		subresourceRange;
3418e5c31af7Sopenharmony_ci	};
3419e5c31af7Sopenharmony_ci	const Unique<VkImageView>				colorAttView			(createImageView(vk, device, &colorAttViewParams));
3420e5c31af7Sopenharmony_ci	const VkImageAspectFlags				inputImageAspect		= getImageAspectFlags(instance.resources.inputFormat);
3421e5c31af7Sopenharmony_ci
3422e5c31af7Sopenharmony_ci	vector<VkImageView>						attViews;
3423e5c31af7Sopenharmony_ci	attViews.push_back(*colorAttView);
3424e5c31af7Sopenharmony_ci
3425e5c31af7Sopenharmony_ci	// Handle resources requested by the test instantiation.
3426e5c31af7Sopenharmony_ci	// These variables should be placed out of the following if block to avoid deallocation after out of scope.
3427e5c31af7Sopenharmony_ci	vector<AllocationSp>					inResourceMemories;
3428e5c31af7Sopenharmony_ci	vector<AllocationSp>					outResourceMemories;
3429e5c31af7Sopenharmony_ci	vector<BufferHandleSp>					inResourceBuffers;
3430e5c31af7Sopenharmony_ci	vector<BufferHandleSp>					outResourceBuffers;
3431e5c31af7Sopenharmony_ci	vector<ImageHandleSp>					inResourceImages;
3432e5c31af7Sopenharmony_ci	vector<ImageViewHandleSp>				inResourceImageViews;
3433e5c31af7Sopenharmony_ci	vector<SamplerHandleSp>					inResourceSamplers;
3434e5c31af7Sopenharmony_ci	Move<VkDescriptorPool>					descriptorPool;
3435e5c31af7Sopenharmony_ci	Move<VkDescriptorSetLayout>				setLayout;
3436e5c31af7Sopenharmony_ci	VkDescriptorSetLayout					rawSetLayout			= DE_NULL;
3437e5c31af7Sopenharmony_ci	VkDescriptorSet							rawSet					= DE_NULL;
3438e5c31af7Sopenharmony_ci
3439e5c31af7Sopenharmony_ci	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
3440e5c31af7Sopenharmony_ci
3441e5c31af7Sopenharmony_ci	// Command buffer
3442e5c31af7Sopenharmony_ci	const Unique<VkCommandBuffer>			cmdBuf					(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3443e5c31af7Sopenharmony_ci
3444e5c31af7Sopenharmony_ci	if (numResources != 0)
3445e5c31af7Sopenharmony_ci	{
3446e5c31af7Sopenharmony_ci		vector<VkDescriptorSetLayoutBinding>	setLayoutBindings;
3447e5c31af7Sopenharmony_ci		vector<VkDescriptorPoolSize>			poolSizes;
3448e5c31af7Sopenharmony_ci
3449e5c31af7Sopenharmony_ci		setLayoutBindings.reserve(numResources);
3450e5c31af7Sopenharmony_ci		poolSizes.reserve(numResources);
3451e5c31af7Sopenharmony_ci
3452e5c31af7Sopenharmony_ci		// Process all input resources.
3453e5c31af7Sopenharmony_ci		for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
3454e5c31af7Sopenharmony_ci		{
3455e5c31af7Sopenharmony_ci			const Resource&	resource	= instance.resources.inputs[inputNdx];
3456e5c31af7Sopenharmony_ci
3457e5c31af7Sopenharmony_ci			const bool		hasImage	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)	||
3458e5c31af7Sopenharmony_ci										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3459e5c31af7Sopenharmony_ci										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3460e5c31af7Sopenharmony_ci
3461e5c31af7Sopenharmony_ci			const bool		hasSampler	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3462e5c31af7Sopenharmony_ci										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLER)			||
3463e5c31af7Sopenharmony_ci										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3464e5c31af7Sopenharmony_ci
3465e5c31af7Sopenharmony_ci			// Resource is a buffer
3466e5c31af7Sopenharmony_ci			if (!hasImage && !hasSampler)
3467e5c31af7Sopenharmony_ci			{
3468e5c31af7Sopenharmony_ci				Move<VkBuffer>					resourceBuffer			= createBufferForResource(vk, device, resource, queueFamilyIndex);
3469e5c31af7Sopenharmony_ci				de::MovePtr<Allocation>			resourceMemory			= allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3470e5c31af7Sopenharmony_ci
3471e5c31af7Sopenharmony_ci				VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3472e5c31af7Sopenharmony_ci
3473e5c31af7Sopenharmony_ci				// Copy data to memory.
3474e5c31af7Sopenharmony_ci				{
3475e5c31af7Sopenharmony_ci					vector<deUint8>					resourceBytes;
3476e5c31af7Sopenharmony_ci					resource.getBytes(resourceBytes);
3477e5c31af7Sopenharmony_ci
3478e5c31af7Sopenharmony_ci					deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
3479e5c31af7Sopenharmony_ci					flushAlloc(vk, device, *resourceMemory);
3480e5c31af7Sopenharmony_ci				}
3481e5c31af7Sopenharmony_ci
3482e5c31af7Sopenharmony_ci				inResourceMemories.push_back(AllocationSp(resourceMemory.release()));
3483e5c31af7Sopenharmony_ci				inResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
3484e5c31af7Sopenharmony_ci			}
3485e5c31af7Sopenharmony_ci			// Resource is an image
3486e5c31af7Sopenharmony_ci			else if (hasImage)
3487e5c31af7Sopenharmony_ci			{
3488e5c31af7Sopenharmony_ci				Move<VkBuffer>					resourceBuffer			= createBufferForResource(vk, device, resource, queueFamilyIndex);
3489e5c31af7Sopenharmony_ci				de::MovePtr<Allocation>			resourceMemory			= allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3490e5c31af7Sopenharmony_ci
3491e5c31af7Sopenharmony_ci				VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3492e5c31af7Sopenharmony_ci
3493e5c31af7Sopenharmony_ci				// Copy data to memory.
3494e5c31af7Sopenharmony_ci				{
3495e5c31af7Sopenharmony_ci					vector<deUint8>					resourceBytes;
3496e5c31af7Sopenharmony_ci					resource.getBytes(resourceBytes);
3497e5c31af7Sopenharmony_ci
3498e5c31af7Sopenharmony_ci					deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
3499e5c31af7Sopenharmony_ci					flushAlloc(vk, device, *resourceMemory);
3500e5c31af7Sopenharmony_ci				}
3501e5c31af7Sopenharmony_ci
3502e5c31af7Sopenharmony_ci				Move<VkImage>					resourceImage			= createImageForResource(vk, device, resource, instance.resources.inputFormat, queueFamilyIndex);
3503e5c31af7Sopenharmony_ci				de::MovePtr<Allocation>			resourceImageMemory		= allocator.allocate(getImageMemoryRequirements(vk, device, *resourceImage), MemoryRequirement::Any);
3504e5c31af7Sopenharmony_ci
3505e5c31af7Sopenharmony_ci				VK_CHECK(vk.bindImageMemory(device, *resourceImage, resourceImageMemory->getMemory(), resourceImageMemory->getOffset()));
3506e5c31af7Sopenharmony_ci
3507e5c31af7Sopenharmony_ci				copyBufferToImage(context, vk, device, queue, *cmdPool, *cmdBuf, resourceBuffer.get(), resourceImage.get(), inputImageAspect);
3508e5c31af7Sopenharmony_ci
3509e5c31af7Sopenharmony_ci				inResourceMemories.push_back(AllocationSp(resourceImageMemory.release()));
3510e5c31af7Sopenharmony_ci				inResourceImages.push_back(ImageHandleSp(new ImageHandleUp(resourceImage)));
3511e5c31af7Sopenharmony_ci			}
3512e5c31af7Sopenharmony_ci
3513e5c31af7Sopenharmony_ci			// Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool.
3514e5c31af7Sopenharmony_ci			const VkDescriptorSetLayoutBinding	binding				=
3515e5c31af7Sopenharmony_ci			{
3516e5c31af7Sopenharmony_ci				inputNdx,											// binding
3517e5c31af7Sopenharmony_ci				resource.getDescriptorType(),						// descriptorType
3518e5c31af7Sopenharmony_ci				1u,													// descriptorCount
3519e5c31af7Sopenharmony_ci				VK_SHADER_STAGE_ALL_GRAPHICS,						// stageFlags
3520e5c31af7Sopenharmony_ci				DE_NULL,											// pImmutableSamplers
3521e5c31af7Sopenharmony_ci			};
3522e5c31af7Sopenharmony_ci			setLayoutBindings.push_back(binding);
3523e5c31af7Sopenharmony_ci
3524e5c31af7Sopenharmony_ci			// Note: the following code doesn't check and unify descriptors of the same type.
3525e5c31af7Sopenharmony_ci			const VkDescriptorPoolSize		poolSize				=
3526e5c31af7Sopenharmony_ci			{
3527e5c31af7Sopenharmony_ci				resource.getDescriptorType(),						// type
3528e5c31af7Sopenharmony_ci				1u,													// descriptorCount
3529e5c31af7Sopenharmony_ci			};
3530e5c31af7Sopenharmony_ci			poolSizes.push_back(poolSize);
3531e5c31af7Sopenharmony_ci		}
3532e5c31af7Sopenharmony_ci
3533e5c31af7Sopenharmony_ci		// Process all output resources.
3534e5c31af7Sopenharmony_ci		for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
3535e5c31af7Sopenharmony_ci		{
3536e5c31af7Sopenharmony_ci			const Resource&					resource				= instance.resources.outputs[outputNdx];
3537e5c31af7Sopenharmony_ci			// Create buffer and allocate memory.
3538e5c31af7Sopenharmony_ci			Move<VkBuffer>					resourceBuffer			= createBufferForResource(vk, device, resource, queueFamilyIndex);
3539e5c31af7Sopenharmony_ci			de::MovePtr<Allocation>			resourceMemory			= allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3540e5c31af7Sopenharmony_ci			vector<deUint8>					resourceBytes;
3541e5c31af7Sopenharmony_ci
3542e5c31af7Sopenharmony_ci			VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3543e5c31af7Sopenharmony_ci
3544e5c31af7Sopenharmony_ci			// Fill memory with all ones.
3545e5c31af7Sopenharmony_ci			resource.getBytes(resourceBytes);
3546e5c31af7Sopenharmony_ci			deMemset((deUint8*)resourceMemory->getHostPtr(), 0xff, resourceBytes.size());
3547e5c31af7Sopenharmony_ci			flushAlloc(vk, device, *resourceMemory);
3548e5c31af7Sopenharmony_ci
3549e5c31af7Sopenharmony_ci			outResourceMemories.push_back(AllocationSp(resourceMemory.release()));
3550e5c31af7Sopenharmony_ci			outResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
3551e5c31af7Sopenharmony_ci
3552e5c31af7Sopenharmony_ci			// Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool.
3553e5c31af7Sopenharmony_ci			const VkDescriptorSetLayoutBinding	binding				=
3554e5c31af7Sopenharmony_ci			{
3555e5c31af7Sopenharmony_ci				numInResources  + outputNdx,						// binding
3556e5c31af7Sopenharmony_ci				resource.getDescriptorType(),						// descriptorType
3557e5c31af7Sopenharmony_ci				1u,													// descriptorCount
3558e5c31af7Sopenharmony_ci				VK_SHADER_STAGE_ALL_GRAPHICS,						// stageFlags
3559e5c31af7Sopenharmony_ci				DE_NULL,											// pImmutableSamplers
3560e5c31af7Sopenharmony_ci			};
3561e5c31af7Sopenharmony_ci			setLayoutBindings.push_back(binding);
3562e5c31af7Sopenharmony_ci
3563e5c31af7Sopenharmony_ci			// Note: the following code doesn't check and unify descriptors of the same type.
3564e5c31af7Sopenharmony_ci			const VkDescriptorPoolSize		poolSize				=
3565e5c31af7Sopenharmony_ci			{
3566e5c31af7Sopenharmony_ci				resource.getDescriptorType(),						// type
3567e5c31af7Sopenharmony_ci				1u,													// descriptorCount
3568e5c31af7Sopenharmony_ci			};
3569e5c31af7Sopenharmony_ci			poolSizes.push_back(poolSize);
3570e5c31af7Sopenharmony_ci		}
3571e5c31af7Sopenharmony_ci
3572e5c31af7Sopenharmony_ci		// Create descriptor set layout, descriptor pool, and allocate descriptor set.
3573e5c31af7Sopenharmony_ci		const VkDescriptorSetLayoutCreateInfo	setLayoutParams		=
3574e5c31af7Sopenharmony_ci		{
3575e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
3576e5c31af7Sopenharmony_ci			DE_NULL,												// pNext
3577e5c31af7Sopenharmony_ci			(VkDescriptorSetLayoutCreateFlags)0,					// flags
3578e5c31af7Sopenharmony_ci			numResources,											// bindingCount
3579e5c31af7Sopenharmony_ci			setLayoutBindings.data(),								// pBindings
3580e5c31af7Sopenharmony_ci		};
3581e5c31af7Sopenharmony_ci		setLayout													= createDescriptorSetLayout(vk, device, &setLayoutParams);
3582e5c31af7Sopenharmony_ci		rawSetLayout												= *setLayout;
3583e5c31af7Sopenharmony_ci
3584e5c31af7Sopenharmony_ci		const VkDescriptorPoolCreateInfo		poolParams			=
3585e5c31af7Sopenharmony_ci		{
3586e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,			// sType
3587e5c31af7Sopenharmony_ci			DE_NULL,												// pNext
3588e5c31af7Sopenharmony_ci			(VkDescriptorPoolCreateFlags)0,							// flags
3589e5c31af7Sopenharmony_ci			1u,														// maxSets
3590e5c31af7Sopenharmony_ci			numResources,											// poolSizeCount
3591e5c31af7Sopenharmony_ci			poolSizes.data(),										// pPoolSizes
3592e5c31af7Sopenharmony_ci		};
3593e5c31af7Sopenharmony_ci		descriptorPool												= createDescriptorPool(vk, device, &poolParams);
3594e5c31af7Sopenharmony_ci
3595e5c31af7Sopenharmony_ci		const VkDescriptorSetAllocateInfo		setAllocParams		=
3596e5c31af7Sopenharmony_ci		{
3597e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			// sType
3598e5c31af7Sopenharmony_ci			DE_NULL,												// pNext
3599e5c31af7Sopenharmony_ci			*descriptorPool,										// descriptorPool
3600e5c31af7Sopenharmony_ci			1u,														// descriptorSetCount
3601e5c31af7Sopenharmony_ci			&rawSetLayout,											// pSetLayouts
3602e5c31af7Sopenharmony_ci		};
3603e5c31af7Sopenharmony_ci		VK_CHECK(vk.allocateDescriptorSets(device, &setAllocParams, &rawSet));
3604e5c31af7Sopenharmony_ci
3605e5c31af7Sopenharmony_ci		// Update descriptor set.
3606e5c31af7Sopenharmony_ci		vector<VkWriteDescriptorSet>			writeSpecs;
3607e5c31af7Sopenharmony_ci		vector<VkDescriptorBufferInfo>			dBufferInfos;
3608e5c31af7Sopenharmony_ci		vector<VkDescriptorImageInfo>			dImageInfos;
3609e5c31af7Sopenharmony_ci
3610e5c31af7Sopenharmony_ci		writeSpecs.reserve(numResources);
3611e5c31af7Sopenharmony_ci		dBufferInfos.reserve(numResources);
3612e5c31af7Sopenharmony_ci		dImageInfos.reserve(numResources);
3613e5c31af7Sopenharmony_ci
3614e5c31af7Sopenharmony_ci		deUint32								imgResourceNdx		= 0u;
3615e5c31af7Sopenharmony_ci		deUint32								bufResourceNdx		= 0u;
3616e5c31af7Sopenharmony_ci
3617e5c31af7Sopenharmony_ci		for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
3618e5c31af7Sopenharmony_ci		{
3619e5c31af7Sopenharmony_ci			const Resource&	resource	= instance.resources.inputs[inputNdx];
3620e5c31af7Sopenharmony_ci
3621e5c31af7Sopenharmony_ci			const bool		hasImage	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)	||
3622e5c31af7Sopenharmony_ci										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3623e5c31af7Sopenharmony_ci										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3624e5c31af7Sopenharmony_ci
3625e5c31af7Sopenharmony_ci			const bool		hasSampler	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3626e5c31af7Sopenharmony_ci										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLER)			||
3627e5c31af7Sopenharmony_ci										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3628e5c31af7Sopenharmony_ci
3629e5c31af7Sopenharmony_ci			// Create image view and sampler
3630e5c31af7Sopenharmony_ci			if (hasImage || hasSampler)
3631e5c31af7Sopenharmony_ci			{
3632e5c31af7Sopenharmony_ci				if (resource.getDescriptorType() != VK_DESCRIPTOR_TYPE_SAMPLER)
3633e5c31af7Sopenharmony_ci				{
3634e5c31af7Sopenharmony_ci					const VkImageViewCreateInfo	imgViewParams	=
3635e5c31af7Sopenharmony_ci					{
3636e5c31af7Sopenharmony_ci						VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	//	VkStructureType				sType;
3637e5c31af7Sopenharmony_ci						DE_NULL,									//	const void*					pNext;
3638e5c31af7Sopenharmony_ci						0u,											//	VkImageViewCreateFlags		flags;
3639e5c31af7Sopenharmony_ci						**inResourceImages[imgResourceNdx++],		//	VkImage						image;
3640e5c31af7Sopenharmony_ci						VK_IMAGE_VIEW_TYPE_2D,						//	VkImageViewType				viewType;
3641e5c31af7Sopenharmony_ci						instance.resources.inputFormat,				//	VkFormat					format;
3642e5c31af7Sopenharmony_ci						{
3643e5c31af7Sopenharmony_ci							VK_COMPONENT_SWIZZLE_R,
3644e5c31af7Sopenharmony_ci							VK_COMPONENT_SWIZZLE_G,
3645e5c31af7Sopenharmony_ci							VK_COMPONENT_SWIZZLE_B,
3646e5c31af7Sopenharmony_ci							VK_COMPONENT_SWIZZLE_A
3647e5c31af7Sopenharmony_ci						},											//	VkComponentMapping			channels;
3648e5c31af7Sopenharmony_ci						{
3649e5c31af7Sopenharmony_ci							inputImageAspect,	//	VkImageAspectFlags	aspectMask;
3650e5c31af7Sopenharmony_ci							0u,					//	deUint32			baseMipLevel;
3651e5c31af7Sopenharmony_ci							1u,					//	deUint32			mipLevels;
3652e5c31af7Sopenharmony_ci							0u,					//	deUint32			baseArrayLayer;
3653e5c31af7Sopenharmony_ci							1u,					//	deUint32			arraySize;
3654e5c31af7Sopenharmony_ci						},											//	VkImageSubresourceRange		subresourceRange;
3655e5c31af7Sopenharmony_ci					};
3656e5c31af7Sopenharmony_ci
3657e5c31af7Sopenharmony_ci					Move<VkImageView>			imgView			(createImageView(vk, device, &imgViewParams));
3658e5c31af7Sopenharmony_ci					inResourceImageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imgView)));
3659e5c31af7Sopenharmony_ci				}
3660e5c31af7Sopenharmony_ci
3661e5c31af7Sopenharmony_ci				if (hasSampler)
3662e5c31af7Sopenharmony_ci				{
3663e5c31af7Sopenharmony_ci					const bool					hasDepthComponent	= tcu::hasDepthComponent(vk::mapVkFormat(instance.resources.inputFormat).order);
3664e5c31af7Sopenharmony_ci					const VkSamplerCreateInfo	samplerParams
3665e5c31af7Sopenharmony_ci					{
3666e5c31af7Sopenharmony_ci						VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType			sType;
3667e5c31af7Sopenharmony_ci						DE_NULL,									// const void*				pNext;
3668e5c31af7Sopenharmony_ci						0,											// VkSamplerCreateFlags		flags;
3669e5c31af7Sopenharmony_ci						VK_FILTER_NEAREST,							// VkFilter					magFilter:
3670e5c31af7Sopenharmony_ci						VK_FILTER_NEAREST,							// VkFilter					minFilter;
3671e5c31af7Sopenharmony_ci						VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode		mipmapMode;
3672e5c31af7Sopenharmony_ci						VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeU;
3673e5c31af7Sopenharmony_ci						VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeV;
3674e5c31af7Sopenharmony_ci						VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeW;
3675e5c31af7Sopenharmony_ci						0.0f,										// float					mipLodBias;
3676e5c31af7Sopenharmony_ci						VK_FALSE,									// VkBool32					anistoropyEnable;
3677e5c31af7Sopenharmony_ci						1.0f,										// float					maxAnisotropy;
3678e5c31af7Sopenharmony_ci						(hasDepthComponent) ? VK_TRUE : VK_FALSE,	// VkBool32					compareEnable;
3679e5c31af7Sopenharmony_ci						VK_COMPARE_OP_LESS,							// VkCompareOp				compareOp;
3680e5c31af7Sopenharmony_ci						0.0f,										// float					minLod;
3681e5c31af7Sopenharmony_ci						0.0f,										// float					maxLod;
3682e5c31af7Sopenharmony_ci						VK_BORDER_COLOR_INT_OPAQUE_BLACK,			// VkBorderColor			borderColor;
3683e5c31af7Sopenharmony_ci						VK_FALSE									// VkBool32					unnormalizedCoordinates;
3684e5c31af7Sopenharmony_ci					};
3685e5c31af7Sopenharmony_ci
3686e5c31af7Sopenharmony_ci					Move<VkSampler>				sampler			(createSampler(vk, device, &samplerParams));
3687e5c31af7Sopenharmony_ci					inResourceSamplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
3688e5c31af7Sopenharmony_ci				}
3689e5c31af7Sopenharmony_ci			}
3690e5c31af7Sopenharmony_ci
3691e5c31af7Sopenharmony_ci			// Create descriptor buffer and image infos
3692e5c31af7Sopenharmony_ci			switch (resource.getDescriptorType())
3693e5c31af7Sopenharmony_ci			{
3694e5c31af7Sopenharmony_ci				case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
3695e5c31af7Sopenharmony_ci				case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
3696e5c31af7Sopenharmony_ci				{
3697e5c31af7Sopenharmony_ci					const VkDescriptorBufferInfo	bufInfo	=
3698e5c31af7Sopenharmony_ci					{
3699e5c31af7Sopenharmony_ci						**inResourceBuffers[bufResourceNdx++],				// buffer
3700e5c31af7Sopenharmony_ci						0,													// offset
3701e5c31af7Sopenharmony_ci						VK_WHOLE_SIZE,										// size
3702e5c31af7Sopenharmony_ci					};
3703e5c31af7Sopenharmony_ci					dBufferInfos.push_back(bufInfo);
3704e5c31af7Sopenharmony_ci					break;
3705e5c31af7Sopenharmony_ci				}
3706e5c31af7Sopenharmony_ci				case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
3707e5c31af7Sopenharmony_ci				case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
3708e5c31af7Sopenharmony_ci				{
3709e5c31af7Sopenharmony_ci					const VkDescriptorImageInfo		imgInfo	=
3710e5c31af7Sopenharmony_ci					{
3711e5c31af7Sopenharmony_ci						DE_NULL,												// sampler
3712e5c31af7Sopenharmony_ci						**inResourceImageViews.back(),							// imageView
3713e5c31af7Sopenharmony_ci						VK_IMAGE_LAYOUT_GENERAL									// imageLayout
3714e5c31af7Sopenharmony_ci					};
3715e5c31af7Sopenharmony_ci					dImageInfos.push_back(imgInfo);
3716e5c31af7Sopenharmony_ci					break;
3717e5c31af7Sopenharmony_ci				}
3718e5c31af7Sopenharmony_ci				case VK_DESCRIPTOR_TYPE_SAMPLER:
3719e5c31af7Sopenharmony_ci				{
3720e5c31af7Sopenharmony_ci					const VkDescriptorImageInfo		imgInfo	=
3721e5c31af7Sopenharmony_ci					{
3722e5c31af7Sopenharmony_ci						**inResourceSamplers.back(),							// sampler
3723e5c31af7Sopenharmony_ci						DE_NULL,												// imageView
3724e5c31af7Sopenharmony_ci						VK_IMAGE_LAYOUT_GENERAL									// imageLayout
3725e5c31af7Sopenharmony_ci					};
3726e5c31af7Sopenharmony_ci					dImageInfos.push_back(imgInfo);
3727e5c31af7Sopenharmony_ci					break;
3728e5c31af7Sopenharmony_ci				}
3729e5c31af7Sopenharmony_ci				case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
3730e5c31af7Sopenharmony_ci				{
3731e5c31af7Sopenharmony_ci
3732e5c31af7Sopenharmony_ci					const VkDescriptorImageInfo		imgInfo	=
3733e5c31af7Sopenharmony_ci					{
3734e5c31af7Sopenharmony_ci						**inResourceSamplers.back(),							// sampler
3735e5c31af7Sopenharmony_ci						**inResourceImageViews.back(),							// imageView
3736e5c31af7Sopenharmony_ci						VK_IMAGE_LAYOUT_GENERAL									// imageLayout
3737e5c31af7Sopenharmony_ci					};
3738e5c31af7Sopenharmony_ci					dImageInfos.push_back(imgInfo);
3739e5c31af7Sopenharmony_ci					break;
3740e5c31af7Sopenharmony_ci				}
3741e5c31af7Sopenharmony_ci				default:
3742e5c31af7Sopenharmony_ci					DE_FATAL("Not implemented");
3743e5c31af7Sopenharmony_ci			}
3744e5c31af7Sopenharmony_ci
3745e5c31af7Sopenharmony_ci			const VkWriteDescriptorSet			writeSpec			= {
3746e5c31af7Sopenharmony_ci				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,							// sType
3747e5c31af7Sopenharmony_ci				DE_NULL,														// pNext
3748e5c31af7Sopenharmony_ci				rawSet,															// dstSet
3749e5c31af7Sopenharmony_ci				inputNdx,														// binding
3750e5c31af7Sopenharmony_ci				0,																// dstArrayElement
3751e5c31af7Sopenharmony_ci				1u,																// descriptorCount
3752e5c31af7Sopenharmony_ci				instance.resources.inputs[inputNdx].getDescriptorType(),		// descriptorType
3753e5c31af7Sopenharmony_ci				( (hasImage | hasSampler)	? &dImageInfos.back()	: DE_NULL),	// pImageInfo
3754e5c31af7Sopenharmony_ci				(!(hasImage | hasSampler)	? &dBufferInfos.back()	: DE_NULL),	// pBufferInfo
3755e5c31af7Sopenharmony_ci				DE_NULL,														// pTexelBufferView
3756e5c31af7Sopenharmony_ci			};
3757e5c31af7Sopenharmony_ci			writeSpecs.push_back(writeSpec);
3758e5c31af7Sopenharmony_ci		}
3759e5c31af7Sopenharmony_ci
3760e5c31af7Sopenharmony_ci		for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
3761e5c31af7Sopenharmony_ci		{
3762e5c31af7Sopenharmony_ci			const VkDescriptorBufferInfo		bufInfo				=
3763e5c31af7Sopenharmony_ci			{
3764e5c31af7Sopenharmony_ci				**outResourceBuffers[outputNdx],					// buffer
3765e5c31af7Sopenharmony_ci				0,													// offset
3766e5c31af7Sopenharmony_ci				VK_WHOLE_SIZE,										// size
3767e5c31af7Sopenharmony_ci			};
3768e5c31af7Sopenharmony_ci			dBufferInfos.push_back(bufInfo);
3769e5c31af7Sopenharmony_ci
3770e5c31af7Sopenharmony_ci			const VkWriteDescriptorSet			writeSpec			= {
3771e5c31af7Sopenharmony_ci				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,						// sType
3772e5c31af7Sopenharmony_ci				DE_NULL,													// pNext
3773e5c31af7Sopenharmony_ci				rawSet,														// dstSet
3774e5c31af7Sopenharmony_ci				numInResources + outputNdx,									// binding
3775e5c31af7Sopenharmony_ci				0,															// dstArrayElement
3776e5c31af7Sopenharmony_ci				1u,															// descriptorCount
3777e5c31af7Sopenharmony_ci				instance.resources.outputs[outputNdx].getDescriptorType(),	// descriptorType
3778e5c31af7Sopenharmony_ci				DE_NULL,													// pImageInfo
3779e5c31af7Sopenharmony_ci				&dBufferInfos.back(),										// pBufferInfo
3780e5c31af7Sopenharmony_ci				DE_NULL,													// pTexelBufferView
3781e5c31af7Sopenharmony_ci			};
3782e5c31af7Sopenharmony_ci			writeSpecs.push_back(writeSpec);
3783e5c31af7Sopenharmony_ci		}
3784e5c31af7Sopenharmony_ci		vk.updateDescriptorSets(device, numResources, writeSpecs.data(), 0, DE_NULL);
3785e5c31af7Sopenharmony_ci	}
3786e5c31af7Sopenharmony_ci
3787e5c31af7Sopenharmony_ci	// Pipeline layout
3788e5c31af7Sopenharmony_ci	VkPipelineLayoutCreateInfo				pipelineLayoutParams	=
3789e5c31af7Sopenharmony_ci	{
3790e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,			//	VkStructureType					sType;
3791e5c31af7Sopenharmony_ci		DE_NULL,												//	const void*						pNext;
3792e5c31af7Sopenharmony_ci		(VkPipelineLayoutCreateFlags)0,
3793e5c31af7Sopenharmony_ci		0u,														//	deUint32						descriptorSetCount;
3794e5c31af7Sopenharmony_ci		DE_NULL,												//	const VkDescriptorSetLayout*	pSetLayouts;
3795e5c31af7Sopenharmony_ci		0u,														//	deUint32						pushConstantRangeCount;
3796e5c31af7Sopenharmony_ci		DE_NULL,												//	const VkPushConstantRange*		pPushConstantRanges;
3797e5c31af7Sopenharmony_ci	};
3798e5c31af7Sopenharmony_ci
3799e5c31af7Sopenharmony_ci	VkPushConstantRange						pushConstantRange		=
3800e5c31af7Sopenharmony_ci	{
3801e5c31af7Sopenharmony_ci		VK_SHADER_STAGE_ALL_GRAPHICS,							// VkShaderStageFlags    stageFlags;
3802e5c31af7Sopenharmony_ci		0,														// uint32_t              offset;
3803e5c31af7Sopenharmony_ci		0,														// uint32_t              size;
3804e5c31af7Sopenharmony_ci	};
3805e5c31af7Sopenharmony_ci	if (hasPushConstants)
3806e5c31af7Sopenharmony_ci	{
3807e5c31af7Sopenharmony_ci		vector<deUint8> pushConstantsBytes;
3808e5c31af7Sopenharmony_ci		instance.pushConstants.getBuffer()->getBytes(pushConstantsBytes);
3809e5c31af7Sopenharmony_ci
3810e5c31af7Sopenharmony_ci		pushConstantRange.size						= static_cast<deUint32>(pushConstantsBytes.size());
3811e5c31af7Sopenharmony_ci		pipelineLayoutParams.pushConstantRangeCount	= 1;
3812e5c31af7Sopenharmony_ci		pipelineLayoutParams.pPushConstantRanges	= &pushConstantRange;
3813e5c31af7Sopenharmony_ci	}
3814e5c31af7Sopenharmony_ci	if (numResources != 0)
3815e5c31af7Sopenharmony_ci	{
3816e5c31af7Sopenharmony_ci		// Update pipeline layout with the descriptor set layout.
3817e5c31af7Sopenharmony_ci		pipelineLayoutParams.setLayoutCount								= 1;
3818e5c31af7Sopenharmony_ci		pipelineLayoutParams.pSetLayouts								= &rawSetLayout;
3819e5c31af7Sopenharmony_ci	}
3820e5c31af7Sopenharmony_ci	const Unique<VkPipelineLayout>			pipelineLayout			(createPipelineLayout(vk, device, &pipelineLayoutParams));
3821e5c31af7Sopenharmony_ci
3822e5c31af7Sopenharmony_ci	// Pipeline
3823e5c31af7Sopenharmony_ci	vector<VkPipelineShaderStageCreateInfo>		shaderStageParams;
3824e5c31af7Sopenharmony_ci	// We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline().
3825e5c31af7Sopenharmony_ci	vector<vector<VkSpecializationMapEntry> >	specConstantEntries;
3826e5c31af7Sopenharmony_ci	vector<VkSpecializationInfo>				specializationInfos;
3827e5c31af7Sopenharmony_ci	if (DE_NULL != instance.resources.verifyBinary)
3828e5c31af7Sopenharmony_ci	{
3829e5c31af7Sopenharmony_ci		std::string shaderName;
3830e5c31af7Sopenharmony_ci		switch(instance.customizedStages)
3831e5c31af7Sopenharmony_ci		{
3832e5c31af7Sopenharmony_ci		case	VK_SHADER_STAGE_VERTEX_BIT:
3833e5c31af7Sopenharmony_ci			shaderName= "vert";
3834e5c31af7Sopenharmony_ci			break;
3835e5c31af7Sopenharmony_ci		case	VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
3836e5c31af7Sopenharmony_ci			shaderName= "tessc";
3837e5c31af7Sopenharmony_ci			break;
3838e5c31af7Sopenharmony_ci		case	VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
3839e5c31af7Sopenharmony_ci			shaderName= "tesse";
3840e5c31af7Sopenharmony_ci			break;
3841e5c31af7Sopenharmony_ci		case	VK_SHADER_STAGE_GEOMETRY_BIT:
3842e5c31af7Sopenharmony_ci			shaderName= "geom";
3843e5c31af7Sopenharmony_ci			break;
3844e5c31af7Sopenharmony_ci		case	VK_SHADER_STAGE_FRAGMENT_BIT:
3845e5c31af7Sopenharmony_ci			shaderName= "frag";
3846e5c31af7Sopenharmony_ci			break;
3847e5c31af7Sopenharmony_ci		default:
3848e5c31af7Sopenharmony_ci			DE_ASSERT(0);
3849e5c31af7Sopenharmony_ci			break;
3850e5c31af7Sopenharmony_ci		}
3851e5c31af7Sopenharmony_ci		const ProgramBinary& binary  = context.getBinaryCollection().get(shaderName);
3852e5c31af7Sopenharmony_ci		if (!instance.resources.verifyBinary(binary))
3853e5c31af7Sopenharmony_ci			return tcu::TestStatus::fail("Binary verification of SPIR-V in the test failed");
3854e5c31af7Sopenharmony_ci
3855e5c31af7Sopenharmony_ci	}
3856e5c31af7Sopenharmony_ci	createPipelineShaderStages(vk, device, instance, context, modules, shaderStageParams);
3857e5c31af7Sopenharmony_ci
3858e5c31af7Sopenharmony_ci	// And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents.
3859e5c31af7Sopenharmony_ci	specConstantEntries.reserve(shaderStageParams.size());
3860e5c31af7Sopenharmony_ci	specializationInfos.reserve(shaderStageParams.size());
3861e5c31af7Sopenharmony_ci
3862e5c31af7Sopenharmony_ci	// Patch the specialization info field in PipelineShaderStageCreateInfos.
3863e5c31af7Sopenharmony_ci	for (vector<VkPipelineShaderStageCreateInfo>::iterator stageInfo = shaderStageParams.begin(); stageInfo != shaderStageParams.end(); ++stageInfo)
3864e5c31af7Sopenharmony_ci	{
3865e5c31af7Sopenharmony_ci		const StageToSpecConstantMap::const_iterator stageIt = instance.specConstants.find(stageInfo->stage);
3866e5c31af7Sopenharmony_ci
3867e5c31af7Sopenharmony_ci		if (stageIt != instance.specConstants.end())
3868e5c31af7Sopenharmony_ci		{
3869e5c31af7Sopenharmony_ci			const size_t						numSpecConstants	= stageIt->second.getValuesCount();
3870e5c31af7Sopenharmony_ci			vector<VkSpecializationMapEntry>	entries;
3871e5c31af7Sopenharmony_ci			VkSpecializationInfo				specInfo;
3872e5c31af7Sopenharmony_ci			size_t								offset				= 0;
3873e5c31af7Sopenharmony_ci
3874e5c31af7Sopenharmony_ci			entries.resize(numSpecConstants);
3875e5c31af7Sopenharmony_ci
3876e5c31af7Sopenharmony_ci			// Constant IDs are numbered sequentially starting from 0.
3877e5c31af7Sopenharmony_ci			for (size_t ndx = 0; ndx < numSpecConstants; ++ndx)
3878e5c31af7Sopenharmony_ci			{
3879e5c31af7Sopenharmony_ci				const size_t valueSize	= stageIt->second.getValueSize(ndx);
3880e5c31af7Sopenharmony_ci
3881e5c31af7Sopenharmony_ci				entries[ndx].constantID	= (deUint32)ndx;
3882e5c31af7Sopenharmony_ci				entries[ndx].offset		= static_cast<deUint32>(offset);
3883e5c31af7Sopenharmony_ci				entries[ndx].size		= valueSize;
3884e5c31af7Sopenharmony_ci
3885e5c31af7Sopenharmony_ci				offset					+= valueSize;
3886e5c31af7Sopenharmony_ci			}
3887e5c31af7Sopenharmony_ci
3888e5c31af7Sopenharmony_ci			specConstantEntries.push_back(entries);
3889e5c31af7Sopenharmony_ci
3890e5c31af7Sopenharmony_ci			specInfo.mapEntryCount	= (deUint32)numSpecConstants;
3891e5c31af7Sopenharmony_ci			specInfo.pMapEntries	= specConstantEntries.back().data();
3892e5c31af7Sopenharmony_ci			specInfo.dataSize		= offset;
3893e5c31af7Sopenharmony_ci			specInfo.pData			= stageIt->second.getValuesBuffer();
3894e5c31af7Sopenharmony_ci			specializationInfos.push_back(specInfo);
3895e5c31af7Sopenharmony_ci
3896e5c31af7Sopenharmony_ci			stageInfo->pSpecializationInfo = &specializationInfos.back();
3897e5c31af7Sopenharmony_ci		}
3898e5c31af7Sopenharmony_ci	}
3899e5c31af7Sopenharmony_ci	const VkPipelineDepthStencilStateCreateInfo	depthStencilParams		=
3900e5c31af7Sopenharmony_ci	{
3901e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	//	VkStructureType		sType;
3902e5c31af7Sopenharmony_ci		DE_NULL,													//	const void*			pNext;
3903e5c31af7Sopenharmony_ci		(VkPipelineDepthStencilStateCreateFlags)0,
3904e5c31af7Sopenharmony_ci		DE_FALSE,													//	deUint32			depthTestEnable;
3905e5c31af7Sopenharmony_ci		DE_FALSE,													//	deUint32			depthWriteEnable;
3906e5c31af7Sopenharmony_ci		VK_COMPARE_OP_ALWAYS,										//	VkCompareOp			depthCompareOp;
3907e5c31af7Sopenharmony_ci		DE_FALSE,													//	deUint32			depthBoundsTestEnable;
3908e5c31af7Sopenharmony_ci		DE_FALSE,													//	deUint32			stencilTestEnable;
3909e5c31af7Sopenharmony_ci		{
3910e5c31af7Sopenharmony_ci			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilFailOp;
3911e5c31af7Sopenharmony_ci			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilPassOp;
3912e5c31af7Sopenharmony_ci			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilDepthFailOp;
3913e5c31af7Sopenharmony_ci			VK_COMPARE_OP_ALWAYS,										//	VkCompareOp	stencilCompareOp;
3914e5c31af7Sopenharmony_ci			0u,															//	deUint32	stencilCompareMask;
3915e5c31af7Sopenharmony_ci			0u,															//	deUint32	stencilWriteMask;
3916e5c31af7Sopenharmony_ci			0u,															//	deUint32	stencilReference;
3917e5c31af7Sopenharmony_ci		},															//	VkStencilOpState	front;
3918e5c31af7Sopenharmony_ci		{
3919e5c31af7Sopenharmony_ci			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilFailOp;
3920e5c31af7Sopenharmony_ci			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilPassOp;
3921e5c31af7Sopenharmony_ci			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilDepthFailOp;
3922e5c31af7Sopenharmony_ci			VK_COMPARE_OP_ALWAYS,										//	VkCompareOp	stencilCompareOp;
3923e5c31af7Sopenharmony_ci			0u,															//	deUint32	stencilCompareMask;
3924e5c31af7Sopenharmony_ci			0u,															//	deUint32	stencilWriteMask;
3925e5c31af7Sopenharmony_ci			0u,															//	deUint32	stencilReference;
3926e5c31af7Sopenharmony_ci		},															//	VkStencilOpState	back;
3927e5c31af7Sopenharmony_ci		-1.0f,														//	float				minDepthBounds;
3928e5c31af7Sopenharmony_ci		+1.0f,														//	float				maxDepthBounds;
3929e5c31af7Sopenharmony_ci	};
3930e5c31af7Sopenharmony_ci	const VkViewport							viewport0				= makeViewport(renderSize);
3931e5c31af7Sopenharmony_ci	const VkRect2D								scissor0				= makeRect2D(0u, 0u);
3932e5c31af7Sopenharmony_ci	const VkPipelineViewportStateCreateInfo		viewportParams			=
3933e5c31af7Sopenharmony_ci	{
3934e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,		//	VkStructureType		sType;
3935e5c31af7Sopenharmony_ci		DE_NULL,													//	const void*			pNext;
3936e5c31af7Sopenharmony_ci		(VkPipelineViewportStateCreateFlags)0,
3937e5c31af7Sopenharmony_ci		1u,															//	deUint32			viewportCount;
3938e5c31af7Sopenharmony_ci		&viewport0,
3939e5c31af7Sopenharmony_ci		1u,
3940e5c31af7Sopenharmony_ci		&scissor0
3941e5c31af7Sopenharmony_ci	};
3942e5c31af7Sopenharmony_ci	const VkSampleMask							sampleMask				= ~0u;
3943e5c31af7Sopenharmony_ci	const VkPipelineMultisampleStateCreateInfo	multisampleParams		=
3944e5c31af7Sopenharmony_ci	{
3945e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType			sType;
3946e5c31af7Sopenharmony_ci		DE_NULL,													//	const void*				pNext;
3947e5c31af7Sopenharmony_ci		(VkPipelineMultisampleStateCreateFlags)0,
3948e5c31af7Sopenharmony_ci		VK_SAMPLE_COUNT_1_BIT,										//	VkSampleCountFlagBits	rasterSamples;
3949e5c31af7Sopenharmony_ci		DE_FALSE,													//	deUint32				sampleShadingEnable;
3950e5c31af7Sopenharmony_ci		0.0f,														//	float					minSampleShading;
3951e5c31af7Sopenharmony_ci		&sampleMask,												//	const VkSampleMask*		pSampleMask;
3952e5c31af7Sopenharmony_ci		DE_FALSE,													//	VkBool32				alphaToCoverageEnable;
3953e5c31af7Sopenharmony_ci		DE_FALSE,													//	VkBool32				alphaToOneEnable;
3954e5c31af7Sopenharmony_ci	};
3955e5c31af7Sopenharmony_ci	const VkPipelineRasterizationStateCreateInfo	rasterParams		=
3956e5c31af7Sopenharmony_ci	{
3957e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType	sType;
3958e5c31af7Sopenharmony_ci		DE_NULL,													//	const void*		pNext;
3959e5c31af7Sopenharmony_ci		(VkPipelineRasterizationStateCreateFlags)0,
3960e5c31af7Sopenharmony_ci		DE_FALSE,													//	deUint32		depthClampEnable;
3961e5c31af7Sopenharmony_ci		DE_FALSE,													//	deUint32		rasterizerDiscardEnable;
3962e5c31af7Sopenharmony_ci		VK_POLYGON_MODE_FILL,										//	VkFillMode		fillMode;
3963e5c31af7Sopenharmony_ci		VK_CULL_MODE_NONE,											//	VkCullMode		cullMode;
3964e5c31af7Sopenharmony_ci		VK_FRONT_FACE_COUNTER_CLOCKWISE,							//	VkFrontFace		frontFace;
3965e5c31af7Sopenharmony_ci		VK_FALSE,													//	VkBool32		depthBiasEnable;
3966e5c31af7Sopenharmony_ci		0.0f,														//	float			depthBias;
3967e5c31af7Sopenharmony_ci		0.0f,														//	float			depthBiasClamp;
3968e5c31af7Sopenharmony_ci		0.0f,														//	float			slopeScaledDepthBias;
3969e5c31af7Sopenharmony_ci		1.0f,														//	float			lineWidth;
3970e5c31af7Sopenharmony_ci	};
3971e5c31af7Sopenharmony_ci	const VkPrimitiveTopology topology = hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
3972e5c31af7Sopenharmony_ci	const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyParams	=
3973e5c31af7Sopenharmony_ci	{
3974e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	//	VkStructureType		sType;
3975e5c31af7Sopenharmony_ci		DE_NULL,														//	const void*			pNext;
3976e5c31af7Sopenharmony_ci		(VkPipelineInputAssemblyStateCreateFlags)0,
3977e5c31af7Sopenharmony_ci		topology,														//	VkPrimitiveTopology	topology;
3978e5c31af7Sopenharmony_ci		DE_FALSE,														//	deUint32			primitiveRestartEnable;
3979e5c31af7Sopenharmony_ci	};
3980e5c31af7Sopenharmony_ci
3981e5c31af7Sopenharmony_ci	vector<VkVertexInputBindingDescription>		vertexBindings;
3982e5c31af7Sopenharmony_ci	vector<VkVertexInputAttributeDescription>	vertexAttribs;
3983e5c31af7Sopenharmony_ci
3984e5c31af7Sopenharmony_ci	const VkVertexInputBindingDescription		vertexBinding0			=
3985e5c31af7Sopenharmony_ci	{
3986e5c31af7Sopenharmony_ci		0u,									// deUint32					binding;
3987e5c31af7Sopenharmony_ci		deUint32(singleVertexDataSize),		// deUint32					strideInBytes;
3988e5c31af7Sopenharmony_ci		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	stepRate;
3989e5c31af7Sopenharmony_ci	};
3990e5c31af7Sopenharmony_ci	vertexBindings.push_back(vertexBinding0);
3991e5c31af7Sopenharmony_ci
3992e5c31af7Sopenharmony_ci	{
3993e5c31af7Sopenharmony_ci		VkVertexInputAttributeDescription		attr0					=
3994e5c31af7Sopenharmony_ci		{
3995e5c31af7Sopenharmony_ci			0u,									// deUint32	location;
3996e5c31af7Sopenharmony_ci			0u,									// deUint32	binding;
3997e5c31af7Sopenharmony_ci			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
3998e5c31af7Sopenharmony_ci			0u									// deUint32	offsetInBytes;
3999e5c31af7Sopenharmony_ci		};
4000e5c31af7Sopenharmony_ci		vertexAttribs.push_back(attr0);
4001e5c31af7Sopenharmony_ci
4002e5c31af7Sopenharmony_ci		VkVertexInputAttributeDescription		attr1					=
4003e5c31af7Sopenharmony_ci		{
4004e5c31af7Sopenharmony_ci			1u,									// deUint32	location;
4005e5c31af7Sopenharmony_ci			0u,									// deUint32	binding;
4006e5c31af7Sopenharmony_ci			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
4007e5c31af7Sopenharmony_ci			sizeof(Vec4),						// deUint32	offsetInBytes;
4008e5c31af7Sopenharmony_ci		};
4009e5c31af7Sopenharmony_ci		vertexAttribs.push_back(attr1);
4010e5c31af7Sopenharmony_ci	}
4011e5c31af7Sopenharmony_ci
4012e5c31af7Sopenharmony_ci	// If the test instantiation has additional input/output interface variables, we need to create additional bindings.
4013e5c31af7Sopenharmony_ci	// Right now we only support one additional input varible for the vertex stage, and that will be bound to binding #1
4014e5c31af7Sopenharmony_ci	// with location #2.
4015e5c31af7Sopenharmony_ci	if (needInterface)
4016e5c31af7Sopenharmony_ci	{
4017e5c31af7Sopenharmony_ci		// Portability requires stride to be multiply of minVertexInputBindingStrideAlignment
4018e5c31af7Sopenharmony_ci		// this value is usually 4 and current tests meet this requirement but
4019e5c31af7Sopenharmony_ci		// if this changes in future then this limit should be verified in checkSupport
4020e5c31af7Sopenharmony_ci		const deUint32 stride = instance.interfaces.getInputType().getNumBytes();
4021e5c31af7Sopenharmony_ci#ifndef CTS_USES_VULKANSC
4022e5c31af7Sopenharmony_ci		if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
4023e5c31af7Sopenharmony_ci			((stride % context.getPortabilitySubsetProperties().minVertexInputBindingStrideAlignment) != 0))
4024e5c31af7Sopenharmony_ci		{
4025e5c31af7Sopenharmony_ci			DE_FATAL("stride is not multiply of minVertexInputBindingStrideAlignment");
4026e5c31af7Sopenharmony_ci		}
4027e5c31af7Sopenharmony_ci#endif // CTS_USES_VULKANSC
4028e5c31af7Sopenharmony_ci
4029e5c31af7Sopenharmony_ci		const VkVertexInputBindingDescription	vertexBinding1			=
4030e5c31af7Sopenharmony_ci		{
4031e5c31af7Sopenharmony_ci			1u,													// deUint32					binding;
4032e5c31af7Sopenharmony_ci			stride,												// deUint32					strideInBytes;
4033e5c31af7Sopenharmony_ci			VK_VERTEX_INPUT_RATE_VERTEX							// VkVertexInputStepRate	stepRate;
4034e5c31af7Sopenharmony_ci		};
4035e5c31af7Sopenharmony_ci		vertexBindings.push_back(vertexBinding1);
4036e5c31af7Sopenharmony_ci
4037e5c31af7Sopenharmony_ci		VkVertexInputAttributeDescription		attr					=
4038e5c31af7Sopenharmony_ci		{
4039e5c31af7Sopenharmony_ci			2u,													// deUint32	location;
4040e5c31af7Sopenharmony_ci			1u,													// deUint32	binding;
4041e5c31af7Sopenharmony_ci			instance.interfaces.getInputType().getVkFormat(),	// VkFormat	format;
4042e5c31af7Sopenharmony_ci			0,													// deUint32	offsetInBytes;
4043e5c31af7Sopenharmony_ci		};
4044e5c31af7Sopenharmony_ci		vertexAttribs.push_back(attr);
4045e5c31af7Sopenharmony_ci	}
4046e5c31af7Sopenharmony_ci
4047e5c31af7Sopenharmony_ci	VkPipelineVertexInputStateCreateInfo		vertexInputStateParams	=
4048e5c31af7Sopenharmony_ci	{
4049e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
4050e5c31af7Sopenharmony_ci		DE_NULL,													//	const void*									pNext;
4051e5c31af7Sopenharmony_ci		(VkPipelineVertexInputStateCreateFlags)0,
4052e5c31af7Sopenharmony_ci		1u,															//	deUint32									bindingCount;
4053e5c31af7Sopenharmony_ci		vertexBindings.data(),										//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
4054e5c31af7Sopenharmony_ci		2u,															//	deUint32									attributeCount;
4055e5c31af7Sopenharmony_ci		vertexAttribs.data(),										//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
4056e5c31af7Sopenharmony_ci	};
4057e5c31af7Sopenharmony_ci
4058e5c31af7Sopenharmony_ci	if (needInterface)
4059e5c31af7Sopenharmony_ci	{
4060e5c31af7Sopenharmony_ci		vertexInputStateParams.vertexBindingDescriptionCount += 1;
4061e5c31af7Sopenharmony_ci		vertexInputStateParams.vertexAttributeDescriptionCount += 1;
4062e5c31af7Sopenharmony_ci	}
4063e5c31af7Sopenharmony_ci
4064e5c31af7Sopenharmony_ci	vector<VkPipelineColorBlendAttachmentState>	attBlendStates;
4065e5c31af7Sopenharmony_ci	const VkPipelineColorBlendAttachmentState	attBlendState			=
4066e5c31af7Sopenharmony_ci	{
4067e5c31af7Sopenharmony_ci		DE_FALSE,													//	deUint32		blendEnable;
4068e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_ONE,										//	VkBlend			srcBlendColor;
4069e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_ZERO,										//	VkBlend			destBlendColor;
4070e5c31af7Sopenharmony_ci		VK_BLEND_OP_ADD,											//	VkBlendOp		blendOpColor;
4071e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_ONE,										//	VkBlend			srcBlendAlpha;
4072e5c31af7Sopenharmony_ci		VK_BLEND_FACTOR_ZERO,										//	VkBlend			destBlendAlpha;
4073e5c31af7Sopenharmony_ci		VK_BLEND_OP_ADD,											//	VkBlendOp		blendOpAlpha;
4074e5c31af7Sopenharmony_ci		(VK_COLOR_COMPONENT_R_BIT|
4075e5c31af7Sopenharmony_ci		 VK_COLOR_COMPONENT_G_BIT|
4076e5c31af7Sopenharmony_ci		 VK_COLOR_COMPONENT_B_BIT|
4077e5c31af7Sopenharmony_ci		 VK_COLOR_COMPONENT_A_BIT),									//	VkChannelFlags	channelWriteMask;
4078e5c31af7Sopenharmony_ci	};
4079e5c31af7Sopenharmony_ci	attBlendStates.push_back(attBlendState);
4080e5c31af7Sopenharmony_ci
4081e5c31af7Sopenharmony_ci	if (needInterface)
4082e5c31af7Sopenharmony_ci		attBlendStates.push_back(attBlendState);
4083e5c31af7Sopenharmony_ci
4084e5c31af7Sopenharmony_ci	VkPipelineColorBlendStateCreateInfo		blendParams				=
4085e5c31af7Sopenharmony_ci	{
4086e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
4087e5c31af7Sopenharmony_ci		DE_NULL,													//	const void*									pNext;
4088e5c31af7Sopenharmony_ci		(VkPipelineColorBlendStateCreateFlags)0,
4089e5c31af7Sopenharmony_ci		DE_FALSE,													//	VkBool32									logicOpEnable;
4090e5c31af7Sopenharmony_ci		VK_LOGIC_OP_COPY,											//	VkLogicOp									logicOp;
4091e5c31af7Sopenharmony_ci		1u,															//	deUint32									attachmentCount;
4092e5c31af7Sopenharmony_ci		attBlendStates.data(),										//	const VkPipelineColorBlendAttachmentState*	pAttachments;
4093e5c31af7Sopenharmony_ci		{ 0.0f, 0.0f, 0.0f, 0.0f },									//	float										blendConst[4];
4094e5c31af7Sopenharmony_ci	};
4095e5c31af7Sopenharmony_ci	if (needInterface)
4096e5c31af7Sopenharmony_ci	{
4097e5c31af7Sopenharmony_ci		blendParams.attachmentCount += 1;
4098e5c31af7Sopenharmony_ci	}
4099e5c31af7Sopenharmony_ci	const VkPipelineTessellationStateCreateInfo	tessellationState	=
4100e5c31af7Sopenharmony_ci	{
4101e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
4102e5c31af7Sopenharmony_ci		DE_NULL,
4103e5c31af7Sopenharmony_ci		(VkPipelineTessellationStateCreateFlags)0,
4104e5c31af7Sopenharmony_ci		3u
4105e5c31af7Sopenharmony_ci	};
4106e5c31af7Sopenharmony_ci
4107e5c31af7Sopenharmony_ci	const	VkDynamicState							dynamicStates[]				=
4108e5c31af7Sopenharmony_ci	{
4109e5c31af7Sopenharmony_ci		VK_DYNAMIC_STATE_SCISSOR
4110e5c31af7Sopenharmony_ci	};
4111e5c31af7Sopenharmony_ci
4112e5c31af7Sopenharmony_ci	const VkPipelineDynamicStateCreateInfo			dynamicStateCreateInfo =
4113e5c31af7Sopenharmony_ci	{
4114e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,  // sType
4115e5c31af7Sopenharmony_ci		DE_NULL,											   // pNext
4116e5c31af7Sopenharmony_ci		0u,													   // flags
4117e5c31af7Sopenharmony_ci		DE_LENGTH_OF_ARRAY(dynamicStates),					   // dynamicStateCount
4118e5c31af7Sopenharmony_ci		dynamicStates										   // pDynamicStates
4119e5c31af7Sopenharmony_ci	};
4120e5c31af7Sopenharmony_ci
4121e5c31af7Sopenharmony_ci	const VkPipelineTessellationStateCreateInfo* tessellationInfo	=	hasTessellation ? &tessellationState: DE_NULL;
4122e5c31af7Sopenharmony_ci	const VkGraphicsPipelineCreateInfo		pipelineParams			=
4123e5c31af7Sopenharmony_ci	{
4124e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,		//	VkStructureType									sType;
4125e5c31af7Sopenharmony_ci		DE_NULL,												//	const void*										pNext;
4126e5c31af7Sopenharmony_ci		0u,														//	VkPipelineCreateFlags							flags;
4127e5c31af7Sopenharmony_ci		(deUint32)shaderStageParams.size(),						//	deUint32										stageCount;
4128e5c31af7Sopenharmony_ci		&shaderStageParams[0],									//	const VkPipelineShaderStageCreateInfo*			pStages;
4129e5c31af7Sopenharmony_ci		&vertexInputStateParams,								//	const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
4130e5c31af7Sopenharmony_ci		&inputAssemblyParams,									//	const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
4131e5c31af7Sopenharmony_ci		tessellationInfo,										//	const VkPipelineTessellationStateCreateInfo*	pTessellationState;
4132e5c31af7Sopenharmony_ci		&viewportParams,										//	const VkPipelineViewportStateCreateInfo*		pViewportState;
4133e5c31af7Sopenharmony_ci		&rasterParams,											//	const VkPipelineRasterStateCreateInfo*			pRasterState;
4134e5c31af7Sopenharmony_ci		&multisampleParams,										//	const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
4135e5c31af7Sopenharmony_ci		&depthStencilParams,									//	const VkPipelineDepthStencilStateCreateInfo*	pDepthStencilState;
4136e5c31af7Sopenharmony_ci		&blendParams,											//	const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
4137e5c31af7Sopenharmony_ci		&dynamicStateCreateInfo,								//	const VkPipelineDynamicStateCreateInfo*			pDynamicState;
4138e5c31af7Sopenharmony_ci		*pipelineLayout,										//	VkPipelineLayout								layout;
4139e5c31af7Sopenharmony_ci		*renderPass,											//	VkRenderPass									renderPass;
4140e5c31af7Sopenharmony_ci		0u,														//	deUint32										subpass;
4141e5c31af7Sopenharmony_ci		DE_NULL,												//	VkPipeline										basePipelineHandle;
4142e5c31af7Sopenharmony_ci		0u,														//	deInt32											basePipelineIndex;
4143e5c31af7Sopenharmony_ci	};
4144e5c31af7Sopenharmony_ci
4145e5c31af7Sopenharmony_ci	const Unique<VkPipeline>				pipeline				(createGraphicsPipeline(vk, device, DE_NULL, &pipelineParams));
4146e5c31af7Sopenharmony_ci
4147e5c31af7Sopenharmony_ci	if (needInterface)
4148e5c31af7Sopenharmony_ci	{
4149e5c31af7Sopenharmony_ci		const VkImageViewCreateInfo			fragOutputViewParams	=
4150e5c31af7Sopenharmony_ci		{
4151e5c31af7Sopenharmony_ci			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			//	VkStructureType				sType;
4152e5c31af7Sopenharmony_ci			DE_NULL,											//	const void*					pNext;
4153e5c31af7Sopenharmony_ci			0u,													//	VkImageViewCreateFlags		flags;
4154e5c31af7Sopenharmony_ci			*fragOutputImage,									//	VkImage						image;
4155e5c31af7Sopenharmony_ci			VK_IMAGE_VIEW_TYPE_2D,								//	VkImageViewType				viewType;
4156e5c31af7Sopenharmony_ci			instance.interfaces.getOutputType().getVkFormat(),	//	VkFormat					format;
4157e5c31af7Sopenharmony_ci			{
4158e5c31af7Sopenharmony_ci				VK_COMPONENT_SWIZZLE_R,
4159e5c31af7Sopenharmony_ci				VK_COMPONENT_SWIZZLE_G,
4160e5c31af7Sopenharmony_ci				VK_COMPONENT_SWIZZLE_B,
4161e5c31af7Sopenharmony_ci				VK_COMPONENT_SWIZZLE_A
4162e5c31af7Sopenharmony_ci			},													//	VkChannelMapping			channels;
4163e5c31af7Sopenharmony_ci			{
4164e5c31af7Sopenharmony_ci				VK_IMAGE_ASPECT_COLOR_BIT,						//	VkImageAspectFlags	aspectMask;
4165e5c31af7Sopenharmony_ci				0u,												//	deUint32			baseMipLevel;
4166e5c31af7Sopenharmony_ci				1u,												//	deUint32			mipLevels;
4167e5c31af7Sopenharmony_ci				0u,												//	deUint32			baseArrayLayer;
4168e5c31af7Sopenharmony_ci				1u,												//	deUint32			arraySize;
4169e5c31af7Sopenharmony_ci			},													//	VkImageSubresourceRange		subresourceRange;
4170e5c31af7Sopenharmony_ci		};
4171e5c31af7Sopenharmony_ci		fragOutputImageView = createImageView(vk, device, &fragOutputViewParams);
4172e5c31af7Sopenharmony_ci		attViews.push_back(*fragOutputImageView);
4173e5c31af7Sopenharmony_ci	}
4174e5c31af7Sopenharmony_ci
4175e5c31af7Sopenharmony_ci	// Framebuffer
4176e5c31af7Sopenharmony_ci	VkFramebufferCreateInfo					framebufferParams		=
4177e5c31af7Sopenharmony_ci	{
4178e5c31af7Sopenharmony_ci		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,				//	VkStructureType		sType;
4179e5c31af7Sopenharmony_ci		DE_NULL,												//	const void*			pNext;
4180e5c31af7Sopenharmony_ci		(VkFramebufferCreateFlags)0,
4181e5c31af7Sopenharmony_ci		*renderPass,											//	VkRenderPass		renderPass;
4182e5c31af7Sopenharmony_ci		1u,														//	deUint32			attachmentCount;
4183e5c31af7Sopenharmony_ci		attViews.data(),										//	const VkImageView*	pAttachments;
4184e5c31af7Sopenharmony_ci		(deUint32)renderSize.x(),								//	deUint32			width;
4185e5c31af7Sopenharmony_ci		(deUint32)renderSize.y(),								//	deUint32			height;
4186e5c31af7Sopenharmony_ci		1u,														//	deUint32			layers;
4187e5c31af7Sopenharmony_ci	};
4188e5c31af7Sopenharmony_ci
4189e5c31af7Sopenharmony_ci	if (needInterface)
4190e5c31af7Sopenharmony_ci		framebufferParams.attachmentCount += 1;
4191e5c31af7Sopenharmony_ci
4192e5c31af7Sopenharmony_ci	const Unique<VkFramebuffer>				framebuffer				(createFramebuffer(vk, device, &framebufferParams));
4193e5c31af7Sopenharmony_ci
4194e5c31af7Sopenharmony_ci	bool firstPass = true;
4195e5c31af7Sopenharmony_ci
4196e5c31af7Sopenharmony_ci	for (int x = 0; x < numRenderSegments; x++)
4197e5c31af7Sopenharmony_ci	{
4198e5c31af7Sopenharmony_ci		for (int y = 0; y < numRenderSegments; y++)
4199e5c31af7Sopenharmony_ci		{
4200e5c31af7Sopenharmony_ci			// Record commands
4201e5c31af7Sopenharmony_ci			beginCommandBuffer(vk, *cmdBuf);
4202e5c31af7Sopenharmony_ci
4203e5c31af7Sopenharmony_ci			if (firstPass)
4204e5c31af7Sopenharmony_ci			{
4205e5c31af7Sopenharmony_ci				const VkMemoryBarrier			vertFlushBarrier	=
4206e5c31af7Sopenharmony_ci				{
4207e5c31af7Sopenharmony_ci					VK_STRUCTURE_TYPE_MEMORY_BARRIER,			//	VkStructureType		sType;
4208e5c31af7Sopenharmony_ci					DE_NULL,									//	const void*			pNext;
4209e5c31af7Sopenharmony_ci					VK_ACCESS_HOST_WRITE_BIT,					//	VkMemoryOutputFlags	outputMask;
4210e5c31af7Sopenharmony_ci					VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,		//	VkMemoryInputFlags	inputMask;
4211e5c31af7Sopenharmony_ci				};
4212e5c31af7Sopenharmony_ci				vector<VkImageMemoryBarrier>	colorAttBarriers;
4213e5c31af7Sopenharmony_ci
4214e5c31af7Sopenharmony_ci				VkImageMemoryBarrier			imgBarrier          =
4215e5c31af7Sopenharmony_ci				{
4216e5c31af7Sopenharmony_ci					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		//	VkStructureType			sType;
4217e5c31af7Sopenharmony_ci					DE_NULL,									//	const void*				pNext;
4218e5c31af7Sopenharmony_ci					0u,											//	VkMemoryOutputFlags		outputMask;
4219e5c31af7Sopenharmony_ci					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		//	VkMemoryInputFlags		inputMask;
4220e5c31af7Sopenharmony_ci					VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout			oldLayout;
4221e5c31af7Sopenharmony_ci					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout			newLayout;
4222e5c31af7Sopenharmony_ci					queueFamilyIndex,							//	deUint32				srcQueueFamilyIndex;
4223e5c31af7Sopenharmony_ci					queueFamilyIndex,							//	deUint32				destQueueFamilyIndex;
4224e5c31af7Sopenharmony_ci					*image,										//	VkImage					image;
4225e5c31af7Sopenharmony_ci					{
4226e5c31af7Sopenharmony_ci						VK_IMAGE_ASPECT_COLOR_BIT,					//	VkImageAspect	aspect;
4227e5c31af7Sopenharmony_ci						0u,											//	deUint32		baseMipLevel;
4228e5c31af7Sopenharmony_ci						1u,											//	deUint32		mipLevels;
4229e5c31af7Sopenharmony_ci						0u,											//	deUint32		baseArraySlice;
4230e5c31af7Sopenharmony_ci						1u,											//	deUint32		arraySize;
4231e5c31af7Sopenharmony_ci					}											//	VkImageSubresourceRange	subresourceRange;
4232e5c31af7Sopenharmony_ci				};
4233e5c31af7Sopenharmony_ci				colorAttBarriers.push_back(imgBarrier);
4234e5c31af7Sopenharmony_ci				if (needInterface)
4235e5c31af7Sopenharmony_ci				{
4236e5c31af7Sopenharmony_ci					imgBarrier.image = *fragOutputImage;
4237e5c31af7Sopenharmony_ci					colorAttBarriers.push_back(imgBarrier);
4238e5c31af7Sopenharmony_ci					vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 2, colorAttBarriers.data());
4239e5c31af7Sopenharmony_ci				}
4240e5c31af7Sopenharmony_ci				else
4241e5c31af7Sopenharmony_ci				{
4242e5c31af7Sopenharmony_ci					vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, colorAttBarriers.data());
4243e5c31af7Sopenharmony_ci				}
4244e5c31af7Sopenharmony_ci			}
4245e5c31af7Sopenharmony_ci
4246e5c31af7Sopenharmony_ci			{
4247e5c31af7Sopenharmony_ci				vector<VkClearValue>			clearValue;
4248e5c31af7Sopenharmony_ci				clearValue.push_back(makeClearValueColorF32(defaulClearColor[0], defaulClearColor[1], defaulClearColor[2], defaulClearColor[3]));
4249e5c31af7Sopenharmony_ci				if (needInterface)
4250e5c31af7Sopenharmony_ci				{
4251e5c31af7Sopenharmony_ci					clearValue.push_back(makeClearValueColorU32(0, 0, 0, 0));
4252e5c31af7Sopenharmony_ci				}
4253e5c31af7Sopenharmony_ci
4254e5c31af7Sopenharmony_ci
4255e5c31af7Sopenharmony_ci				vk::VkRect2D scissor = makeRect2D(x * renderDimension, y * renderDimension, renderDimension, renderDimension);
4256e5c31af7Sopenharmony_ci				vk.cmdSetScissor(*cmdBuf, 0u, 1u, &scissor);
4257e5c31af7Sopenharmony_ci
4258e5c31af7Sopenharmony_ci				beginRenderPass(vk, *cmdBuf, *renderPass, *framebuffer, scissor, (deUint32)clearValue.size(), clearValue.data());
4259e5c31af7Sopenharmony_ci			}
4260e5c31af7Sopenharmony_ci
4261e5c31af7Sopenharmony_ci			vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
4262e5c31af7Sopenharmony_ci			{
4263e5c31af7Sopenharmony_ci				const VkDeviceSize bindingOffset = 0;
4264e5c31af7Sopenharmony_ci				vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
4265e5c31af7Sopenharmony_ci			}
4266e5c31af7Sopenharmony_ci			if (needInterface)
4267e5c31af7Sopenharmony_ci			{
4268e5c31af7Sopenharmony_ci				const VkDeviceSize bindingOffset = 0;
4269e5c31af7Sopenharmony_ci				vk.cmdBindVertexBuffers(*cmdBuf, 1u, 1u, &vertexInputBuffer.get(), &bindingOffset);
4270e5c31af7Sopenharmony_ci			}
4271e5c31af7Sopenharmony_ci			if (hasPushConstants)
4272e5c31af7Sopenharmony_ci			{
4273e5c31af7Sopenharmony_ci				vector<deUint8> pushConstantsBytes;
4274e5c31af7Sopenharmony_ci				instance.pushConstants.getBuffer()->getBytes(pushConstantsBytes);
4275e5c31af7Sopenharmony_ci
4276e5c31af7Sopenharmony_ci				const deUint32	size	= static_cast<deUint32>(pushConstantsBytes.size());
4277e5c31af7Sopenharmony_ci				const void*		data	= &pushConstantsBytes.front();
4278e5c31af7Sopenharmony_ci
4279e5c31af7Sopenharmony_ci				vk.cmdPushConstants(*cmdBuf, *pipelineLayout, VK_SHADER_STAGE_ALL_GRAPHICS, 0, size, data);
4280e5c31af7Sopenharmony_ci			}
4281e5c31af7Sopenharmony_ci			if (numResources != 0)
4282e5c31af7Sopenharmony_ci			{
4283e5c31af7Sopenharmony_ci				// Bind to set number 0.
4284e5c31af7Sopenharmony_ci				vk.cmdBindDescriptorSets(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, &rawSet, 0, DE_NULL);
4285e5c31af7Sopenharmony_ci			}
4286e5c31af7Sopenharmony_ci			vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/);
4287e5c31af7Sopenharmony_ci			endRenderPass(vk, *cmdBuf);
4288e5c31af7Sopenharmony_ci
4289e5c31af7Sopenharmony_ci			if (x == numRenderSegments - 1 && y == numRenderSegments - 1)
4290e5c31af7Sopenharmony_ci			{
4291e5c31af7Sopenharmony_ci				{
4292e5c31af7Sopenharmony_ci					vector<VkImageMemoryBarrier>	renderFinishBarrier;
4293e5c31af7Sopenharmony_ci					VkImageMemoryBarrier			imgBarrier				=
4294e5c31af7Sopenharmony_ci					{
4295e5c31af7Sopenharmony_ci						VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		//	VkStructureType			sType;
4296e5c31af7Sopenharmony_ci						DE_NULL,									//	const void*				pNext;
4297e5c31af7Sopenharmony_ci						VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		//	VkMemoryOutputFlags		outputMask;
4298e5c31af7Sopenharmony_ci						VK_ACCESS_TRANSFER_READ_BIT,				//	VkMemoryInputFlags		inputMask;
4299e5c31af7Sopenharmony_ci						VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout			oldLayout;
4300e5c31af7Sopenharmony_ci						VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		//	VkImageLayout			newLayout;
4301e5c31af7Sopenharmony_ci						queueFamilyIndex,							//	deUint32				srcQueueFamilyIndex;
4302e5c31af7Sopenharmony_ci						queueFamilyIndex,							//	deUint32				destQueueFamilyIndex;
4303e5c31af7Sopenharmony_ci						*image,										//	VkImage					image;
4304e5c31af7Sopenharmony_ci						{
4305e5c31af7Sopenharmony_ci							VK_IMAGE_ASPECT_COLOR_BIT,					//	VkImageAspectFlags	aspectMask;
4306e5c31af7Sopenharmony_ci							0u,											//	deUint32			baseMipLevel;
4307e5c31af7Sopenharmony_ci							1u,											//	deUint32			mipLevels;
4308e5c31af7Sopenharmony_ci							0u,											//	deUint32			baseArraySlice;
4309e5c31af7Sopenharmony_ci							1u,											//	deUint32			arraySize;
4310e5c31af7Sopenharmony_ci						}											//	VkImageSubresourceRange	subresourceRange;
4311e5c31af7Sopenharmony_ci					};
4312e5c31af7Sopenharmony_ci					renderFinishBarrier.push_back(imgBarrier);
4313e5c31af7Sopenharmony_ci
4314e5c31af7Sopenharmony_ci					if (needInterface)
4315e5c31af7Sopenharmony_ci					{
4316e5c31af7Sopenharmony_ci						imgBarrier.image = *fragOutputImage;
4317e5c31af7Sopenharmony_ci						renderFinishBarrier.push_back(imgBarrier);
4318e5c31af7Sopenharmony_ci						vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 2, renderFinishBarrier.data());
4319e5c31af7Sopenharmony_ci					}
4320e5c31af7Sopenharmony_ci					else
4321e5c31af7Sopenharmony_ci					{
4322e5c31af7Sopenharmony_ci						vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, renderFinishBarrier.data());
4323e5c31af7Sopenharmony_ci					}
4324e5c31af7Sopenharmony_ci				}
4325e5c31af7Sopenharmony_ci
4326e5c31af7Sopenharmony_ci				{
4327e5c31af7Sopenharmony_ci					const VkBufferImageCopy	copyParams	=
4328e5c31af7Sopenharmony_ci					{
4329e5c31af7Sopenharmony_ci						(VkDeviceSize)0u,						//	VkDeviceSize			bufferOffset;
4330e5c31af7Sopenharmony_ci						(deUint32)renderSize.x(),				//	deUint32				bufferRowLength;
4331e5c31af7Sopenharmony_ci						(deUint32)renderSize.y(),				//	deUint32				bufferImageHeight;
4332e5c31af7Sopenharmony_ci						{
4333e5c31af7Sopenharmony_ci							VK_IMAGE_ASPECT_COLOR_BIT,				//	VkImageAspect		aspect;
4334e5c31af7Sopenharmony_ci							0u,										//	deUint32			mipLevel;
4335e5c31af7Sopenharmony_ci							0u,										//	deUint32			arrayLayer;
4336e5c31af7Sopenharmony_ci							1u,										//	deUint32			arraySize;
4337e5c31af7Sopenharmony_ci						},										//	VkImageSubresourceCopy	imageSubresource;
4338e5c31af7Sopenharmony_ci						{ 0u, 0u, 0u },							//	VkOffset3D				imageOffset;
4339e5c31af7Sopenharmony_ci						{ renderSize.x(), renderSize.y(), 1u }
4340e5c31af7Sopenharmony_ci					};
4341e5c31af7Sopenharmony_ci					vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
4342e5c31af7Sopenharmony_ci
4343e5c31af7Sopenharmony_ci					if (needInterface)
4344e5c31af7Sopenharmony_ci					{
4345e5c31af7Sopenharmony_ci						vk.cmdCopyImageToBuffer(*cmdBuf, *fragOutputImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *fragOutputBuffer, 1u, &copyParams);
4346e5c31af7Sopenharmony_ci					}
4347e5c31af7Sopenharmony_ci				}
4348e5c31af7Sopenharmony_ci
4349e5c31af7Sopenharmony_ci				{
4350e5c31af7Sopenharmony_ci					vector<VkBufferMemoryBarrier>	cpFinishBarriers;
4351e5c31af7Sopenharmony_ci					VkBufferMemoryBarrier			copyFinishBarrier	=
4352e5c31af7Sopenharmony_ci					{
4353e5c31af7Sopenharmony_ci						VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	//	VkStructureType		sType;
4354e5c31af7Sopenharmony_ci						DE_NULL,									//	const void*			pNext;
4355e5c31af7Sopenharmony_ci						VK_ACCESS_TRANSFER_WRITE_BIT,				//	VkMemoryOutputFlags	outputMask;
4356e5c31af7Sopenharmony_ci						VK_ACCESS_HOST_READ_BIT,					//	VkMemoryInputFlags	inputMask;
4357e5c31af7Sopenharmony_ci						queueFamilyIndex,							//	deUint32			srcQueueFamilyIndex;
4358e5c31af7Sopenharmony_ci						queueFamilyIndex,							//	deUint32			destQueueFamilyIndex;
4359e5c31af7Sopenharmony_ci						*readImageBuffer,							//	VkBuffer			buffer;
4360e5c31af7Sopenharmony_ci						0u,											//	VkDeviceSize		offset;
4361e5c31af7Sopenharmony_ci						imageSizeBytes								//	VkDeviceSize		size;
4362e5c31af7Sopenharmony_ci					};
4363e5c31af7Sopenharmony_ci					cpFinishBarriers.push_back(copyFinishBarrier);
4364e5c31af7Sopenharmony_ci
4365e5c31af7Sopenharmony_ci					if (needInterface)
4366e5c31af7Sopenharmony_ci					{
4367e5c31af7Sopenharmony_ci						copyFinishBarrier.buffer	= *fragOutputBuffer;
4368e5c31af7Sopenharmony_ci						copyFinishBarrier.size		= VK_WHOLE_SIZE;
4369e5c31af7Sopenharmony_ci						cpFinishBarriers.push_back(copyFinishBarrier);
4370e5c31af7Sopenharmony_ci
4371e5c31af7Sopenharmony_ci						vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 2, cpFinishBarriers.data(), 0, (const VkImageMemoryBarrier*)DE_NULL);
4372e5c31af7Sopenharmony_ci					}
4373e5c31af7Sopenharmony_ci					else
4374e5c31af7Sopenharmony_ci					{
4375e5c31af7Sopenharmony_ci						vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, cpFinishBarriers.data(), 0, (const VkImageMemoryBarrier*)DE_NULL);
4376e5c31af7Sopenharmony_ci					}
4377e5c31af7Sopenharmony_ci				}
4378e5c31af7Sopenharmony_ci				}
4379e5c31af7Sopenharmony_ci
4380e5c31af7Sopenharmony_ci			endCommandBuffer(vk, *cmdBuf);
4381e5c31af7Sopenharmony_ci
4382e5c31af7Sopenharmony_ci			if (firstPass)
4383e5c31af7Sopenharmony_ci			{
4384e5c31af7Sopenharmony_ci				// Upload vertex data
4385e5c31af7Sopenharmony_ci				{
4386e5c31af7Sopenharmony_ci					void* vertexBufPtr = vertexBufferMemory->getHostPtr();
4387e5c31af7Sopenharmony_ci					deMemcpy(vertexBufPtr, &vertexData[0], vertexDataSize);
4388e5c31af7Sopenharmony_ci					flushAlloc(vk, device, *vertexBufferMemory);
4389e5c31af7Sopenharmony_ci				}
4390e5c31af7Sopenharmony_ci
4391e5c31af7Sopenharmony_ci				if (needInterface)
4392e5c31af7Sopenharmony_ci				{
4393e5c31af7Sopenharmony_ci					vector<deUint8> inputBufferBytes;
4394e5c31af7Sopenharmony_ci					instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
4395e5c31af7Sopenharmony_ci
4396e5c31af7Sopenharmony_ci					const deUint32				typNumBytes		= instance.interfaces.getInputType().getNumBytes();
4397e5c31af7Sopenharmony_ci					const deUint32				bufNumBytes		= static_cast<deUint32>(inputBufferBytes.size());
4398e5c31af7Sopenharmony_ci
4399e5c31af7Sopenharmony_ci					// Require that the test instantation provides four output values.
4400e5c31af7Sopenharmony_ci					DE_ASSERT(bufNumBytes == 4 * typNumBytes);
4401e5c31af7Sopenharmony_ci
4402e5c31af7Sopenharmony_ci					// We have four triangles. Because interpolation happens before executing the fragment shader,
4403e5c31af7Sopenharmony_ci					// we need to provide the same vertex attribute for the same triangle. That means, duplicate each
4404e5c31af7Sopenharmony_ci					// value three times for all four values.
4405e5c31af7Sopenharmony_ci
4406e5c31af7Sopenharmony_ci					const deUint8*				provided		= static_cast<const deUint8*>(&inputBufferBytes.front());
4407e5c31af7Sopenharmony_ci					vector<deUint8>				data;
4408e5c31af7Sopenharmony_ci
4409e5c31af7Sopenharmony_ci					data.reserve(3 * bufNumBytes);
4410e5c31af7Sopenharmony_ci
4411e5c31af7Sopenharmony_ci					for (deUint32 offset = 0; offset < bufNumBytes; offset += typNumBytes)
4412e5c31af7Sopenharmony_ci						for (deUint32 vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
4413e5c31af7Sopenharmony_ci							for (deUint32 byteNdx = 0; byteNdx < typNumBytes; ++byteNdx)
4414e5c31af7Sopenharmony_ci								data.push_back(provided[offset + byteNdx]);
4415e5c31af7Sopenharmony_ci
4416e5c31af7Sopenharmony_ci					deMemcpy(vertexInputMemory->getHostPtr(), data.data(), data.size());
4417e5c31af7Sopenharmony_ci
4418e5c31af7Sopenharmony_ci					flushAlloc(vk, device, *vertexInputMemory);
4419e5c31af7Sopenharmony_ci
4420e5c31af7Sopenharmony_ci				}
4421e5c31af7Sopenharmony_ci				firstPass = false;
4422e5c31af7Sopenharmony_ci			}
4423e5c31af7Sopenharmony_ci
4424e5c31af7Sopenharmony_ci			// Submit & wait for completion
4425e5c31af7Sopenharmony_ci			submitCommandsAndWait(vk, device, queue, cmdBuf.get());
4426e5c31af7Sopenharmony_ci			context.resetCommandPoolForVKSC(device, *cmdPool);
4427e5c31af7Sopenharmony_ci		}
4428e5c31af7Sopenharmony_ci	}
4429e5c31af7Sopenharmony_ci
4430e5c31af7Sopenharmony_ci	const void* imagePtr	= readImageBufferMemory->getHostPtr();
4431e5c31af7Sopenharmony_ci	const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
4432e5c31af7Sopenharmony_ci												  renderSize.x(), renderSize.y(), 1, imagePtr);
4433e5c31af7Sopenharmony_ci	// Log image
4434e5c31af7Sopenharmony_ci	invalidateAlloc(vk, device, *readImageBufferMemory);
4435e5c31af7Sopenharmony_ci	context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer);
4436e5c31af7Sopenharmony_ci
4437e5c31af7Sopenharmony_ci	if (needInterface)
4438e5c31af7Sopenharmony_ci		invalidateAlloc(vk, device, *fragOutputMemory);
4439e5c31af7Sopenharmony_ci
4440e5c31af7Sopenharmony_ci	// Make sure all output resources are ready.
4441e5c31af7Sopenharmony_ci	for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
4442e5c31af7Sopenharmony_ci		invalidateAlloc(vk, device, *outResourceMemories[outputNdx]);
4443e5c31af7Sopenharmony_ci
4444e5c31af7Sopenharmony_ci	const RGBA threshold(1, 1, 1, 1);
4445e5c31af7Sopenharmony_ci
4446e5c31af7Sopenharmony_ci	const RGBA upperLeft(pixelBuffer.getPixel(1, 1));
4447e5c31af7Sopenharmony_ci	if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold))
4448e5c31af7Sopenharmony_ci		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper left corner mismatch"));
4449e5c31af7Sopenharmony_ci
4450e5c31af7Sopenharmony_ci	const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1));
4451e5c31af7Sopenharmony_ci	if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold))
4452e5c31af7Sopenharmony_ci		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper right corner mismatch"));
4453e5c31af7Sopenharmony_ci
4454e5c31af7Sopenharmony_ci	const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1));
4455e5c31af7Sopenharmony_ci	if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold))
4456e5c31af7Sopenharmony_ci		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower left corner mismatch"));
4457e5c31af7Sopenharmony_ci
4458e5c31af7Sopenharmony_ci	const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1));
4459e5c31af7Sopenharmony_ci	if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold))
4460e5c31af7Sopenharmony_ci		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower right corner mismatch"));
4461e5c31af7Sopenharmony_ci
4462e5c31af7Sopenharmony_ci	// Check that the contents in the ouput variable matches expected.
4463e5c31af7Sopenharmony_ci	if (needInterface)
4464e5c31af7Sopenharmony_ci	{
4465e5c31af7Sopenharmony_ci		vector<deUint8>						inputBufferBytes;
4466e5c31af7Sopenharmony_ci		vector<deUint8>						outputBufferBytes;
4467e5c31af7Sopenharmony_ci
4468e5c31af7Sopenharmony_ci		instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
4469e5c31af7Sopenharmony_ci		instance.interfaces.getOutputBuffer()->getBytes(outputBufferBytes);
4470e5c31af7Sopenharmony_ci
4471e5c31af7Sopenharmony_ci		const IFDataType&					inputType				= instance.interfaces.getInputType();
4472e5c31af7Sopenharmony_ci		const IFDataType&					outputType				= instance.interfaces.getOutputType();
4473e5c31af7Sopenharmony_ci		const void*							inputData				= &inputBufferBytes.front();
4474e5c31af7Sopenharmony_ci		const void*							outputData				= &outputBufferBytes.front();
4475e5c31af7Sopenharmony_ci		vector<std::pair<int, int> >		positions;
4476e5c31af7Sopenharmony_ci		const tcu::ConstPixelBufferAccess	fragOutputBufferAccess	(outputType.getTextureFormat(), renderSize.x(), renderSize.y(), 1, fragOutputMemory->getHostPtr());
4477e5c31af7Sopenharmony_ci
4478e5c31af7Sopenharmony_ci		positions.push_back(std::make_pair(1, 1));
4479e5c31af7Sopenharmony_ci		positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, 1));
4480e5c31af7Sopenharmony_ci		positions.push_back(std::make_pair(1, fragOutputBufferAccess.getHeight() - 1));
4481e5c31af7Sopenharmony_ci		positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, fragOutputBufferAccess.getHeight() - 1));
4482e5c31af7Sopenharmony_ci
4483e5c31af7Sopenharmony_ci		for (deUint32 posNdx = 0; posNdx < positions.size(); ++posNdx)
4484e5c31af7Sopenharmony_ci		{
4485e5c31af7Sopenharmony_ci			const int	x		= positions[posNdx].first;
4486e5c31af7Sopenharmony_ci			const int	y		= positions[posNdx].second;
4487e5c31af7Sopenharmony_ci			bool		equal	= true;
4488e5c31af7Sopenharmony_ci
4489e5c31af7Sopenharmony_ci			if (outputType.elementType == NUMBERTYPE_FLOAT32)
4490e5c31af7Sopenharmony_ci			{
4491e5c31af7Sopenharmony_ci				const float*		expected	= static_cast<const float*>(outputData) + posNdx * outputType.numElements;
4492e5c31af7Sopenharmony_ci				const float*		actual		= static_cast<const float*>(fragOutputBufferAccess.getPixelPtr(x, y));
4493e5c31af7Sopenharmony_ci
4494e5c31af7Sopenharmony_ci				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4495e5c31af7Sopenharmony_ci					if (!compare32BitFloat(expected[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4496e5c31af7Sopenharmony_ci						equal = false;
4497e5c31af7Sopenharmony_ci			}
4498e5c31af7Sopenharmony_ci			else if (outputType.elementType == NUMBERTYPE_INT32)
4499e5c31af7Sopenharmony_ci			{
4500e5c31af7Sopenharmony_ci				const deInt32*		expected	= static_cast<const deInt32*>(outputData) + posNdx * outputType.numElements;
4501e5c31af7Sopenharmony_ci				const deInt32*		actual		= static_cast<const deInt32*>(fragOutputBufferAccess.getPixelPtr(x, y));
4502e5c31af7Sopenharmony_ci
4503e5c31af7Sopenharmony_ci				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4504e5c31af7Sopenharmony_ci					if (expected[eleNdx] != actual[eleNdx])
4505e5c31af7Sopenharmony_ci						equal = false;
4506e5c31af7Sopenharmony_ci			}
4507e5c31af7Sopenharmony_ci			else if (outputType.elementType == NUMBERTYPE_UINT32)
4508e5c31af7Sopenharmony_ci			{
4509e5c31af7Sopenharmony_ci				const deUint32*		expected	= static_cast<const deUint32*>(outputData) + posNdx * outputType.numElements;
4510e5c31af7Sopenharmony_ci				const deUint32*		actual		= static_cast<const deUint32*>(fragOutputBufferAccess.getPixelPtr(x, y));
4511e5c31af7Sopenharmony_ci
4512e5c31af7Sopenharmony_ci				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4513e5c31af7Sopenharmony_ci					if (expected[eleNdx] != actual[eleNdx])
4514e5c31af7Sopenharmony_ci						equal = false;
4515e5c31af7Sopenharmony_ci			}
4516e5c31af7Sopenharmony_ci			else if (outputType.elementType == NUMBERTYPE_FLOAT16 && inputType.elementType == NUMBERTYPE_FLOAT64)
4517e5c31af7Sopenharmony_ci			{
4518e5c31af7Sopenharmony_ci				const double*		original	= static_cast<const double*>(inputData) + posNdx * outputType.numElements;
4519e5c31af7Sopenharmony_ci				const deFloat16*	actual		= static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4520e5c31af7Sopenharmony_ci
4521e5c31af7Sopenharmony_ci				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4522e5c31af7Sopenharmony_ci					if (!compare16BitFloat64(original[eleNdx], actual[eleNdx], instance.interfaces.getRoundingMode(), context.getTestContext().getLog()))
4523e5c31af7Sopenharmony_ci						equal = false;
4524e5c31af7Sopenharmony_ci			}
4525e5c31af7Sopenharmony_ci			else if (outputType.elementType == NUMBERTYPE_FLOAT16 && inputType.elementType != NUMBERTYPE_FLOAT64)
4526e5c31af7Sopenharmony_ci			{
4527e5c31af7Sopenharmony_ci				if (inputType.elementType == NUMBERTYPE_FLOAT16)
4528e5c31af7Sopenharmony_ci				{
4529e5c31af7Sopenharmony_ci					const deFloat16*	original	= static_cast<const deFloat16*>(inputData) + posNdx * outputType.numElements;
4530e5c31af7Sopenharmony_ci					const deFloat16*	actual		= static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4531e5c31af7Sopenharmony_ci
4532e5c31af7Sopenharmony_ci					for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4533e5c31af7Sopenharmony_ci						if (!compare16BitFloat(original[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4534e5c31af7Sopenharmony_ci							equal = false;
4535e5c31af7Sopenharmony_ci				}
4536e5c31af7Sopenharmony_ci				else
4537e5c31af7Sopenharmony_ci				{
4538e5c31af7Sopenharmony_ci					const float*		original	= static_cast<const float*>(inputData) + posNdx * outputType.numElements;
4539e5c31af7Sopenharmony_ci					const deFloat16*	actual		= static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4540e5c31af7Sopenharmony_ci
4541e5c31af7Sopenharmony_ci					for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4542e5c31af7Sopenharmony_ci						if (!compare16BitFloat(original[eleNdx], actual[eleNdx], instance.interfaces.getRoundingMode(), context.getTestContext().getLog()))
4543e5c31af7Sopenharmony_ci							equal = false;
4544e5c31af7Sopenharmony_ci				}
4545e5c31af7Sopenharmony_ci			}
4546e5c31af7Sopenharmony_ci			else if (outputType.elementType == NUMBERTYPE_INT16)
4547e5c31af7Sopenharmony_ci			{
4548e5c31af7Sopenharmony_ci				const deInt16*		expected	= static_cast<const deInt16*>(outputData) + posNdx * outputType.numElements;
4549e5c31af7Sopenharmony_ci				const deInt16*		actual		= static_cast<const deInt16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4550e5c31af7Sopenharmony_ci
4551e5c31af7Sopenharmony_ci				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4552e5c31af7Sopenharmony_ci					if (expected[eleNdx] != actual[eleNdx])
4553e5c31af7Sopenharmony_ci						equal = false;
4554e5c31af7Sopenharmony_ci			}
4555e5c31af7Sopenharmony_ci			else if (outputType.elementType == NUMBERTYPE_UINT16)
4556e5c31af7Sopenharmony_ci			{
4557e5c31af7Sopenharmony_ci				const deUint16*		expected	= static_cast<const deUint16*>(outputData) + posNdx * outputType.numElements;
4558e5c31af7Sopenharmony_ci				const deUint16*		actual		= static_cast<const deUint16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4559e5c31af7Sopenharmony_ci
4560e5c31af7Sopenharmony_ci				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4561e5c31af7Sopenharmony_ci					if (expected[eleNdx] != actual[eleNdx])
4562e5c31af7Sopenharmony_ci						equal = false;
4563e5c31af7Sopenharmony_ci			}
4564e5c31af7Sopenharmony_ci			else if (outputType.elementType == NUMBERTYPE_FLOAT64)
4565e5c31af7Sopenharmony_ci			{
4566e5c31af7Sopenharmony_ci				const double*		expected	= static_cast<const double*>(outputData) + posNdx * outputType.numElements;
4567e5c31af7Sopenharmony_ci				const double*		actual		= static_cast<const double*>(fragOutputBufferAccess.getPixelPtr(x, y));
4568e5c31af7Sopenharmony_ci
4569e5c31af7Sopenharmony_ci				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4570e5c31af7Sopenharmony_ci					if (!compare64BitFloat(expected[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4571e5c31af7Sopenharmony_ci						equal = false;
4572e5c31af7Sopenharmony_ci			}
4573e5c31af7Sopenharmony_ci			else {
4574e5c31af7Sopenharmony_ci				DE_ASSERT(0 && "unhandled type");
4575e5c31af7Sopenharmony_ci			}
4576e5c31af7Sopenharmony_ci
4577e5c31af7Sopenharmony_ci			if (!equal)
4578e5c31af7Sopenharmony_ci				return TestStatus(instance.failResult, instance.getSpecializedFailMessage("fragment output dat point #" + numberToString(posNdx) + " mismatch"));
4579e5c31af7Sopenharmony_ci		}
4580e5c31af7Sopenharmony_ci	}
4581e5c31af7Sopenharmony_ci
4582e5c31af7Sopenharmony_ci	// Check the contents in output resources match with expected.
4583e5c31af7Sopenharmony_ci	for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
4584e5c31af7Sopenharmony_ci	{
4585e5c31af7Sopenharmony_ci		const BufferSp& expected = instance.resources.outputs[outputNdx].getBuffer();
4586e5c31af7Sopenharmony_ci
4587e5c31af7Sopenharmony_ci		if (instance.resources.verifyIO != DE_NULL)
4588e5c31af7Sopenharmony_ci		{
4589e5c31af7Sopenharmony_ci			if (!(*instance.resources.verifyIO)(instance.resources.inputs, outResourceMemories, instance.resources.outputs, context.getTestContext().getLog()))
4590e5c31af7Sopenharmony_ci				return tcu::TestStatus::fail("Resource returned doesn't match with expected");
4591e5c31af7Sopenharmony_ci		}
4592e5c31af7Sopenharmony_ci		else
4593e5c31af7Sopenharmony_ci		{
4594e5c31af7Sopenharmony_ci			vector<deUint8> expectedBytes;
4595e5c31af7Sopenharmony_ci			expected->getBytes(expectedBytes);
4596e5c31af7Sopenharmony_ci
4597e5c31af7Sopenharmony_ci			if (deMemCmp(&expectedBytes.front(), outResourceMemories[outputNdx]->getHostPtr(), expectedBytes.size()))
4598e5c31af7Sopenharmony_ci			{
4599e5c31af7Sopenharmony_ci				const size_t	numExpectedEntries	= expectedBytes.size() / sizeof(float);
4600e5c31af7Sopenharmony_ci				float*			expectedFloats		= reinterpret_cast<float*>(&expectedBytes.front());
4601e5c31af7Sopenharmony_ci				float*			outputFloats		= reinterpret_cast<float*>(outResourceMemories[outputNdx]->getHostPtr());
4602e5c31af7Sopenharmony_ci				float			diff				= 0.0f;
4603e5c31af7Sopenharmony_ci				deUint32		bitDiff				= 0;
4604e5c31af7Sopenharmony_ci
4605e5c31af7Sopenharmony_ci				for (size_t expectedNdx = 0; expectedNdx < numExpectedEntries; ++expectedNdx)
4606e5c31af7Sopenharmony_ci				{
4607e5c31af7Sopenharmony_ci					// RTZ and RNE can introduce a difference of a single ULP
4608e5c31af7Sopenharmony_ci					// The RTZ output will always be either equal or lower than the RNE expected,
4609e5c31af7Sopenharmony_ci					// so perform a bitwise subtractraction and check for the ULP difference
4610e5c31af7Sopenharmony_ci					bitDiff = *reinterpret_cast<deUint32*>(&expectedFloats[expectedNdx]) - *reinterpret_cast<deUint32*>(&outputFloats[expectedNdx]);
4611e5c31af7Sopenharmony_ci
4612e5c31af7Sopenharmony_ci					// Allow a maximum of 1 ULP difference to account for RTZ rounding
4613e5c31af7Sopenharmony_ci					if (bitDiff & (~0x1))
4614e5c31af7Sopenharmony_ci					{
4615e5c31af7Sopenharmony_ci						// Note: RTZ/RNE rounding leniency isn't applied for the checks below:
4616e5c31af7Sopenharmony_ci
4617e5c31af7Sopenharmony_ci						// Some *variable_pointers* tests store counters in buffer
4618e5c31af7Sopenharmony_ci						// whose value may vary if the same shader may be executed for multiple times
4619e5c31af7Sopenharmony_ci						// in this case the output value can be expected value + non-negative integer N
4620e5c31af7Sopenharmony_ci						if (instance.customizedStages == VK_SHADER_STAGE_VERTEX_BIT ||
4621e5c31af7Sopenharmony_ci							instance.customizedStages == VK_SHADER_STAGE_GEOMETRY_BIT ||
4622e5c31af7Sopenharmony_ci							instance.customizedStages == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
4623e5c31af7Sopenharmony_ci							instance.customizedStages == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
4624e5c31af7Sopenharmony_ci						{
4625e5c31af7Sopenharmony_ci							if (deFloatIsInf(outputFloats[expectedNdx]) || deFloatIsNaN(outputFloats[expectedNdx]))
4626e5c31af7Sopenharmony_ci								return tcu::TestStatus::fail("Value returned is invalid");
4627e5c31af7Sopenharmony_ci
4628e5c31af7Sopenharmony_ci							diff = outputFloats[expectedNdx] - expectedFloats[expectedNdx];
4629e5c31af7Sopenharmony_ci							deUint32 intDiff = static_cast<deUint32>(diff);
4630e5c31af7Sopenharmony_ci
4631e5c31af7Sopenharmony_ci							if ((diff < 0.0f) || (expectedFloats[expectedNdx] + static_cast<float>(intDiff)) != outputFloats[expectedNdx])
4632e5c31af7Sopenharmony_ci								return tcu::TestStatus::fail("Value returned should be equal to expected value plus non-negative integer");
4633e5c31af7Sopenharmony_ci						}
4634e5c31af7Sopenharmony_ci						else
4635e5c31af7Sopenharmony_ci						{
4636e5c31af7Sopenharmony_ci							return tcu::TestStatus::fail("Resource returned should be equal to expected, allowing for RTZ/RNE rounding");
4637e5c31af7Sopenharmony_ci						}
4638e5c31af7Sopenharmony_ci					}
4639e5c31af7Sopenharmony_ci				}
4640e5c31af7Sopenharmony_ci			}
4641e5c31af7Sopenharmony_ci
4642e5c31af7Sopenharmony_ci		}
4643e5c31af7Sopenharmony_ci	}
4644e5c31af7Sopenharmony_ci
4645e5c31af7Sopenharmony_ci	return TestStatus::pass("Rendered output matches input");
4646e5c31af7Sopenharmony_ci}
4647e5c31af7Sopenharmony_ci
4648e5c31af7Sopenharmony_ciconst vector<ShaderElement>& getVertFragPipelineStages (void)
4649e5c31af7Sopenharmony_ci{
4650e5c31af7Sopenharmony_ci	static vector<ShaderElement> vertFragPipelineStages;
4651e5c31af7Sopenharmony_ci	if(vertFragPipelineStages.empty())
4652e5c31af7Sopenharmony_ci	{
4653e5c31af7Sopenharmony_ci		vertFragPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4654e5c31af7Sopenharmony_ci		vertFragPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4655e5c31af7Sopenharmony_ci	}
4656e5c31af7Sopenharmony_ci	return vertFragPipelineStages;
4657e5c31af7Sopenharmony_ci}
4658e5c31af7Sopenharmony_ci
4659e5c31af7Sopenharmony_ciconst vector<ShaderElement>& getTessPipelineStages (void)
4660e5c31af7Sopenharmony_ci{
4661e5c31af7Sopenharmony_ci	static vector<ShaderElement> tessPipelineStages;
4662e5c31af7Sopenharmony_ci	if(tessPipelineStages.empty())
4663e5c31af7Sopenharmony_ci	{
4664e5c31af7Sopenharmony_ci		tessPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4665e5c31af7Sopenharmony_ci		tessPipelineStages.push_back(ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
4666e5c31af7Sopenharmony_ci		tessPipelineStages.push_back(ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
4667e5c31af7Sopenharmony_ci		tessPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4668e5c31af7Sopenharmony_ci	}
4669e5c31af7Sopenharmony_ci	return tessPipelineStages;
4670e5c31af7Sopenharmony_ci}
4671e5c31af7Sopenharmony_ci
4672e5c31af7Sopenharmony_ciconst vector<ShaderElement>& getGeomPipelineStages (void)
4673e5c31af7Sopenharmony_ci{
4674e5c31af7Sopenharmony_ci	static vector<ShaderElement> geomPipelineStages;
4675e5c31af7Sopenharmony_ci	if(geomPipelineStages.empty())
4676e5c31af7Sopenharmony_ci	{
4677e5c31af7Sopenharmony_ci		geomPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4678e5c31af7Sopenharmony_ci		geomPipelineStages.push_back(ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT));
4679e5c31af7Sopenharmony_ci		geomPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4680e5c31af7Sopenharmony_ci	}
4681e5c31af7Sopenharmony_ci	return geomPipelineStages;
4682e5c31af7Sopenharmony_ci}
4683e5c31af7Sopenharmony_ci
4684e5c31af7Sopenharmony_ci// Helper structure used by addTestForStage function.
4685e5c31af7Sopenharmony_cistruct StageData
4686e5c31af7Sopenharmony_ci{
4687e5c31af7Sopenharmony_ci	typedef const vector<ShaderElement>& (*GetPipelineStagesFn)();
4688e5c31af7Sopenharmony_ci	typedef void (*AddShaderCodeCustomStageFn)(vk::SourceCollections&, InstanceContext);
4689e5c31af7Sopenharmony_ci
4690e5c31af7Sopenharmony_ci	GetPipelineStagesFn			getPipelineFn;
4691e5c31af7Sopenharmony_ci	AddShaderCodeCustomStageFn	initProgramsFn;
4692e5c31af7Sopenharmony_ci
4693e5c31af7Sopenharmony_ci	StageData()
4694e5c31af7Sopenharmony_ci		: getPipelineFn(DE_NULL)
4695e5c31af7Sopenharmony_ci		, initProgramsFn(DE_NULL)
4696e5c31af7Sopenharmony_ci	{
4697e5c31af7Sopenharmony_ci	}
4698e5c31af7Sopenharmony_ci
4699e5c31af7Sopenharmony_ci	StageData(GetPipelineStagesFn pipelineGetter, AddShaderCodeCustomStageFn programsInitializer)
4700e5c31af7Sopenharmony_ci		: getPipelineFn(pipelineGetter)
4701e5c31af7Sopenharmony_ci		, initProgramsFn(programsInitializer)
4702e5c31af7Sopenharmony_ci	{
4703e5c31af7Sopenharmony_ci	}
4704e5c31af7Sopenharmony_ci};
4705e5c31af7Sopenharmony_ci
4706e5c31af7Sopenharmony_ci// Helper function used by addTestForStage function.
4707e5c31af7Sopenharmony_ciconst StageData& getStageData (vk::VkShaderStageFlagBits stage)
4708e5c31af7Sopenharmony_ci{
4709e5c31af7Sopenharmony_ci	// Construct map
4710e5c31af7Sopenharmony_ci	static map<vk::VkShaderStageFlagBits, StageData> testedStageData;
4711e5c31af7Sopenharmony_ci	if(testedStageData.empty())
4712e5c31af7Sopenharmony_ci	{
4713e5c31af7Sopenharmony_ci		testedStageData[VK_SHADER_STAGE_VERTEX_BIT]					 = StageData(getVertFragPipelineStages, addShaderCodeCustomVertex);
4714e5c31af7Sopenharmony_ci		testedStageData[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT]	 = StageData(getTessPipelineStages, addShaderCodeCustomTessControl);
4715e5c31af7Sopenharmony_ci		testedStageData[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = StageData(getTessPipelineStages, addShaderCodeCustomTessEval);
4716e5c31af7Sopenharmony_ci		testedStageData[VK_SHADER_STAGE_GEOMETRY_BIT]				 = StageData(getGeomPipelineStages, addShaderCodeCustomGeometry);
4717e5c31af7Sopenharmony_ci		testedStageData[VK_SHADER_STAGE_FRAGMENT_BIT]				 = StageData(getVertFragPipelineStages, addShaderCodeCustomFragment);
4718e5c31af7Sopenharmony_ci	}
4719e5c31af7Sopenharmony_ci
4720e5c31af7Sopenharmony_ci	return testedStageData[stage];
4721e5c31af7Sopenharmony_ci}
4722e5c31af7Sopenharmony_ci
4723e5c31af7Sopenharmony_civoid createTestForStage (vk::VkShaderStageFlagBits	stage,
4724e5c31af7Sopenharmony_ci						 const std::string&			name,
4725e5c31af7Sopenharmony_ci						 const RGBA					(&inputColors)[4],
4726e5c31af7Sopenharmony_ci						 const RGBA					(&outputColors)[4],
4727e5c31af7Sopenharmony_ci						 const map<string, string>&	testCodeFragments,
4728e5c31af7Sopenharmony_ci						 const SpecConstants&		specConstants,
4729e5c31af7Sopenharmony_ci						 const PushConstants&		pushConstants,
4730e5c31af7Sopenharmony_ci						 const GraphicsResources&	resources,
4731e5c31af7Sopenharmony_ci						 const GraphicsInterfaces&	interfaces,
4732e5c31af7Sopenharmony_ci						 const vector<string>&		extensions,
4733e5c31af7Sopenharmony_ci						 VulkanFeatures				vulkanFeatures,
4734e5c31af7Sopenharmony_ci						 tcu::TestCaseGroup*		tests,
4735e5c31af7Sopenharmony_ci						 const qpTestResult			failResult,
4736e5c31af7Sopenharmony_ci						 const string&				failMessageTemplate,
4737e5c31af7Sopenharmony_ci						 const bool					renderFullSquare,
4738e5c31af7Sopenharmony_ci						 const bool					splitRenderArea)
4739e5c31af7Sopenharmony_ci{
4740e5c31af7Sopenharmony_ci	const StageData&				stageData			= getStageData(stage);
4741e5c31af7Sopenharmony_ci	DE_ASSERT(stageData.getPipelineFn || stageData.initProgramsFn);
4742e5c31af7Sopenharmony_ci	const vector<ShaderElement>&	pipeline			= stageData.getPipelineFn();
4743e5c31af7Sopenharmony_ci
4744e5c31af7Sopenharmony_ci	StageToSpecConstantMap			specConstantMap;
4745e5c31af7Sopenharmony_ci	if (!specConstants.empty())
4746e5c31af7Sopenharmony_ci		specConstantMap[stage] = specConstants;
4747e5c31af7Sopenharmony_ci
4748e5c31af7Sopenharmony_ci	InstanceContext					ctx					(inputColors, outputColors, testCodeFragments, specConstantMap, pushConstants, resources, interfaces, extensions, vulkanFeatures, stage);
4749e5c31af7Sopenharmony_ci	ctx.splitRenderArea = splitRenderArea;
4750e5c31af7Sopenharmony_ci	for (size_t i = 0; i < pipeline.size(); ++i)
4751e5c31af7Sopenharmony_ci	{
4752e5c31af7Sopenharmony_ci		ctx.moduleMap[pipeline[i].moduleName].push_back(std::make_pair(pipeline[i].entryName, pipeline[i].stage));
4753e5c31af7Sopenharmony_ci		ctx.requiredStages = static_cast<VkShaderStageFlagBits>(ctx.requiredStages | pipeline[i].stage);
4754e5c31af7Sopenharmony_ci	}
4755e5c31af7Sopenharmony_ci
4756e5c31af7Sopenharmony_ci	ctx.failResult = failResult;
4757e5c31af7Sopenharmony_ci	if (!failMessageTemplate.empty())
4758e5c31af7Sopenharmony_ci		ctx.failMessageTemplate = failMessageTemplate;
4759e5c31af7Sopenharmony_ci
4760e5c31af7Sopenharmony_ci	ctx.renderFullSquare = renderFullSquare;
4761e5c31af7Sopenharmony_ci	ctx.splitRenderArea	= splitRenderArea;
4762e5c31af7Sopenharmony_ci	addFunctionCaseWithPrograms<InstanceContext>(tests, name, stageData.initProgramsFn, runAndVerifyDefaultPipeline, ctx);
4763e5c31af7Sopenharmony_ci}
4764e5c31af7Sopenharmony_ci
4765e5c31af7Sopenharmony_civoid createTestsForAllStages (const std::string&			name,
4766e5c31af7Sopenharmony_ci							  const RGBA					(&inputColors)[4],
4767e5c31af7Sopenharmony_ci							  const RGBA					(&outputColors)[4],
4768e5c31af7Sopenharmony_ci							  const map<string, string>&	testCodeFragments,
4769e5c31af7Sopenharmony_ci							  const SpecConstants&			specConstants,
4770e5c31af7Sopenharmony_ci							  const PushConstants&			pushConstants,
4771e5c31af7Sopenharmony_ci							  const GraphicsResources&		resources,
4772e5c31af7Sopenharmony_ci							  const GraphicsInterfaces&		interfaces,
4773e5c31af7Sopenharmony_ci							  const vector<string>&			extensions,
4774e5c31af7Sopenharmony_ci							  VulkanFeatures				vulkanFeatures,
4775e5c31af7Sopenharmony_ci							  tcu::TestCaseGroup*			tests,
4776e5c31af7Sopenharmony_ci							  const qpTestResult			failResult,
4777e5c31af7Sopenharmony_ci							  const string&					failMessageTemplate,
4778e5c31af7Sopenharmony_ci							  const bool					splitRenderArea)
4779e5c31af7Sopenharmony_ci{
4780e5c31af7Sopenharmony_ci	createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, name + "_vert",
4781e5c31af7Sopenharmony_ci					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4782e5c31af7Sopenharmony_ci					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4783e5c31af7Sopenharmony_ci
4784e5c31af7Sopenharmony_ci	createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, name + "_tessc",
4785e5c31af7Sopenharmony_ci					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4786e5c31af7Sopenharmony_ci					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4787e5c31af7Sopenharmony_ci
4788e5c31af7Sopenharmony_ci	createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, name + "_tesse",
4789e5c31af7Sopenharmony_ci					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4790e5c31af7Sopenharmony_ci					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4791e5c31af7Sopenharmony_ci
4792e5c31af7Sopenharmony_ci	createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, name + "_geom",
4793e5c31af7Sopenharmony_ci					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4794e5c31af7Sopenharmony_ci					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4795e5c31af7Sopenharmony_ci
4796e5c31af7Sopenharmony_ci	createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, name + "_frag",
4797e5c31af7Sopenharmony_ci					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4798e5c31af7Sopenharmony_ci					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate, false, splitRenderArea);
4799e5c31af7Sopenharmony_ci}
4800e5c31af7Sopenharmony_ci
4801e5c31af7Sopenharmony_civoid addTessCtrlTest (tcu::TestCaseGroup* group, const char* name, const map<string, string>& fragments)
4802e5c31af7Sopenharmony_ci{
4803e5c31af7Sopenharmony_ci	RGBA defaultColors[4];
4804e5c31af7Sopenharmony_ci	getDefaultColors(defaultColors);
4805e5c31af7Sopenharmony_ci
4806e5c31af7Sopenharmony_ci	createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, name,
4807e5c31af7Sopenharmony_ci					   defaultColors, defaultColors, fragments, SpecConstants(), PushConstants(), GraphicsResources(),
4808e5c31af7Sopenharmony_ci					   GraphicsInterfaces(), vector<string>(), VulkanFeatures(), group);
4809e5c31af7Sopenharmony_ci}
4810e5c31af7Sopenharmony_ci
4811e5c31af7Sopenharmony_ci} // SpirVAssembly
4812e5c31af7Sopenharmony_ci} // vkt
4813