1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2015 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 ShaderLibrary Vulkan implementation
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "vktShaderLibrary.hpp"
25e5c31af7Sopenharmony_ci#include "vktTestCase.hpp"
26e5c31af7Sopenharmony_ci
27e5c31af7Sopenharmony_ci#include "vkPrograms.hpp"
28e5c31af7Sopenharmony_ci#include "vkRef.hpp"
29e5c31af7Sopenharmony_ci#include "vkRefUtil.hpp"
30e5c31af7Sopenharmony_ci#include "vkMemUtil.hpp"
31e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
32e5c31af7Sopenharmony_ci#include "vkBuilderUtil.hpp"
33e5c31af7Sopenharmony_ci#include "vkTypeUtil.hpp"
34e5c31af7Sopenharmony_ci#include "vkImageUtil.hpp"
35e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp"
36e5c31af7Sopenharmony_ci#include "vkObjUtil.hpp"
37e5c31af7Sopenharmony_ci
38e5c31af7Sopenharmony_ci#include "gluShaderLibrary.hpp"
39e5c31af7Sopenharmony_ci#include "gluShaderUtil.hpp"
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
42e5c31af7Sopenharmony_ci#include "tcuTexture.hpp"
43e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
44e5c31af7Sopenharmony_ci#include "tcuVector.hpp"
45e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp"
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
48e5c31af7Sopenharmony_ci#include "deArrayUtil.hpp"
49e5c31af7Sopenharmony_ci#include "deMemory.h"
50e5c31af7Sopenharmony_ci
51e5c31af7Sopenharmony_ci#include <sstream>
52e5c31af7Sopenharmony_ci#include <map>
53e5c31af7Sopenharmony_ci
54e5c31af7Sopenharmony_cinamespace vkt
55e5c31af7Sopenharmony_ci{
56e5c31af7Sopenharmony_ci
57e5c31af7Sopenharmony_ciusing std::string;
58e5c31af7Sopenharmony_ciusing std::vector;
59e5c31af7Sopenharmony_ciusing std::map;
60e5c31af7Sopenharmony_ciusing std::pair;
61e5c31af7Sopenharmony_ciusing std::ostringstream;
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ciusing de::MovePtr;
64e5c31af7Sopenharmony_ciusing de::UniquePtr;
65e5c31af7Sopenharmony_ci
66e5c31af7Sopenharmony_ciusing glu::ShaderType;
67e5c31af7Sopenharmony_ciusing glu::ProgramSources;
68e5c31af7Sopenharmony_ciusing glu::DataType;
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_ciusing glu::sl::ShaderCaseSpecification;
71e5c31af7Sopenharmony_ciusing glu::sl::ProgramSpecializationParams;
72e5c31af7Sopenharmony_ciusing glu::sl::RequiredExtension;
73e5c31af7Sopenharmony_ciusing glu::sl::Value;
74e5c31af7Sopenharmony_ciusing glu::sl::ValueBlock;
75e5c31af7Sopenharmony_ci
76e5c31af7Sopenharmony_ciusing tcu::TestStatus;
77e5c31af7Sopenharmony_ciusing tcu::StringTemplate;
78e5c31af7Sopenharmony_ciusing tcu::Vec2;
79e5c31af7Sopenharmony_ciusing tcu::ConstPixelBufferAccess;
80e5c31af7Sopenharmony_ciusing tcu::TextureFormat;
81e5c31af7Sopenharmony_ciusing tcu::TestLog;
82e5c31af7Sopenharmony_ci
83e5c31af7Sopenharmony_ciusing vk::SourceCollections;
84e5c31af7Sopenharmony_ciusing vk::Move;
85e5c31af7Sopenharmony_ciusing vk::Unique;
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_cinamespace
88e5c31af7Sopenharmony_ci{
89e5c31af7Sopenharmony_ci
90e5c31af7Sopenharmony_cienum
91e5c31af7Sopenharmony_ci{
92e5c31af7Sopenharmony_ci	REFERENCE_UNIFORM_BINDING	= 0,
93e5c31af7Sopenharmony_ci	USER_UNIFORM_BINDING		= 1
94e5c31af7Sopenharmony_ci};
95e5c31af7Sopenharmony_ci
96e5c31af7Sopenharmony_cistring getShaderName (ShaderType shaderType, size_t progNdx)
97e5c31af7Sopenharmony_ci{
98e5c31af7Sopenharmony_ci	ostringstream str;
99e5c31af7Sopenharmony_ci	str << glu::getShaderTypeName(shaderType);
100e5c31af7Sopenharmony_ci	if (progNdx > 0)
101e5c31af7Sopenharmony_ci		str << "_" << progNdx;
102e5c31af7Sopenharmony_ci	return str.str();
103e5c31af7Sopenharmony_ci}
104e5c31af7Sopenharmony_ci
105e5c31af7Sopenharmony_civoid genUniformBlock (ostringstream& out, const string& blockName, const string& instanceName, int setNdx, int bindingNdx, const vector<Value>& uniforms)
106e5c31af7Sopenharmony_ci{
107e5c31af7Sopenharmony_ci	out << "layout(";
108e5c31af7Sopenharmony_ci
109e5c31af7Sopenharmony_ci	if (setNdx != 0)
110e5c31af7Sopenharmony_ci		out << "set = " << setNdx << ", ";
111e5c31af7Sopenharmony_ci
112e5c31af7Sopenharmony_ci	out << "binding = " << bindingNdx << ", std140) uniform " << blockName << "\n"
113e5c31af7Sopenharmony_ci		<< "{\n";
114e5c31af7Sopenharmony_ci
115e5c31af7Sopenharmony_ci	for (vector<Value>::const_iterator val = uniforms.begin(); val != uniforms.end(); ++val)
116e5c31af7Sopenharmony_ci		out << "\t" << glu::declare(val->type, val->name, 1) << ";\n";
117e5c31af7Sopenharmony_ci
118e5c31af7Sopenharmony_ci	out << "}";
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ci	if (!instanceName.empty())
121e5c31af7Sopenharmony_ci		out << " " << instanceName;
122e5c31af7Sopenharmony_ci
123e5c31af7Sopenharmony_ci	out << ";\n";
124e5c31af7Sopenharmony_ci}
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_civoid declareReferenceBlock (ostringstream& out, const ValueBlock& valueBlock)
127e5c31af7Sopenharmony_ci{
128e5c31af7Sopenharmony_ci	if (!valueBlock.outputs.empty())
129e5c31af7Sopenharmony_ci		genUniformBlock(out, "Reference", "ref", 0, REFERENCE_UNIFORM_BINDING, valueBlock.outputs);
130e5c31af7Sopenharmony_ci}
131e5c31af7Sopenharmony_ci
132e5c31af7Sopenharmony_civoid declareUniforms (ostringstream& out, const ValueBlock& valueBlock)
133e5c31af7Sopenharmony_ci{
134e5c31af7Sopenharmony_ci	if (!valueBlock.uniforms.empty())
135e5c31af7Sopenharmony_ci		genUniformBlock(out, "Uniforms", "", 0, USER_UNIFORM_BINDING, valueBlock.uniforms);
136e5c31af7Sopenharmony_ci}
137e5c31af7Sopenharmony_ci
138e5c31af7Sopenharmony_ciDataType getTransportType (DataType valueType)
139e5c31af7Sopenharmony_ci{
140e5c31af7Sopenharmony_ci	if (isDataTypeBoolOrBVec(valueType))
141e5c31af7Sopenharmony_ci		return glu::getDataTypeUintVec(getDataTypeScalarSize(valueType));
142e5c31af7Sopenharmony_ci	else
143e5c31af7Sopenharmony_ci		return valueType;
144e5c31af7Sopenharmony_ci}
145e5c31af7Sopenharmony_ci
146e5c31af7Sopenharmony_ciint getNumTransportLocations (DataType valueType)
147e5c31af7Sopenharmony_ci{
148e5c31af7Sopenharmony_ci	return isDataTypeMatrix(valueType) ? getDataTypeMatrixNumColumns(valueType) : 1;
149e5c31af7Sopenharmony_ci}
150e5c31af7Sopenharmony_ci
151e5c31af7Sopenharmony_ci// This functions builds a matching vertex shader for a 'both' case, when
152e5c31af7Sopenharmony_ci// the fragment shader is being tested.
153e5c31af7Sopenharmony_ci// We need to build attributes and varyings for each 'input'.
154e5c31af7Sopenharmony_cistring genVertexShader (const ShaderCaseSpecification& spec)
155e5c31af7Sopenharmony_ci{
156e5c31af7Sopenharmony_ci	ostringstream	res;
157e5c31af7Sopenharmony_ci	int				curInputLoc		= 0;
158e5c31af7Sopenharmony_ci	int				curOutputLoc	= 0;
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_ci	res << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
161e5c31af7Sopenharmony_ci
162e5c31af7Sopenharmony_ci	// Declarations (position + attribute/varying for each input).
163e5c31af7Sopenharmony_ci	res << "precision highp float;\n";
164e5c31af7Sopenharmony_ci	res << "precision highp int;\n";
165e5c31af7Sopenharmony_ci	res << "\n";
166e5c31af7Sopenharmony_ci	res << "layout(location = 0) in highp vec4 dEQP_Position;\n";
167e5c31af7Sopenharmony_ci	curInputLoc += 1;
168e5c31af7Sopenharmony_ci
169e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
170e5c31af7Sopenharmony_ci	{
171e5c31af7Sopenharmony_ci		const Value&		val					= spec.values.inputs[ndx];
172e5c31af7Sopenharmony_ci		const DataType		valueType			= val.type.getBasicType();
173e5c31af7Sopenharmony_ci		const DataType		transportType		= getTransportType(valueType);
174e5c31af7Sopenharmony_ci		const char* const	transportTypeStr	= getDataTypeName(transportType);
175e5c31af7Sopenharmony_ci		const int			numLocs				= getNumTransportLocations(valueType);
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_ci		res << "layout(location = " << curInputLoc << ") in " << transportTypeStr << " a_" << val.name << ";\n";
178e5c31af7Sopenharmony_ci		res << "layout(location = " << curOutputLoc << ") flat out " << transportTypeStr << " " << (transportType != valueType ? "v_" : "") << val.name << ";\n";
179e5c31af7Sopenharmony_ci
180e5c31af7Sopenharmony_ci		curInputLoc		+= numLocs;
181e5c31af7Sopenharmony_ci		curOutputLoc	+= numLocs;
182e5c31af7Sopenharmony_ci	}
183e5c31af7Sopenharmony_ci	res << "\n";
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_ci	// Main function.
186e5c31af7Sopenharmony_ci	// - gl_Position = dEQP_Position;
187e5c31af7Sopenharmony_ci	// - for each input: write attribute directly to varying
188e5c31af7Sopenharmony_ci	res << "void main()\n";
189e5c31af7Sopenharmony_ci	res << "{\n";
190e5c31af7Sopenharmony_ci	res << "	gl_Position = dEQP_Position;\n";
191e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
192e5c31af7Sopenharmony_ci	{
193e5c31af7Sopenharmony_ci		const Value&	val		= spec.values.inputs[ndx];
194e5c31af7Sopenharmony_ci		const string&	name	= val.name;
195e5c31af7Sopenharmony_ci
196e5c31af7Sopenharmony_ci		res << "	" << (getTransportType(val.type.getBasicType()) != val.type.getBasicType() ? "v_" : "")
197e5c31af7Sopenharmony_ci			<< name << " = a_" << name << ";\n";
198e5c31af7Sopenharmony_ci	}
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci	res << "}\n";
201e5c31af7Sopenharmony_ci	return res.str();
202e5c31af7Sopenharmony_ci}
203e5c31af7Sopenharmony_ci
204e5c31af7Sopenharmony_civoid genCompareOp (ostringstream& output, const char* dstVec4Var, const ValueBlock& valueBlock, const char* checkVarName)
205e5c31af7Sopenharmony_ci{
206e5c31af7Sopenharmony_ci	bool isFirstOutput = true;
207e5c31af7Sopenharmony_ci
208e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < valueBlock.outputs.size(); ndx++)
209e5c31af7Sopenharmony_ci	{
210e5c31af7Sopenharmony_ci		const Value&	val		= valueBlock.outputs[ndx];
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_ci		// Check if we're only interested in one variable (then skip if not the right one).
213e5c31af7Sopenharmony_ci		if (checkVarName && val.name != checkVarName)
214e5c31af7Sopenharmony_ci			continue;
215e5c31af7Sopenharmony_ci
216e5c31af7Sopenharmony_ci		// Prefix.
217e5c31af7Sopenharmony_ci		if (isFirstOutput)
218e5c31af7Sopenharmony_ci		{
219e5c31af7Sopenharmony_ci			output << "bool RES = ";
220e5c31af7Sopenharmony_ci			isFirstOutput = false;
221e5c31af7Sopenharmony_ci		}
222e5c31af7Sopenharmony_ci		else
223e5c31af7Sopenharmony_ci			output << "RES = RES && ";
224e5c31af7Sopenharmony_ci
225e5c31af7Sopenharmony_ci		// Generate actual comparison.
226e5c31af7Sopenharmony_ci		if (getDataTypeScalarType(val.type.getBasicType()) == glu::TYPE_FLOAT)
227e5c31af7Sopenharmony_ci			output << "isOk(" << val.name << ", ref." << val.name << ", 0.05);\n";
228e5c31af7Sopenharmony_ci		else
229e5c31af7Sopenharmony_ci			output << "isOk(" << val.name << ", ref." << val.name << ");\n";
230e5c31af7Sopenharmony_ci	}
231e5c31af7Sopenharmony_ci
232e5c31af7Sopenharmony_ci	if (isFirstOutput)
233e5c31af7Sopenharmony_ci		output << dstVec4Var << " = vec4(1.0);\n";
234e5c31af7Sopenharmony_ci	else
235e5c31af7Sopenharmony_ci		output << dstVec4Var << " = vec4(RES, RES, RES, 1.0);\n";
236e5c31af7Sopenharmony_ci}
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_cistring genFragmentShader (const ShaderCaseSpecification& spec)
239e5c31af7Sopenharmony_ci{
240e5c31af7Sopenharmony_ci	ostringstream	shader;
241e5c31af7Sopenharmony_ci	ostringstream	setup;
242e5c31af7Sopenharmony_ci	int				curInLoc	= 0;
243e5c31af7Sopenharmony_ci
244e5c31af7Sopenharmony_ci	shader << glu::getGLSLVersionDeclaration(spec.targetVersion) << "\n";
245e5c31af7Sopenharmony_ci
246e5c31af7Sopenharmony_ci	shader << "precision highp float;\n";
247e5c31af7Sopenharmony_ci	shader << "precision highp int;\n";
248e5c31af7Sopenharmony_ci	shader << "\n";
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_ci	shader << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
251e5c31af7Sopenharmony_ci	shader << "\n";
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ci	genCompareFunctions(shader, spec.values, false);
254e5c31af7Sopenharmony_ci	shader << "\n";
255e5c31af7Sopenharmony_ci
256e5c31af7Sopenharmony_ci	// Declarations (varying, reference for each output).
257e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
258e5c31af7Sopenharmony_ci	{
259e5c31af7Sopenharmony_ci		const Value&		val					= spec.values.outputs[ndx];
260e5c31af7Sopenharmony_ci		const DataType		valueType			= val.type.getBasicType();
261e5c31af7Sopenharmony_ci		const char*	const	valueTypeStr		= getDataTypeName(valueType);
262e5c31af7Sopenharmony_ci		const DataType		transportType		= getTransportType(valueType);
263e5c31af7Sopenharmony_ci		const char* const	transportTypeStr	= getDataTypeName(transportType);
264e5c31af7Sopenharmony_ci		const int			numLocs				= getNumTransportLocations(valueType);
265e5c31af7Sopenharmony_ci
266e5c31af7Sopenharmony_ci		shader << "layout(location = " << curInLoc << ") flat in " << transportTypeStr << " " << (valueType != transportType ? "v_" : "") << val.name << ";\n";
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci		if (valueType != transportType)
269e5c31af7Sopenharmony_ci			setup << "	" << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
270e5c31af7Sopenharmony_ci
271e5c31af7Sopenharmony_ci		curInLoc += numLocs;
272e5c31af7Sopenharmony_ci	}
273e5c31af7Sopenharmony_ci
274e5c31af7Sopenharmony_ci	declareReferenceBlock(shader, spec.values);
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_ci	shader << "\n";
277e5c31af7Sopenharmony_ci	shader << "void main()\n";
278e5c31af7Sopenharmony_ci	shader << "{\n";
279e5c31af7Sopenharmony_ci
280e5c31af7Sopenharmony_ci	shader << setup.str();
281e5c31af7Sopenharmony_ci
282e5c31af7Sopenharmony_ci	shader << "	";
283e5c31af7Sopenharmony_ci	genCompareOp(shader, "dEQP_FragColor", spec.values, DE_NULL);
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_ci	shader << "}\n";
286e5c31af7Sopenharmony_ci	return shader.str();
287e5c31af7Sopenharmony_ci}
288e5c31af7Sopenharmony_ci
289e5c31af7Sopenharmony_ci// Specialize a shader for the vertex shader test case.
290e5c31af7Sopenharmony_cistring specializeVertexShader (const ShaderCaseSpecification& spec, const string& src)
291e5c31af7Sopenharmony_ci{
292e5c31af7Sopenharmony_ci	ostringstream		decl;
293e5c31af7Sopenharmony_ci	ostringstream		setup;
294e5c31af7Sopenharmony_ci	ostringstream		output;
295e5c31af7Sopenharmony_ci	int					curInputLoc		= 0;
296e5c31af7Sopenharmony_ci	int					curOutputLoc	= 0;
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_ci	// generated from "both" case
299e5c31af7Sopenharmony_ci	DE_ASSERT(spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY);
300e5c31af7Sopenharmony_ci
301e5c31af7Sopenharmony_ci	// Output (write out position).
302e5c31af7Sopenharmony_ci	output << "gl_Position = dEQP_Position;\n";
303e5c31af7Sopenharmony_ci
304e5c31af7Sopenharmony_ci	// Declarations (position + attribute for each input, varying for each output).
305e5c31af7Sopenharmony_ci	decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
306e5c31af7Sopenharmony_ci	curInputLoc += 1;
307e5c31af7Sopenharmony_ci
308e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
309e5c31af7Sopenharmony_ci	{
310e5c31af7Sopenharmony_ci		const Value&		val					= spec.values.inputs[ndx];
311e5c31af7Sopenharmony_ci		const DataType		valueType			= val.type.getBasicType();
312e5c31af7Sopenharmony_ci		const char*	const	valueTypeStr		= getDataTypeName(valueType);
313e5c31af7Sopenharmony_ci		const DataType		transportType		= getTransportType(valueType);
314e5c31af7Sopenharmony_ci		const char* const	transportTypeStr	= getDataTypeName(transportType);
315e5c31af7Sopenharmony_ci		const int			numLocs				= getNumTransportLocations(valueType);
316e5c31af7Sopenharmony_ci
317e5c31af7Sopenharmony_ci		decl << "layout(location = " << curInputLoc << ") in ";
318e5c31af7Sopenharmony_ci
319e5c31af7Sopenharmony_ci		curInputLoc += numLocs;
320e5c31af7Sopenharmony_ci
321e5c31af7Sopenharmony_ci		if (valueType == transportType)
322e5c31af7Sopenharmony_ci			decl << transportTypeStr << " " << val.name << ";\n";
323e5c31af7Sopenharmony_ci		else
324e5c31af7Sopenharmony_ci		{
325e5c31af7Sopenharmony_ci			decl << transportTypeStr << " a_" << val.name << ";\n";
326e5c31af7Sopenharmony_ci			setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
327e5c31af7Sopenharmony_ci		}
328e5c31af7Sopenharmony_ci	}
329e5c31af7Sopenharmony_ci
330e5c31af7Sopenharmony_ci	declareUniforms(decl, spec.values);
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
333e5c31af7Sopenharmony_ci	{
334e5c31af7Sopenharmony_ci		const Value&		val					= spec.values.outputs[ndx];
335e5c31af7Sopenharmony_ci		const DataType		valueType			= val.type.getBasicType();
336e5c31af7Sopenharmony_ci		const char*	const	valueTypeStr		= getDataTypeName(valueType);
337e5c31af7Sopenharmony_ci		const DataType		transportType		= getTransportType(valueType);
338e5c31af7Sopenharmony_ci		const char* const	transportTypeStr	= getDataTypeName(transportType);
339e5c31af7Sopenharmony_ci		const int			numLocs				= getNumTransportLocations(valueType);
340e5c31af7Sopenharmony_ci
341e5c31af7Sopenharmony_ci		decl << "layout(location = " << curOutputLoc << ") flat out ";
342e5c31af7Sopenharmony_ci
343e5c31af7Sopenharmony_ci		curOutputLoc += numLocs;
344e5c31af7Sopenharmony_ci
345e5c31af7Sopenharmony_ci		if (valueType == transportType)
346e5c31af7Sopenharmony_ci			decl << transportTypeStr << " " << val.name << ";\n";
347e5c31af7Sopenharmony_ci		else
348e5c31af7Sopenharmony_ci		{
349e5c31af7Sopenharmony_ci			decl << transportTypeStr << " v_" << val.name << ";\n";
350e5c31af7Sopenharmony_ci			decl << valueTypeStr << " " << val.name << ";\n";
351e5c31af7Sopenharmony_ci
352e5c31af7Sopenharmony_ci			output << "v_" << val.name << " = " << transportTypeStr << "(" << val.name << ");\n";
353e5c31af7Sopenharmony_ci		}
354e5c31af7Sopenharmony_ci	}
355e5c31af7Sopenharmony_ci
356e5c31af7Sopenharmony_ci	// Shader specialization.
357e5c31af7Sopenharmony_ci	map<string, string> params;
358e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("DECLARATIONS", decl.str()));
359e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("SETUP", setup.str()));
360e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("OUTPUT", output.str()));
361e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("POSITION_FRAG_COLOR", "gl_Position"));
362e5c31af7Sopenharmony_ci
363e5c31af7Sopenharmony_ci	StringTemplate	tmpl	(src);
364e5c31af7Sopenharmony_ci	const string	baseSrc	= tmpl.specialize(params);
365e5c31af7Sopenharmony_ci	const string	withExt	= injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_VERTEX);
366e5c31af7Sopenharmony_ci
367e5c31af7Sopenharmony_ci	return withExt;
368e5c31af7Sopenharmony_ci}
369e5c31af7Sopenharmony_ci
370e5c31af7Sopenharmony_ci// Specialize a shader for the fragment shader test case.
371e5c31af7Sopenharmony_cistring specializeFragmentShader (const ShaderCaseSpecification& spec, const string& src)
372e5c31af7Sopenharmony_ci{
373e5c31af7Sopenharmony_ci	ostringstream		decl;
374e5c31af7Sopenharmony_ci	ostringstream		setup;
375e5c31af7Sopenharmony_ci	ostringstream		output;
376e5c31af7Sopenharmony_ci	int					curInputLoc	= 0;
377e5c31af7Sopenharmony_ci
378e5c31af7Sopenharmony_ci	// generated from "both" case
379e5c31af7Sopenharmony_ci	DE_ASSERT(spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY);
380e5c31af7Sopenharmony_ci
381e5c31af7Sopenharmony_ci	genCompareFunctions(decl, spec.values, false);
382e5c31af7Sopenharmony_ci	genCompareOp(output, "dEQP_FragColor", spec.values, DE_NULL);
383e5c31af7Sopenharmony_ci
384e5c31af7Sopenharmony_ci	decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
385e5c31af7Sopenharmony_ci
386e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < spec.values.inputs.size(); ndx++)
387e5c31af7Sopenharmony_ci	{
388e5c31af7Sopenharmony_ci		const Value&		val					= spec.values.inputs[ndx];
389e5c31af7Sopenharmony_ci		const DataType		valueType			= val.type.getBasicType();
390e5c31af7Sopenharmony_ci		const char*	const	valueTypeStr		= getDataTypeName(valueType);
391e5c31af7Sopenharmony_ci		const DataType		transportType		= getTransportType(valueType);
392e5c31af7Sopenharmony_ci		const char* const	transportTypeStr	= getDataTypeName(transportType);
393e5c31af7Sopenharmony_ci		const int			numLocs				= getNumTransportLocations(valueType);
394e5c31af7Sopenharmony_ci
395e5c31af7Sopenharmony_ci		decl << "layout(location = " << curInputLoc << ") flat in ";
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci		curInputLoc += numLocs;
398e5c31af7Sopenharmony_ci
399e5c31af7Sopenharmony_ci		if (valueType == transportType)
400e5c31af7Sopenharmony_ci			decl << transportTypeStr << " " << val.name << ";\n";
401e5c31af7Sopenharmony_ci		else
402e5c31af7Sopenharmony_ci		{
403e5c31af7Sopenharmony_ci			decl << transportTypeStr << " v_" << val.name << ";\n";
404e5c31af7Sopenharmony_ci			setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(v_" << val.name << ");\n";
405e5c31af7Sopenharmony_ci		}
406e5c31af7Sopenharmony_ci	}
407e5c31af7Sopenharmony_ci
408e5c31af7Sopenharmony_ci	declareUniforms(decl, spec.values);
409e5c31af7Sopenharmony_ci	declareReferenceBlock(decl, spec.values);
410e5c31af7Sopenharmony_ci
411e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < spec.values.outputs.size(); ndx++)
412e5c31af7Sopenharmony_ci	{
413e5c31af7Sopenharmony_ci		const Value&		val				= spec.values.outputs[ndx];
414e5c31af7Sopenharmony_ci		const DataType		basicType		= val.type.getBasicType();
415e5c31af7Sopenharmony_ci		const char* const	refTypeStr		= getDataTypeName(basicType);
416e5c31af7Sopenharmony_ci
417e5c31af7Sopenharmony_ci		decl << refTypeStr << " " << val.name << ";\n";
418e5c31af7Sopenharmony_ci	}
419e5c31af7Sopenharmony_ci
420e5c31af7Sopenharmony_ci	// Shader specialization.
421e5c31af7Sopenharmony_ci	map<string, string> params;
422e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("DECLARATIONS", decl.str()));
423e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("SETUP", setup.str()));
424e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("OUTPUT", output.str()));
425e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("POSITION_FRAG_COLOR", "dEQP_FragColor"));
426e5c31af7Sopenharmony_ci
427e5c31af7Sopenharmony_ci	StringTemplate	tmpl	(src);
428e5c31af7Sopenharmony_ci	const string	baseSrc	= tmpl.specialize(params);
429e5c31af7Sopenharmony_ci	const string	withExt	= injectExtensionRequirements(baseSrc, spec.programs[0].requiredExtensions, glu::SHADERTYPE_FRAGMENT);
430e5c31af7Sopenharmony_ci
431e5c31af7Sopenharmony_ci	return withExt;
432e5c31af7Sopenharmony_ci}
433e5c31af7Sopenharmony_ci
434e5c31af7Sopenharmony_cimap<string, string> generateVertexSpecialization (const ProgramSpecializationParams& specParams)
435e5c31af7Sopenharmony_ci{
436e5c31af7Sopenharmony_ci	ostringstream			decl;
437e5c31af7Sopenharmony_ci	ostringstream			setup;
438e5c31af7Sopenharmony_ci	map<string, string>		params;
439e5c31af7Sopenharmony_ci	int						curInputLoc		= 0;
440e5c31af7Sopenharmony_ci
441e5c31af7Sopenharmony_ci	decl << "layout(location = 0) in highp vec4 dEQP_Position;\n";
442e5c31af7Sopenharmony_ci	curInputLoc += 1;
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < specParams.caseSpec.values.inputs.size(); ndx++)
445e5c31af7Sopenharmony_ci	{
446e5c31af7Sopenharmony_ci		const Value&		val					= specParams.caseSpec.values.inputs[ndx];
447e5c31af7Sopenharmony_ci		const DataType		valueType			= val.type.getBasicType();
448e5c31af7Sopenharmony_ci		const char*	const	valueTypeStr		= getDataTypeName(valueType);
449e5c31af7Sopenharmony_ci		const DataType		transportType		= getTransportType(valueType);
450e5c31af7Sopenharmony_ci		const char* const	transportTypeStr	= getDataTypeName(transportType);
451e5c31af7Sopenharmony_ci		const int			numLocs				= getNumTransportLocations(valueType);
452e5c31af7Sopenharmony_ci
453e5c31af7Sopenharmony_ci		decl << "layout(location = " << curInputLoc << ") in ";
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_ci		curInputLoc += numLocs;
456e5c31af7Sopenharmony_ci
457e5c31af7Sopenharmony_ci		if (valueType == transportType)
458e5c31af7Sopenharmony_ci			decl << transportTypeStr << " " << val.name << ";\n";
459e5c31af7Sopenharmony_ci		else
460e5c31af7Sopenharmony_ci		{
461e5c31af7Sopenharmony_ci			decl << transportTypeStr << " a_" << val.name << ";\n";
462e5c31af7Sopenharmony_ci			setup << valueTypeStr << " " << val.name << " = " << valueTypeStr << "(a_" << val.name << ");\n";
463e5c31af7Sopenharmony_ci		}
464e5c31af7Sopenharmony_ci	}
465e5c31af7Sopenharmony_ci
466e5c31af7Sopenharmony_ci	declareUniforms(decl, specParams.caseSpec.values);
467e5c31af7Sopenharmony_ci
468e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("VERTEX_DECLARATIONS",	decl.str()));
469e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("VERTEX_SETUP",			setup.str()));
470e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("VERTEX_OUTPUT",			string("gl_Position = dEQP_Position;\n")));
471e5c31af7Sopenharmony_ci
472e5c31af7Sopenharmony_ci	return params;
473e5c31af7Sopenharmony_ci}
474e5c31af7Sopenharmony_ci
475e5c31af7Sopenharmony_cimap<string, string> generateFragmentSpecialization (const ProgramSpecializationParams& specParams)
476e5c31af7Sopenharmony_ci{
477e5c31af7Sopenharmony_ci	ostringstream		decl;
478e5c31af7Sopenharmony_ci	ostringstream		output;
479e5c31af7Sopenharmony_ci	map<string, string>	params;
480e5c31af7Sopenharmony_ci
481e5c31af7Sopenharmony_ci	genCompareFunctions(decl, specParams.caseSpec.values, false);
482e5c31af7Sopenharmony_ci	genCompareOp(output, "dEQP_FragColor", specParams.caseSpec.values, DE_NULL);
483e5c31af7Sopenharmony_ci
484e5c31af7Sopenharmony_ci	decl << "layout(location = 0) out mediump vec4 dEQP_FragColor;\n";
485e5c31af7Sopenharmony_ci
486e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < specParams.caseSpec.values.outputs.size(); ndx++)
487e5c31af7Sopenharmony_ci	{
488e5c31af7Sopenharmony_ci		const Value&		val			= specParams.caseSpec.values.outputs[ndx];
489e5c31af7Sopenharmony_ci		const char*	const	refTypeStr	= getDataTypeName(val.type.getBasicType());
490e5c31af7Sopenharmony_ci
491e5c31af7Sopenharmony_ci		decl << refTypeStr << " " << val.name << ";\n";
492e5c31af7Sopenharmony_ci	}
493e5c31af7Sopenharmony_ci
494e5c31af7Sopenharmony_ci	declareReferenceBlock(decl, specParams.caseSpec.values);
495e5c31af7Sopenharmony_ci	declareUniforms(decl, specParams.caseSpec.values);
496e5c31af7Sopenharmony_ci
497e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("FRAGMENT_DECLARATIONS",	decl.str()));
498e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("FRAGMENT_OUTPUT",		output.str()));
499e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("FRAG_COLOR",			"dEQP_FragColor"));
500e5c31af7Sopenharmony_ci
501e5c31af7Sopenharmony_ci	return params;
502e5c31af7Sopenharmony_ci}
503e5c31af7Sopenharmony_ci
504e5c31af7Sopenharmony_cimap<string, string> generateGeometrySpecialization (const ProgramSpecializationParams& specParams)
505e5c31af7Sopenharmony_ci{
506e5c31af7Sopenharmony_ci	ostringstream		decl;
507e5c31af7Sopenharmony_ci	map<string, string>	params;
508e5c31af7Sopenharmony_ci
509e5c31af7Sopenharmony_ci	decl << "layout (triangles) in;\n";
510e5c31af7Sopenharmony_ci	decl << "layout (triangle_strip, max_vertices=3) out;\n";
511e5c31af7Sopenharmony_ci	decl << "\n";
512e5c31af7Sopenharmony_ci
513e5c31af7Sopenharmony_ci	declareUniforms(decl, specParams.caseSpec.values);
514e5c31af7Sopenharmony_ci
515e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("GEOMETRY_DECLARATIONS",		decl.str()));
516e5c31af7Sopenharmony_ci
517e5c31af7Sopenharmony_ci	return params;
518e5c31af7Sopenharmony_ci}
519e5c31af7Sopenharmony_ci
520e5c31af7Sopenharmony_cimap<string, string> generateTessControlSpecialization (const ProgramSpecializationParams& specParams)
521e5c31af7Sopenharmony_ci{
522e5c31af7Sopenharmony_ci	ostringstream		decl;
523e5c31af7Sopenharmony_ci	ostringstream		output;
524e5c31af7Sopenharmony_ci	map<string, string>	params;
525e5c31af7Sopenharmony_ci
526e5c31af7Sopenharmony_ci	decl << "layout (vertices=3) out;\n";
527e5c31af7Sopenharmony_ci	decl << "\n";
528e5c31af7Sopenharmony_ci
529e5c31af7Sopenharmony_ci	declareUniforms(decl, specParams.caseSpec.values);
530e5c31af7Sopenharmony_ci
531e5c31af7Sopenharmony_ci	output <<	"gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
532e5c31af7Sopenharmony_ci				"gl_TessLevelInner[0] = 2.0;\n"
533e5c31af7Sopenharmony_ci				"gl_TessLevelInner[1] = 2.0;\n"
534e5c31af7Sopenharmony_ci				"gl_TessLevelOuter[0] = 2.0;\n"
535e5c31af7Sopenharmony_ci				"gl_TessLevelOuter[1] = 2.0;\n"
536e5c31af7Sopenharmony_ci				"gl_TessLevelOuter[2] = 2.0;\n"
537e5c31af7Sopenharmony_ci				"gl_TessLevelOuter[3] = 2.0;";
538e5c31af7Sopenharmony_ci
539e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("TESSELLATION_CONTROL_DECLARATIONS",	decl.str()));
540e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("TESSELLATION_CONTROL_OUTPUT",		output.str()));
541e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES",				de::toString(specParams.maxPatchVertices)));
542e5c31af7Sopenharmony_ci
543e5c31af7Sopenharmony_ci	return params;
544e5c31af7Sopenharmony_ci}
545e5c31af7Sopenharmony_ci
546e5c31af7Sopenharmony_cimap<string, string> generateTessEvalSpecialization (const ProgramSpecializationParams& specParams)
547e5c31af7Sopenharmony_ci{
548e5c31af7Sopenharmony_ci	ostringstream		decl;
549e5c31af7Sopenharmony_ci	ostringstream		output;
550e5c31af7Sopenharmony_ci	map<string, string>	params;
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_ci	decl << "layout (triangles) in;\n";
553e5c31af7Sopenharmony_ci	decl << "\n";
554e5c31af7Sopenharmony_ci
555e5c31af7Sopenharmony_ci	declareUniforms(decl, specParams.caseSpec.values);
556e5c31af7Sopenharmony_ci
557e5c31af7Sopenharmony_ci	output <<	"gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n";
558e5c31af7Sopenharmony_ci
559e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("TESSELLATION_EVALUATION_DECLARATIONS",	decl.str()));
560e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("TESSELLATION_EVALUATION_OUTPUT",		output.str()));
561e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("GL_MAX_PATCH_VERTICES",					de::toString(specParams.maxPatchVertices)));
562e5c31af7Sopenharmony_ci
563e5c31af7Sopenharmony_ci	return params;
564e5c31af7Sopenharmony_ci}
565e5c31af7Sopenharmony_ci
566e5c31af7Sopenharmony_civoid specializeShaderSources (ProgramSources&						dst,
567e5c31af7Sopenharmony_ci							  const ProgramSources&					src,
568e5c31af7Sopenharmony_ci							  const ProgramSpecializationParams&	specParams,
569e5c31af7Sopenharmony_ci							  glu::ShaderType						shaderType,
570e5c31af7Sopenharmony_ci							  map<string, string>					(*specializationGenerator) (const ProgramSpecializationParams& specParams))
571e5c31af7Sopenharmony_ci{
572e5c31af7Sopenharmony_ci	if (!src.sources[shaderType].empty())
573e5c31af7Sopenharmony_ci	{
574e5c31af7Sopenharmony_ci		const map<string, string>	tmplParams	= specializationGenerator(specParams);
575e5c31af7Sopenharmony_ci
576e5c31af7Sopenharmony_ci		for (size_t ndx = 0; ndx < src.sources[shaderType].size(); ++ndx)
577e5c31af7Sopenharmony_ci		{
578e5c31af7Sopenharmony_ci			const StringTemplate	tmpl			(src.sources[shaderType][ndx]);
579e5c31af7Sopenharmony_ci			const string			baseGLSLCode	= tmpl.specialize(tmplParams);
580e5c31af7Sopenharmony_ci			const string			sourceWithExts	= injectExtensionRequirements(baseGLSLCode, specParams.requiredExtensions, shaderType);
581e5c31af7Sopenharmony_ci
582e5c31af7Sopenharmony_ci			dst << glu::ShaderSource(shaderType, sourceWithExts);
583e5c31af7Sopenharmony_ci		}
584e5c31af7Sopenharmony_ci	}
585e5c31af7Sopenharmony_ci}
586e5c31af7Sopenharmony_ci
587e5c31af7Sopenharmony_civoid specializeProgramSources (glu::ProgramSources&					dst,
588e5c31af7Sopenharmony_ci							   const glu::ProgramSources&			src,
589e5c31af7Sopenharmony_ci							   const ProgramSpecializationParams&	specParams)
590e5c31af7Sopenharmony_ci{
591e5c31af7Sopenharmony_ci	specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_VERTEX,					generateVertexSpecialization);
592e5c31af7Sopenharmony_ci	specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_FRAGMENT,					generateFragmentSpecialization);
593e5c31af7Sopenharmony_ci	specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_GEOMETRY,					generateGeometrySpecialization);
594e5c31af7Sopenharmony_ci	specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_CONTROL,		generateTessControlSpecialization);
595e5c31af7Sopenharmony_ci	specializeShaderSources(dst, src, specParams, glu::SHADERTYPE_TESSELLATION_EVALUATION,	generateTessEvalSpecialization);
596e5c31af7Sopenharmony_ci
597e5c31af7Sopenharmony_ci	dst << glu::ProgramSeparable(src.separable);
598e5c31af7Sopenharmony_ci}
599e5c31af7Sopenharmony_ci
600e5c31af7Sopenharmony_cistruct ValueBufferLayout
601e5c31af7Sopenharmony_ci{
602e5c31af7Sopenharmony_ci	struct Entry
603e5c31af7Sopenharmony_ci	{
604e5c31af7Sopenharmony_ci		int		offset;
605e5c31af7Sopenharmony_ci		int		vecStride;	//! Applies to matrices only
606e5c31af7Sopenharmony_ci
607e5c31af7Sopenharmony_ci		Entry (void) : offset(0), vecStride(0) {}
608e5c31af7Sopenharmony_ci		Entry (int offset_, int vecStride_) : offset(offset_), vecStride(vecStride_) {}
609e5c31af7Sopenharmony_ci	};
610e5c31af7Sopenharmony_ci
611e5c31af7Sopenharmony_ci	vector<Entry>	entries;
612e5c31af7Sopenharmony_ci	int				size;
613e5c31af7Sopenharmony_ci
614e5c31af7Sopenharmony_ci	ValueBufferLayout (void) : size(0) {}
615e5c31af7Sopenharmony_ci};
616e5c31af7Sopenharmony_ci
617e5c31af7Sopenharmony_ciValueBufferLayout computeStd140Layout (const vector<Value>& values)
618e5c31af7Sopenharmony_ci{
619e5c31af7Sopenharmony_ci	ValueBufferLayout layout;
620e5c31af7Sopenharmony_ci
621e5c31af7Sopenharmony_ci	layout.entries.resize(values.size());
622e5c31af7Sopenharmony_ci
623e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < values.size(); ++ndx)
624e5c31af7Sopenharmony_ci	{
625e5c31af7Sopenharmony_ci		const DataType	basicType	= values[ndx].type.getBasicType();
626e5c31af7Sopenharmony_ci		const bool		isMatrix	= isDataTypeMatrix(basicType);
627e5c31af7Sopenharmony_ci		const int		numVecs		= isMatrix ? getDataTypeMatrixNumColumns(basicType) : 1;
628e5c31af7Sopenharmony_ci		const DataType	vecType		= isMatrix ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
629e5c31af7Sopenharmony_ci		const int		vecSize		= getDataTypeScalarSize(vecType);
630e5c31af7Sopenharmony_ci		const int		alignment	= ((isMatrix || vecSize == 3) ? 4 : vecSize)*int(sizeof(deUint32));
631e5c31af7Sopenharmony_ci
632e5c31af7Sopenharmony_ci		layout.size			= deAlign32(layout.size, alignment);
633e5c31af7Sopenharmony_ci		layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
634e5c31af7Sopenharmony_ci		layout.size			+= alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
635e5c31af7Sopenharmony_ci	}
636e5c31af7Sopenharmony_ci
637e5c31af7Sopenharmony_ci	return layout;
638e5c31af7Sopenharmony_ci}
639e5c31af7Sopenharmony_ci
640e5c31af7Sopenharmony_ciValueBufferLayout computeStd430Layout (const vector<Value>& values)
641e5c31af7Sopenharmony_ci{
642e5c31af7Sopenharmony_ci	ValueBufferLayout layout;
643e5c31af7Sopenharmony_ci
644e5c31af7Sopenharmony_ci	layout.entries.resize(values.size());
645e5c31af7Sopenharmony_ci
646e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < values.size(); ++ndx)
647e5c31af7Sopenharmony_ci	{
648e5c31af7Sopenharmony_ci		const DataType	basicType	= values[ndx].type.getBasicType();
649e5c31af7Sopenharmony_ci		const int		numVecs		= isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
650e5c31af7Sopenharmony_ci		const DataType	vecType		= isDataTypeMatrix(basicType) ? glu::getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType)) : basicType;
651e5c31af7Sopenharmony_ci		const int		vecSize		= getDataTypeScalarSize(vecType);
652e5c31af7Sopenharmony_ci		const int		alignment	= (vecSize == 3 ? 4 : vecSize)*int(sizeof(deUint32));
653e5c31af7Sopenharmony_ci
654e5c31af7Sopenharmony_ci		layout.size			= deAlign32(layout.size, alignment);
655e5c31af7Sopenharmony_ci		layout.entries[ndx] = ValueBufferLayout::Entry(layout.size, alignment);
656e5c31af7Sopenharmony_ci		layout.size			+= alignment*(numVecs-1) + vecSize*int(sizeof(deUint32));
657e5c31af7Sopenharmony_ci	}
658e5c31af7Sopenharmony_ci
659e5c31af7Sopenharmony_ci	return layout;
660e5c31af7Sopenharmony_ci}
661e5c31af7Sopenharmony_ci
662e5c31af7Sopenharmony_civoid copyToLayout (void* dst, const ValueBufferLayout::Entry& entryLayout, const Value& value, int arrayNdx)
663e5c31af7Sopenharmony_ci{
664e5c31af7Sopenharmony_ci	const DataType	basicType	= value.type.getBasicType();
665e5c31af7Sopenharmony_ci	const int		scalarSize	= getDataTypeScalarSize(basicType);
666e5c31af7Sopenharmony_ci	const int		numVecs		= isDataTypeMatrix(basicType) ? getDataTypeMatrixNumColumns(basicType) : 1;
667e5c31af7Sopenharmony_ci	const int		numComps	= isDataTypeMatrix(basicType) ? getDataTypeMatrixNumRows(basicType) : scalarSize;
668e5c31af7Sopenharmony_ci
669e5c31af7Sopenharmony_ci	DE_ASSERT(size_t((arrayNdx+1)*scalarSize) <= value.elements.size());
670e5c31af7Sopenharmony_ci
671e5c31af7Sopenharmony_ci	if (isDataTypeBoolOrBVec(basicType))
672e5c31af7Sopenharmony_ci	{
673e5c31af7Sopenharmony_ci		for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
674e5c31af7Sopenharmony_ci		{
675e5c31af7Sopenharmony_ci			for (int compNdx = 0; compNdx < numComps; compNdx++)
676e5c31af7Sopenharmony_ci			{
677e5c31af7Sopenharmony_ci				const deUint32 data = value.elements[arrayNdx*scalarSize + vecNdx*numComps + compNdx].bool32 ? ~0u : 0u;
678e5c31af7Sopenharmony_ci
679e5c31af7Sopenharmony_ci				deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride + compNdx * sizeof(deUint32),
680e5c31af7Sopenharmony_ci						 &data,
681e5c31af7Sopenharmony_ci						 sizeof(deUint32));
682e5c31af7Sopenharmony_ci			}
683e5c31af7Sopenharmony_ci		}
684e5c31af7Sopenharmony_ci	}
685e5c31af7Sopenharmony_ci	else
686e5c31af7Sopenharmony_ci	{
687e5c31af7Sopenharmony_ci		for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
688e5c31af7Sopenharmony_ci			deMemcpy((deUint8*)dst + entryLayout.offset + vecNdx*entryLayout.vecStride,
689e5c31af7Sopenharmony_ci					 &value.elements[arrayNdx*scalarSize + vecNdx*numComps],
690e5c31af7Sopenharmony_ci					 numComps*sizeof(deUint32));
691e5c31af7Sopenharmony_ci	}
692e5c31af7Sopenharmony_ci}
693e5c31af7Sopenharmony_ci
694e5c31af7Sopenharmony_civoid copyToLayout (void* dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
695e5c31af7Sopenharmony_ci{
696e5c31af7Sopenharmony_ci	DE_ASSERT(layout.entries.size() == values.size());
697e5c31af7Sopenharmony_ci
698e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < values.size(); ndx++)
699e5c31af7Sopenharmony_ci		copyToLayout(dst, layout.entries[ndx], values[ndx], arrayNdx);
700e5c31af7Sopenharmony_ci}
701e5c31af7Sopenharmony_ci
702e5c31af7Sopenharmony_cideUint32 getShaderStages (const ShaderCaseSpecification& spec)
703e5c31af7Sopenharmony_ci{
704e5c31af7Sopenharmony_ci	if (spec.caseType == glu::sl::CASETYPE_COMPLETE)
705e5c31af7Sopenharmony_ci	{
706e5c31af7Sopenharmony_ci		deUint32	stages	= 0u;
707e5c31af7Sopenharmony_ci
708e5c31af7Sopenharmony_ci		for (size_t progNdx = 0; progNdx < spec.programs.size(); progNdx++)
709e5c31af7Sopenharmony_ci		{
710e5c31af7Sopenharmony_ci			for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
711e5c31af7Sopenharmony_ci			{
712e5c31af7Sopenharmony_ci				if (!spec.programs[progNdx].sources.sources[shaderType].empty())
713e5c31af7Sopenharmony_ci					stages |= (1u << shaderType);
714e5c31af7Sopenharmony_ci			}
715e5c31af7Sopenharmony_ci		}
716e5c31af7Sopenharmony_ci
717e5c31af7Sopenharmony_ci		return stages;
718e5c31af7Sopenharmony_ci	}
719e5c31af7Sopenharmony_ci	else
720e5c31af7Sopenharmony_ci		return (1u << glu::SHADERTYPE_VERTEX) | (1u << glu::SHADERTYPE_FRAGMENT);
721e5c31af7Sopenharmony_ci}
722e5c31af7Sopenharmony_ci
723e5c31af7Sopenharmony_ciclass PipelineProgram
724e5c31af7Sopenharmony_ci{
725e5c31af7Sopenharmony_cipublic:
726e5c31af7Sopenharmony_ci								PipelineProgram		(Context& context, const ShaderCaseSpecification& spec);
727e5c31af7Sopenharmony_ci
728e5c31af7Sopenharmony_ci	deUint32					getStages			(void) const					{ return m_stages;							}
729e5c31af7Sopenharmony_ci
730e5c31af7Sopenharmony_ci	bool						hasShader			(glu::ShaderType type) const	{ return (m_stages & (1u << type)) != 0;	}
731e5c31af7Sopenharmony_ci	vk::VkShaderModule			getShader			(glu::ShaderType type) const	{ return *m_shaderModules[type];			}
732e5c31af7Sopenharmony_ci
733e5c31af7Sopenharmony_ciprivate:
734e5c31af7Sopenharmony_ci	const deUint32				m_stages;
735e5c31af7Sopenharmony_ci	Move<vk::VkShaderModule>	m_shaderModules[glu::SHADERTYPE_LAST];
736e5c31af7Sopenharmony_ci};
737e5c31af7Sopenharmony_ci
738e5c31af7Sopenharmony_ciPipelineProgram::PipelineProgram (Context& context, const ShaderCaseSpecification& spec)
739e5c31af7Sopenharmony_ci	: m_stages(getShaderStages(spec))
740e5c31af7Sopenharmony_ci{
741e5c31af7Sopenharmony_ci	// \note Currently only a single source program is supported as framework lacks SPIR-V linking capability
742e5c31af7Sopenharmony_ci	TCU_CHECK_INTERNAL(spec.programs.size() == 1);
743e5c31af7Sopenharmony_ci
744e5c31af7Sopenharmony_ci	for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
745e5c31af7Sopenharmony_ci	{
746e5c31af7Sopenharmony_ci		if ((m_stages & (1u << shaderType)) != 0)
747e5c31af7Sopenharmony_ci		{
748e5c31af7Sopenharmony_ci			m_shaderModules[shaderType]	= vk::createShaderModule(context.getDeviceInterface(), context.getDevice(),
749e5c31af7Sopenharmony_ci																 context.getBinaryCollection().get(getShaderName((glu::ShaderType)shaderType, 0)), 0u);
750e5c31af7Sopenharmony_ci		}
751e5c31af7Sopenharmony_ci	}
752e5c31af7Sopenharmony_ci}
753e5c31af7Sopenharmony_ci
754e5c31af7Sopenharmony_ciMove<vk::VkBuffer> createBuffer (Context& context, vk::VkDeviceSize size, vk::VkBufferUsageFlags usageFlags)
755e5c31af7Sopenharmony_ci{
756e5c31af7Sopenharmony_ci	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
757e5c31af7Sopenharmony_ci	const vk::VkBufferCreateInfo	params				=
758e5c31af7Sopenharmony_ci	{
759e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// sType
760e5c31af7Sopenharmony_ci		DE_NULL,									// pNext
761e5c31af7Sopenharmony_ci		0u,											// flags
762e5c31af7Sopenharmony_ci		size,										// size
763e5c31af7Sopenharmony_ci		usageFlags,									// usage
764e5c31af7Sopenharmony_ci		vk::VK_SHARING_MODE_EXCLUSIVE,				// sharingMode
765e5c31af7Sopenharmony_ci		1u,											// queueFamilyCount
766e5c31af7Sopenharmony_ci		&queueFamilyIndex,							// pQueueFamilyIndices
767e5c31af7Sopenharmony_ci	};
768e5c31af7Sopenharmony_ci
769e5c31af7Sopenharmony_ci	return vk::createBuffer(context.getDeviceInterface(), context.getDevice(), &params);
770e5c31af7Sopenharmony_ci}
771e5c31af7Sopenharmony_ci
772e5c31af7Sopenharmony_ciMove<vk::VkImage> createImage2D (Context& context, deUint32 width, deUint32 height, vk::VkFormat format, vk::VkImageTiling tiling, vk::VkImageUsageFlags usageFlags)
773e5c31af7Sopenharmony_ci{
774e5c31af7Sopenharmony_ci	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
775e5c31af7Sopenharmony_ci	const vk::VkImageCreateInfo		params				=
776e5c31af7Sopenharmony_ci	{
777e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// sType
778e5c31af7Sopenharmony_ci		DE_NULL,									// pNext
779e5c31af7Sopenharmony_ci		0u,											// flags
780e5c31af7Sopenharmony_ci		vk::VK_IMAGE_TYPE_2D,						// imageType
781e5c31af7Sopenharmony_ci		format,										// format
782e5c31af7Sopenharmony_ci		{ width, height, 1u },						// extent
783e5c31af7Sopenharmony_ci		1u,											// mipLevels
784e5c31af7Sopenharmony_ci		1u,											// arraySize
785e5c31af7Sopenharmony_ci		vk::VK_SAMPLE_COUNT_1_BIT,					// samples
786e5c31af7Sopenharmony_ci		tiling,										// tiling
787e5c31af7Sopenharmony_ci		usageFlags,									// usage
788e5c31af7Sopenharmony_ci		vk::VK_SHARING_MODE_EXCLUSIVE,				// sharingMode
789e5c31af7Sopenharmony_ci		1u,											// queueFamilyCount
790e5c31af7Sopenharmony_ci		&queueFamilyIndex,							// pQueueFamilyIndices
791e5c31af7Sopenharmony_ci		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// initialLayout
792e5c31af7Sopenharmony_ci	};
793e5c31af7Sopenharmony_ci
794e5c31af7Sopenharmony_ci	return vk::createImage(context.getDeviceInterface(), context.getDevice(), &params);
795e5c31af7Sopenharmony_ci}
796e5c31af7Sopenharmony_ci
797e5c31af7Sopenharmony_ciMove<vk::VkImageView> createAttachmentView (Context& context, vk::VkImage image, vk::VkFormat format)
798e5c31af7Sopenharmony_ci{
799e5c31af7Sopenharmony_ci	const vk::VkImageViewCreateInfo	params				=
800e5c31af7Sopenharmony_ci	{
801e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// sType
802e5c31af7Sopenharmony_ci		DE_NULL,											// pNext
803e5c31af7Sopenharmony_ci		0u,													// flags
804e5c31af7Sopenharmony_ci		image,												// image
805e5c31af7Sopenharmony_ci		vk::VK_IMAGE_VIEW_TYPE_2D,							// viewType
806e5c31af7Sopenharmony_ci		format,												// format
807e5c31af7Sopenharmony_ci		vk::makeComponentMappingRGBA(),						// channels
808e5c31af7Sopenharmony_ci		{
809e5c31af7Sopenharmony_ci			vk::VK_IMAGE_ASPECT_COLOR_BIT,						// aspectMask
810e5c31af7Sopenharmony_ci			0u,													// baseMipLevel
811e5c31af7Sopenharmony_ci			1u,													// mipLevels
812e5c31af7Sopenharmony_ci			0u,													// baseArrayLayer
813e5c31af7Sopenharmony_ci			1u,													// arraySize
814e5c31af7Sopenharmony_ci		},													// subresourceRange
815e5c31af7Sopenharmony_ci	};
816e5c31af7Sopenharmony_ci
817e5c31af7Sopenharmony_ci	return vk::createImageView(context.getDeviceInterface(), context.getDevice(), &params);
818e5c31af7Sopenharmony_ci}
819e5c31af7Sopenharmony_ci
820e5c31af7Sopenharmony_ciMove<vk::VkRenderPass> createRenderPass (Context& context, vk::VkFormat colorAttFormat, deUint32 size)
821e5c31af7Sopenharmony_ci{
822e5c31af7Sopenharmony_ci	vk::VkAttachmentDescription	colorAttDesc[4];
823e5c31af7Sopenharmony_ci	vk::VkAttachmentReference	colorAttRef[4];
824e5c31af7Sopenharmony_ci
825e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < size; i++)
826e5c31af7Sopenharmony_ci	{
827e5c31af7Sopenharmony_ci		vk::VkAttachmentDescription	desc =
828e5c31af7Sopenharmony_ci		{
829e5c31af7Sopenharmony_ci			0u,														// flags
830e5c31af7Sopenharmony_ci			colorAttFormat,											// format
831e5c31af7Sopenharmony_ci			vk::VK_SAMPLE_COUNT_1_BIT,								// samples
832e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_LOAD_OP_CLEAR,						// loadOp
833e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_STORE_OP_STORE,						// storeOp
834e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// stencilLoadOp
835e5c31af7Sopenharmony_ci			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,					// stencilStoreOp
836e5c31af7Sopenharmony_ci			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// initialLayout
837e5c31af7Sopenharmony_ci			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// finalLayout
838e5c31af7Sopenharmony_ci		};
839e5c31af7Sopenharmony_ci		colorAttDesc[i] = desc;
840e5c31af7Sopenharmony_ci
841e5c31af7Sopenharmony_ci		vk::VkAttachmentReference	ref =
842e5c31af7Sopenharmony_ci		{
843e5c31af7Sopenharmony_ci			i,														// attachment
844e5c31af7Sopenharmony_ci			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// layout
845e5c31af7Sopenharmony_ci		};
846e5c31af7Sopenharmony_ci		colorAttRef[i] = ref;
847e5c31af7Sopenharmony_ci	}
848e5c31af7Sopenharmony_ci
849e5c31af7Sopenharmony_ci	const vk::VkAttachmentReference		dsAttRef			=
850e5c31af7Sopenharmony_ci	{
851e5c31af7Sopenharmony_ci		VK_ATTACHMENT_UNUSED,									// attachment
852e5c31af7Sopenharmony_ci		vk::VK_IMAGE_LAYOUT_GENERAL,							// layout
853e5c31af7Sopenharmony_ci	};
854e5c31af7Sopenharmony_ci	const vk::VkSubpassDescription		subpassDesc			=
855e5c31af7Sopenharmony_ci	{
856e5c31af7Sopenharmony_ci		(vk::VkSubpassDescriptionFlags)0,
857e5c31af7Sopenharmony_ci		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,					// pipelineBindPoint
858e5c31af7Sopenharmony_ci		0u,														// inputCount
859e5c31af7Sopenharmony_ci		DE_NULL,												// pInputAttachments
860e5c31af7Sopenharmony_ci		size,													// colorCount
861e5c31af7Sopenharmony_ci		&colorAttRef[0],										// pColorAttachments
862e5c31af7Sopenharmony_ci		DE_NULL,												// pResolveAttachments
863e5c31af7Sopenharmony_ci		&dsAttRef,												// depthStencilAttachment
864e5c31af7Sopenharmony_ci		0u,														// preserveCount
865e5c31af7Sopenharmony_ci		DE_NULL,												// pPreserveAttachments
866e5c31af7Sopenharmony_ci
867e5c31af7Sopenharmony_ci	};
868e5c31af7Sopenharmony_ci	const vk::VkRenderPassCreateInfo	renderPassParams	=
869e5c31af7Sopenharmony_ci	{
870e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// sType
871e5c31af7Sopenharmony_ci		DE_NULL,												// pNext
872e5c31af7Sopenharmony_ci		(vk::VkRenderPassCreateFlags)0,
873e5c31af7Sopenharmony_ci		size,													// attachmentCount
874e5c31af7Sopenharmony_ci		&colorAttDesc[0],										// pAttachments
875e5c31af7Sopenharmony_ci		1u,														// subpassCount
876e5c31af7Sopenharmony_ci		&subpassDesc,											// pSubpasses
877e5c31af7Sopenharmony_ci		0u,														// dependencyCount
878e5c31af7Sopenharmony_ci		DE_NULL,												// pDependencies
879e5c31af7Sopenharmony_ci	};
880e5c31af7Sopenharmony_ci
881e5c31af7Sopenharmony_ci	return vk::createRenderPass(context.getDeviceInterface(), context.getDevice(), &renderPassParams);
882e5c31af7Sopenharmony_ci}
883e5c31af7Sopenharmony_ci
884e5c31af7Sopenharmony_civk::VkShaderStageFlags getVkStageFlags (deUint32 stages)
885e5c31af7Sopenharmony_ci{
886e5c31af7Sopenharmony_ci	vk::VkShaderStageFlags	vkStages	= 0u;
887e5c31af7Sopenharmony_ci
888e5c31af7Sopenharmony_ci	for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
889e5c31af7Sopenharmony_ci	{
890e5c31af7Sopenharmony_ci		if ((stages & (1u << shaderType)) != 0)
891e5c31af7Sopenharmony_ci			vkStages |= vk::getVkShaderStage((glu::ShaderType)shaderType);
892e5c31af7Sopenharmony_ci	}
893e5c31af7Sopenharmony_ci
894e5c31af7Sopenharmony_ci	return vkStages;
895e5c31af7Sopenharmony_ci}
896e5c31af7Sopenharmony_ci
897e5c31af7Sopenharmony_ciMove<vk::VkDescriptorSetLayout> createDescriptorSetLayout (Context& context, deUint32 shaderStages)
898e5c31af7Sopenharmony_ci{
899e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(REFERENCE_UNIFORM_BINDING	== 0);
900e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(USER_UNIFORM_BINDING		== 1);
901e5c31af7Sopenharmony_ci
902e5c31af7Sopenharmony_ci	return vk::DescriptorSetLayoutBuilder()
903e5c31af7Sopenharmony_ci				.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT)
904e5c31af7Sopenharmony_ci				.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, getVkStageFlags(shaderStages))
905e5c31af7Sopenharmony_ci				.build(context.getDeviceInterface(), context.getDevice());
906e5c31af7Sopenharmony_ci}
907e5c31af7Sopenharmony_ci
908e5c31af7Sopenharmony_ciMove<vk::VkPipelineLayout> createPipelineLayout (Context& context, vk::VkDescriptorSetLayout descriptorSetLayout)
909e5c31af7Sopenharmony_ci{
910e5c31af7Sopenharmony_ci	const vk::VkPipelineLayoutCreateInfo	params	=
911e5c31af7Sopenharmony_ci	{
912e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// sType
913e5c31af7Sopenharmony_ci		DE_NULL,											// pNext
914e5c31af7Sopenharmony_ci		(vk::VkPipelineLayoutCreateFlags)0,
915e5c31af7Sopenharmony_ci		1u,													// descriptorSetCount
916e5c31af7Sopenharmony_ci		&descriptorSetLayout,								// pSetLayouts
917e5c31af7Sopenharmony_ci		0u,													// pushConstantRangeCount
918e5c31af7Sopenharmony_ci		DE_NULL,											// pPushConstantRanges
919e5c31af7Sopenharmony_ci	};
920e5c31af7Sopenharmony_ci
921e5c31af7Sopenharmony_ci	return vk::createPipelineLayout(context.getDeviceInterface(), context.getDevice(), &params);
922e5c31af7Sopenharmony_ci}
923e5c31af7Sopenharmony_ci
924e5c31af7Sopenharmony_civk::VkFormat getVecFormat (DataType scalarType, int scalarSize)
925e5c31af7Sopenharmony_ci{
926e5c31af7Sopenharmony_ci	switch (scalarType)
927e5c31af7Sopenharmony_ci	{
928e5c31af7Sopenharmony_ci		case glu::TYPE_FLOAT:
929e5c31af7Sopenharmony_ci		{
930e5c31af7Sopenharmony_ci			const vk::VkFormat vecFmts[] =
931e5c31af7Sopenharmony_ci			{
932e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32_SFLOAT,
933e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32_SFLOAT,
934e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32B32_SFLOAT,
935e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32B32A32_SFLOAT,
936e5c31af7Sopenharmony_ci			};
937e5c31af7Sopenharmony_ci			return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
938e5c31af7Sopenharmony_ci		}
939e5c31af7Sopenharmony_ci
940e5c31af7Sopenharmony_ci		case glu::TYPE_INT:
941e5c31af7Sopenharmony_ci		{
942e5c31af7Sopenharmony_ci			const vk::VkFormat vecFmts[] =
943e5c31af7Sopenharmony_ci			{
944e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32_SINT,
945e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32_SINT,
946e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32B32_SINT,
947e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32B32A32_SINT,
948e5c31af7Sopenharmony_ci			};
949e5c31af7Sopenharmony_ci			return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
950e5c31af7Sopenharmony_ci		}
951e5c31af7Sopenharmony_ci
952e5c31af7Sopenharmony_ci		case glu::TYPE_UINT:
953e5c31af7Sopenharmony_ci		{
954e5c31af7Sopenharmony_ci			const vk::VkFormat vecFmts[] =
955e5c31af7Sopenharmony_ci			{
956e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32_UINT,
957e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32_UINT,
958e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32B32_UINT,
959e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32B32A32_UINT,
960e5c31af7Sopenharmony_ci			};
961e5c31af7Sopenharmony_ci			return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
962e5c31af7Sopenharmony_ci		}
963e5c31af7Sopenharmony_ci
964e5c31af7Sopenharmony_ci		case glu::TYPE_BOOL:
965e5c31af7Sopenharmony_ci		{
966e5c31af7Sopenharmony_ci			const vk::VkFormat vecFmts[] =
967e5c31af7Sopenharmony_ci			{
968e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32_UINT,
969e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32_UINT,
970e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32B32_UINT,
971e5c31af7Sopenharmony_ci				vk::VK_FORMAT_R32G32B32A32_UINT,
972e5c31af7Sopenharmony_ci			};
973e5c31af7Sopenharmony_ci			return de::getSizedArrayElement<4>(vecFmts, scalarSize-1);
974e5c31af7Sopenharmony_ci		}
975e5c31af7Sopenharmony_ci
976e5c31af7Sopenharmony_ci		default:
977e5c31af7Sopenharmony_ci			DE_FATAL("Unknown scalar type");
978e5c31af7Sopenharmony_ci			return vk::VK_FORMAT_R8G8B8A8_UINT;
979e5c31af7Sopenharmony_ci	}
980e5c31af7Sopenharmony_ci}
981e5c31af7Sopenharmony_ci
982e5c31af7Sopenharmony_civector<vk::VkVertexInputAttributeDescription> getVertexAttributeDescriptions (const vector<Value>& inputValues, const ValueBufferLayout& layout)
983e5c31af7Sopenharmony_ci{
984e5c31af7Sopenharmony_ci	vector<vk::VkVertexInputAttributeDescription>	attribs;
985e5c31af7Sopenharmony_ci
986e5c31af7Sopenharmony_ci	// Position
987e5c31af7Sopenharmony_ci	{
988e5c31af7Sopenharmony_ci		const vk::VkVertexInputAttributeDescription	posDesc	=
989e5c31af7Sopenharmony_ci		{
990e5c31af7Sopenharmony_ci			0u,								// location
991e5c31af7Sopenharmony_ci			0u,								// binding
992e5c31af7Sopenharmony_ci			vk::VK_FORMAT_R32G32_SFLOAT,	// format
993e5c31af7Sopenharmony_ci			0u,								// offset
994e5c31af7Sopenharmony_ci		};
995e5c31af7Sopenharmony_ci
996e5c31af7Sopenharmony_ci		attribs.push_back(posDesc);
997e5c31af7Sopenharmony_ci	}
998e5c31af7Sopenharmony_ci
999e5c31af7Sopenharmony_ci	// Input values
1000e5c31af7Sopenharmony_ci	for (size_t inputNdx = 0; inputNdx < inputValues.size(); inputNdx++)
1001e5c31af7Sopenharmony_ci	{
1002e5c31af7Sopenharmony_ci		const Value&					input		= inputValues[inputNdx];
1003e5c31af7Sopenharmony_ci		const ValueBufferLayout::Entry&	layoutEntry	= layout.entries[inputNdx];
1004e5c31af7Sopenharmony_ci		const DataType					basicType	= input.type.getBasicType();
1005e5c31af7Sopenharmony_ci		const int						numVecs		= isDataTypeMatrix(basicType)
1006e5c31af7Sopenharmony_ci													? getDataTypeMatrixNumColumns(basicType)
1007e5c31af7Sopenharmony_ci													: 1;
1008e5c31af7Sopenharmony_ci		const int						vecSize		= isDataTypeMatrix(basicType)
1009e5c31af7Sopenharmony_ci													? getDataTypeMatrixNumRows(basicType)
1010e5c31af7Sopenharmony_ci													: getDataTypeScalarSize(basicType);
1011e5c31af7Sopenharmony_ci		const DataType					scalarType	= getDataTypeScalarType(basicType);
1012e5c31af7Sopenharmony_ci		const vk::VkFormat				vecFmt		= getVecFormat(scalarType, vecSize);
1013e5c31af7Sopenharmony_ci
1014e5c31af7Sopenharmony_ci		for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
1015e5c31af7Sopenharmony_ci		{
1016e5c31af7Sopenharmony_ci			const deUint32								curLoc	= (deUint32)attribs.size();
1017e5c31af7Sopenharmony_ci			const deUint32								offset	= (deUint32)(layoutEntry.offset + layoutEntry.vecStride*vecNdx);
1018e5c31af7Sopenharmony_ci			const vk::VkVertexInputAttributeDescription	desc	=
1019e5c31af7Sopenharmony_ci			{
1020e5c31af7Sopenharmony_ci				curLoc,		// location
1021e5c31af7Sopenharmony_ci				1u,			// binding
1022e5c31af7Sopenharmony_ci				vecFmt,		// format
1023e5c31af7Sopenharmony_ci				offset,		// offset
1024e5c31af7Sopenharmony_ci			};
1025e5c31af7Sopenharmony_ci
1026e5c31af7Sopenharmony_ci			attribs.push_back(desc);
1027e5c31af7Sopenharmony_ci		}
1028e5c31af7Sopenharmony_ci	}
1029e5c31af7Sopenharmony_ci
1030e5c31af7Sopenharmony_ci	return attribs;
1031e5c31af7Sopenharmony_ci}
1032e5c31af7Sopenharmony_ci
1033e5c31af7Sopenharmony_ciMove<vk::VkPipeline> createPipeline (Context&					context,
1034e5c31af7Sopenharmony_ci									 const vector<Value>&		inputValues,
1035e5c31af7Sopenharmony_ci									 const ValueBufferLayout&	inputLayout,
1036e5c31af7Sopenharmony_ci									 const PipelineProgram&		program,
1037e5c31af7Sopenharmony_ci									 vk::VkRenderPass			renderPass,
1038e5c31af7Sopenharmony_ci									 vk::VkPipelineLayout		pipelineLayout,
1039e5c31af7Sopenharmony_ci									 tcu::UVec2					renderSize,
1040e5c31af7Sopenharmony_ci									 deUint32					size)
1041e5c31af7Sopenharmony_ci{
1042e5c31af7Sopenharmony_ci	const vk::VkShaderModule							vertShader				= program.hasShader(glu::SHADERTYPE_VERTEX) ? program.getShader(glu::SHADERTYPE_VERTEX) : DE_NULL;
1043e5c31af7Sopenharmony_ci	const vk::VkShaderModule							tessControlShader		= program.hasShader(glu::SHADERTYPE_TESSELLATION_CONTROL) ? program.getShader(glu::SHADERTYPE_TESSELLATION_CONTROL) : DE_NULL;
1044e5c31af7Sopenharmony_ci	const vk::VkShaderModule							tessEvalShader			= program.hasShader(glu::SHADERTYPE_TESSELLATION_EVALUATION) ? program.getShader(glu::SHADERTYPE_TESSELLATION_EVALUATION) : DE_NULL;
1045e5c31af7Sopenharmony_ci	const vk::VkShaderModule							geomShader				= program.hasShader(glu::SHADERTYPE_GEOMETRY) ? program.getShader(glu::SHADERTYPE_GEOMETRY) : DE_NULL;
1046e5c31af7Sopenharmony_ci	const vk::VkShaderModule							fragShader				= program.hasShader(glu::SHADERTYPE_FRAGMENT) ? program.getShader(glu::SHADERTYPE_FRAGMENT) : DE_NULL;
1047e5c31af7Sopenharmony_ci	const vector<vk::VkVertexInputAttributeDescription>	vertexAttribParams		(getVertexAttributeDescriptions(inputValues, inputLayout));
1048e5c31af7Sopenharmony_ci	const vector<vk::VkViewport>						viewports				(1, vk::makeViewport(renderSize));
1049e5c31af7Sopenharmony_ci	const vector<vk::VkRect2D>							scissors				(1, vk::makeRect2D(renderSize));
1050e5c31af7Sopenharmony_ci	const vk::VkVertexInputBindingDescription			vertexBindings[]		=
1051e5c31af7Sopenharmony_ci	{
1052e5c31af7Sopenharmony_ci		{
1053e5c31af7Sopenharmony_ci			0u,																	// binding
1054e5c31af7Sopenharmony_ci			(deUint32)sizeof(tcu::Vec2),										// stride
1055e5c31af7Sopenharmony_ci			vk::VK_VERTEX_INPUT_RATE_VERTEX,									// stepRate
1056e5c31af7Sopenharmony_ci		},
1057e5c31af7Sopenharmony_ci		{
1058e5c31af7Sopenharmony_ci			1u,																	// binding
1059e5c31af7Sopenharmony_ci			0u,																	// stride
1060e5c31af7Sopenharmony_ci			vk::VK_VERTEX_INPUT_RATE_INSTANCE,									// stepRate
1061e5c31af7Sopenharmony_ci		},
1062e5c31af7Sopenharmony_ci	};
1063e5c31af7Sopenharmony_ci	const vk::VkPipelineVertexInputStateCreateInfo		vertexInputStateParams	=
1064e5c31af7Sopenharmony_ci	{
1065e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// sType
1066e5c31af7Sopenharmony_ci		DE_NULL,															// pNext
1067e5c31af7Sopenharmony_ci		(vk::VkPipelineVertexInputStateCreateFlags)0,
1068e5c31af7Sopenharmony_ci		(inputValues.empty() ? 1u : 2u),									// bindingCount
1069e5c31af7Sopenharmony_ci		vertexBindings,														// pVertexBindingDescriptions
1070e5c31af7Sopenharmony_ci		(deUint32)vertexAttribParams.size(),								// attributeCount
1071e5c31af7Sopenharmony_ci		&vertexAttribParams[0],												// pVertexAttributeDescriptions
1072e5c31af7Sopenharmony_ci	};
1073e5c31af7Sopenharmony_ci	const vk::VkColorComponentFlags						allCompMask				= vk::VK_COLOR_COMPONENT_R_BIT
1074e5c31af7Sopenharmony_ci																				| vk::VK_COLOR_COMPONENT_G_BIT
1075e5c31af7Sopenharmony_ci																				| vk::VK_COLOR_COMPONENT_B_BIT
1076e5c31af7Sopenharmony_ci																				| vk::VK_COLOR_COMPONENT_A_BIT;
1077e5c31af7Sopenharmony_ci	vk::VkPipelineColorBlendAttachmentState				attBlendParams[4];
1078e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < size; i++)
1079e5c31af7Sopenharmony_ci	{
1080e5c31af7Sopenharmony_ci		vk::VkPipelineColorBlendAttachmentState blend =
1081e5c31af7Sopenharmony_ci		{
1082e5c31af7Sopenharmony_ci			VK_FALSE,															// blendEnable
1083e5c31af7Sopenharmony_ci			vk::VK_BLEND_FACTOR_ONE,											// srcBlendColor
1084e5c31af7Sopenharmony_ci			vk::VK_BLEND_FACTOR_ZERO,											// destBlendColor
1085e5c31af7Sopenharmony_ci			vk::VK_BLEND_OP_ADD,												// blendOpColor
1086e5c31af7Sopenharmony_ci			vk::VK_BLEND_FACTOR_ONE,											// srcBlendAlpha
1087e5c31af7Sopenharmony_ci			vk::VK_BLEND_FACTOR_ZERO,											// destBlendAlpha
1088e5c31af7Sopenharmony_ci			vk::VK_BLEND_OP_ADD,												// blendOpAlpha
1089e5c31af7Sopenharmony_ci			allCompMask,														// componentWriteMask
1090e5c31af7Sopenharmony_ci		};
1091e5c31af7Sopenharmony_ci		attBlendParams[i] = blend;
1092e5c31af7Sopenharmony_ci	}
1093e5c31af7Sopenharmony_ci
1094e5c31af7Sopenharmony_ci	const vk::VkPipelineColorBlendStateCreateInfo		blendParams				=
1095e5c31af7Sopenharmony_ci	{
1096e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// sType
1097e5c31af7Sopenharmony_ci		DE_NULL,															// pNext
1098e5c31af7Sopenharmony_ci		(vk::VkPipelineColorBlendStateCreateFlags)0,
1099e5c31af7Sopenharmony_ci		VK_FALSE,															// logicOpEnable
1100e5c31af7Sopenharmony_ci		vk::VK_LOGIC_OP_COPY,												// logicOp
1101e5c31af7Sopenharmony_ci		size,																// attachmentCount
1102e5c31af7Sopenharmony_ci		&attBlendParams[0],													// pAttachments
1103e5c31af7Sopenharmony_ci		{ 0.0f, 0.0f, 0.0f, 0.0f },											// blendConstants
1104e5c31af7Sopenharmony_ci	};
1105e5c31af7Sopenharmony_ci
1106e5c31af7Sopenharmony_ci	return vk::makeGraphicsPipeline(context.getDeviceInterface(),				// const DeviceInterface&                        vk
1107e5c31af7Sopenharmony_ci									context.getDevice(),						// const VkDevice                                device
1108e5c31af7Sopenharmony_ci									pipelineLayout,								// const VkPipelineLayout                        pipelineLayout
1109e5c31af7Sopenharmony_ci									vertShader,									// const VkShaderModule                          vertexShaderModule
1110e5c31af7Sopenharmony_ci									tessControlShader,							// const VkShaderModule                          tessellationControlShaderModule
1111e5c31af7Sopenharmony_ci									tessEvalShader,								// const VkShaderModule                          tessellationEvalShaderModule
1112e5c31af7Sopenharmony_ci									geomShader,									// const VkShaderModule                          geometryShaderModule
1113e5c31af7Sopenharmony_ci									fragShader,									// const VkShaderModule                          fragmentShaderModule
1114e5c31af7Sopenharmony_ci									renderPass,									// const VkRenderPass                            renderPass
1115e5c31af7Sopenharmony_ci									viewports,									// const std::vector<VkViewport>&                viewports
1116e5c31af7Sopenharmony_ci									scissors,									// const std::vector<VkRect2D>&                  scissors
1117e5c31af7Sopenharmony_ci									vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology                     topology
1118e5c31af7Sopenharmony_ci									0u,											// const deUint32                                subpass
1119e5c31af7Sopenharmony_ci									0u,											// const deUint32                                patchControlPoints
1120e5c31af7Sopenharmony_ci									&vertexInputStateParams,					// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1121e5c31af7Sopenharmony_ci									DE_NULL,									// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1122e5c31af7Sopenharmony_ci									DE_NULL,									// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1123e5c31af7Sopenharmony_ci									DE_NULL,									// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1124e5c31af7Sopenharmony_ci									&blendParams);								// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
1125e5c31af7Sopenharmony_ci}
1126e5c31af7Sopenharmony_ci
1127e5c31af7Sopenharmony_ciMove<vk::VkFramebuffer> createFramebuffer (Context& context, vk::VkRenderPass renderPass, Move<vk::VkImageView> colorAttView[4], deUint32 size, int width, int height)
1128e5c31af7Sopenharmony_ci{
1129e5c31af7Sopenharmony_ci	vk::VkImageView att[4];
1130e5c31af7Sopenharmony_ci	for (deUint32 i = 0; i < size; i++)
1131e5c31af7Sopenharmony_ci	{
1132e5c31af7Sopenharmony_ci		att[i] = *colorAttView[i];
1133e5c31af7Sopenharmony_ci	}
1134e5c31af7Sopenharmony_ci	const vk::VkFramebufferCreateInfo	framebufferParams	=
1135e5c31af7Sopenharmony_ci	{
1136e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// sType
1137e5c31af7Sopenharmony_ci		DE_NULL,										// pNext
1138e5c31af7Sopenharmony_ci		(vk::VkFramebufferCreateFlags)0,
1139e5c31af7Sopenharmony_ci		renderPass,										// renderPass
1140e5c31af7Sopenharmony_ci		size,											// attachmentCount
1141e5c31af7Sopenharmony_ci		&att[0],										// pAttachments
1142e5c31af7Sopenharmony_ci		(deUint32)width,								// width
1143e5c31af7Sopenharmony_ci		(deUint32)height,								// height
1144e5c31af7Sopenharmony_ci		1u,												// layers
1145e5c31af7Sopenharmony_ci	};
1146e5c31af7Sopenharmony_ci
1147e5c31af7Sopenharmony_ci	return vk::createFramebuffer(context.getDeviceInterface(), context.getDevice(), &framebufferParams);
1148e5c31af7Sopenharmony_ci}
1149e5c31af7Sopenharmony_ci
1150e5c31af7Sopenharmony_ciMove<vk::VkCommandPool> createCommandPool (Context& context)
1151e5c31af7Sopenharmony_ci{
1152e5c31af7Sopenharmony_ci	const deUint32						queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1153e5c31af7Sopenharmony_ci
1154e5c31af7Sopenharmony_ci	return vk::createCommandPool(context.getDeviceInterface(), context.getDevice(), (vk::VkCommandPoolCreateFlags)0u, queueFamilyIndex);
1155e5c31af7Sopenharmony_ci}
1156e5c31af7Sopenharmony_ci
1157e5c31af7Sopenharmony_ciMove<vk::VkDescriptorPool> createDescriptorPool (Context& context)
1158e5c31af7Sopenharmony_ci{
1159e5c31af7Sopenharmony_ci	return vk::DescriptorPoolBuilder()
1160e5c31af7Sopenharmony_ci				.addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u)
1161e5c31af7Sopenharmony_ci				.build(context.getDeviceInterface(), context.getDevice(), vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1162e5c31af7Sopenharmony_ci}
1163e5c31af7Sopenharmony_ci
1164e5c31af7Sopenharmony_ciMove<vk::VkDescriptorSet> allocateDescriptorSet (Context& context, vk::VkDescriptorPool descriptorPool, vk::VkDescriptorSetLayout setLayout)
1165e5c31af7Sopenharmony_ci{
1166e5c31af7Sopenharmony_ci	const vk::VkDescriptorSetAllocateInfo	params	=
1167e5c31af7Sopenharmony_ci	{
1168e5c31af7Sopenharmony_ci		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1169e5c31af7Sopenharmony_ci		DE_NULL,
1170e5c31af7Sopenharmony_ci		descriptorPool,
1171e5c31af7Sopenharmony_ci		1u,
1172e5c31af7Sopenharmony_ci		&setLayout
1173e5c31af7Sopenharmony_ci	};
1174e5c31af7Sopenharmony_ci
1175e5c31af7Sopenharmony_ci	return vk::allocateDescriptorSet(context.getDeviceInterface(), context.getDevice(), &params);
1176e5c31af7Sopenharmony_ci}
1177e5c31af7Sopenharmony_ci
1178e5c31af7Sopenharmony_ciMove<vk::VkCommandBuffer> allocateCommandBuffer (Context& context, vk::VkCommandPool cmdPool)
1179e5c31af7Sopenharmony_ci{
1180e5c31af7Sopenharmony_ci	return vk::allocateCommandBuffer(context.getDeviceInterface(), context.getDevice(), cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1181e5c31af7Sopenharmony_ci}
1182e5c31af7Sopenharmony_ci
1183e5c31af7Sopenharmony_civk::VkFormat getRenderTargetFormat (DataType dataType)
1184e5c31af7Sopenharmony_ci{
1185e5c31af7Sopenharmony_ci	switch (dataType)
1186e5c31af7Sopenharmony_ci	{
1187e5c31af7Sopenharmony_ci		case glu::TYPE_FLOAT_VEC2:
1188e5c31af7Sopenharmony_ci			return vk::VK_FORMAT_R8G8_UNORM;
1189e5c31af7Sopenharmony_ci		case glu::TYPE_FLOAT_VEC3:
1190e5c31af7Sopenharmony_ci			return vk::VK_FORMAT_R5G6B5_UNORM_PACK16;
1191e5c31af7Sopenharmony_ci		case glu::TYPE_FLOAT_VEC4:
1192e5c31af7Sopenharmony_ci			return vk::VK_FORMAT_R8G8B8A8_UNORM;
1193e5c31af7Sopenharmony_ci		case glu::TYPE_INT_VEC2:
1194e5c31af7Sopenharmony_ci			return vk::VK_FORMAT_R8G8_SINT;
1195e5c31af7Sopenharmony_ci		case glu::TYPE_INT_VEC4:
1196e5c31af7Sopenharmony_ci			return vk::VK_FORMAT_R8G8B8A8_SINT;
1197e5c31af7Sopenharmony_ci		default:
1198e5c31af7Sopenharmony_ci			return vk::VK_FORMAT_R8G8B8A8_UNORM;
1199e5c31af7Sopenharmony_ci	}
1200e5c31af7Sopenharmony_ci}
1201e5c31af7Sopenharmony_ci
1202e5c31af7Sopenharmony_ciMovePtr<vk::Allocation> allocateAndBindMemory (Context& context, vk::VkImage image, vk::MemoryRequirement memReqs)
1203e5c31af7Sopenharmony_ci{
1204e5c31af7Sopenharmony_ci	const vk::DeviceInterface&		vkd		= context.getDeviceInterface();
1205e5c31af7Sopenharmony_ci	const vk::VkMemoryRequirements	imgReqs	= vk::getImageMemoryRequirements(vkd, context.getDevice(), image);
1206e5c31af7Sopenharmony_ci	MovePtr<vk::Allocation>			memory	= context.getDefaultAllocator().allocate(imgReqs, memReqs);
1207e5c31af7Sopenharmony_ci
1208e5c31af7Sopenharmony_ci	vkd.bindImageMemory(context.getDevice(), image, memory->getMemory(), memory->getOffset());
1209e5c31af7Sopenharmony_ci
1210e5c31af7Sopenharmony_ci	return memory;
1211e5c31af7Sopenharmony_ci}
1212e5c31af7Sopenharmony_ci
1213e5c31af7Sopenharmony_civoid writeValuesToMem (Context& context, const vk::Allocation& dst, const ValueBufferLayout& layout, const vector<Value>& values, int arrayNdx)
1214e5c31af7Sopenharmony_ci{
1215e5c31af7Sopenharmony_ci	copyToLayout(dst.getHostPtr(), layout, values, arrayNdx);
1216e5c31af7Sopenharmony_ci
1217e5c31af7Sopenharmony_ci	// \note Buffers are not allocated with coherency / uncached requirement so we need to manually flush CPU write caches
1218e5c31af7Sopenharmony_ci	flushAlloc(context.getDeviceInterface(), context.getDevice(), dst);
1219e5c31af7Sopenharmony_ci}
1220e5c31af7Sopenharmony_ci
1221e5c31af7Sopenharmony_ciclass ShaderCaseInstance : public TestInstance
1222e5c31af7Sopenharmony_ci{
1223e5c31af7Sopenharmony_cipublic:
1224e5c31af7Sopenharmony_ci													ShaderCaseInstance              (Context& context, const ShaderCaseSpecification& spec);
1225e5c31af7Sopenharmony_ci													~ShaderCaseInstance		(void);
1226e5c31af7Sopenharmony_ci
1227e5c31af7Sopenharmony_ci	TestStatus										iterate					(void);
1228e5c31af7Sopenharmony_ci
1229e5c31af7Sopenharmony_ciprivate:
1230e5c31af7Sopenharmony_ci	enum
1231e5c31af7Sopenharmony_ci	{
1232e5c31af7Sopenharmony_ci		RENDER_WIDTH		= 64,
1233e5c31af7Sopenharmony_ci		RENDER_HEIGHT		= 64,
1234e5c31af7Sopenharmony_ci
1235e5c31af7Sopenharmony_ci		POSITIONS_OFFSET	= 0,
1236e5c31af7Sopenharmony_ci		POSITIONS_SIZE		= (int)sizeof(Vec2)*4,
1237e5c31af7Sopenharmony_ci
1238e5c31af7Sopenharmony_ci		INDICES_OFFSET		= POSITIONS_SIZE,
1239e5c31af7Sopenharmony_ci		INDICES_SIZE		= (int)sizeof(deUint16)*6,
1240e5c31af7Sopenharmony_ci
1241e5c31af7Sopenharmony_ci		TOTAL_POS_NDX_SIZE	= POSITIONS_SIZE+INDICES_SIZE
1242e5c31af7Sopenharmony_ci	};
1243e5c31af7Sopenharmony_ci
1244e5c31af7Sopenharmony_ci	const ShaderCaseSpecification&					m_spec;
1245e5c31af7Sopenharmony_ci
1246e5c31af7Sopenharmony_ci	const Unique<vk::VkBuffer>						m_posNdxBuffer;
1247e5c31af7Sopenharmony_ci	const UniquePtr<vk::Allocation>					m_posNdxMem;
1248e5c31af7Sopenharmony_ci
1249e5c31af7Sopenharmony_ci	const ValueBufferLayout							m_inputLayout;
1250e5c31af7Sopenharmony_ci	const Unique<vk::VkBuffer>						m_inputBuffer;			// Input values (attributes). Can be NULL if no inputs present
1251e5c31af7Sopenharmony_ci	const UniquePtr<vk::Allocation>					m_inputMem;				// Input memory, can be NULL if no input buffer exists
1252e5c31af7Sopenharmony_ci
1253e5c31af7Sopenharmony_ci	const ValueBufferLayout							m_referenceLayout;
1254e5c31af7Sopenharmony_ci	const Unique<vk::VkBuffer>						m_referenceBuffer;		// Output (reference) values. Can be NULL if no outputs present
1255e5c31af7Sopenharmony_ci	const UniquePtr<vk::Allocation>					m_referenceMem;			// Output (reference) memory, can be NULL if no reference buffer exists
1256e5c31af7Sopenharmony_ci
1257e5c31af7Sopenharmony_ci	const ValueBufferLayout							m_uniformLayout;
1258e5c31af7Sopenharmony_ci	const Unique<vk::VkBuffer>						m_uniformBuffer;		// Uniform values. Can be NULL if no uniforms present
1259e5c31af7Sopenharmony_ci	const UniquePtr<vk::Allocation>					m_uniformMem;			// Uniform memory, can be NULL if no uniform buffer exists
1260e5c31af7Sopenharmony_ci
1261e5c31af7Sopenharmony_ci	const vk::VkFormat								m_rtFormat;
1262e5c31af7Sopenharmony_ci	deUint32										m_outputCount;
1263e5c31af7Sopenharmony_ci	Move<vk::VkImage>								m_rtImage [4];
1264e5c31af7Sopenharmony_ci	MovePtr<vk::Allocation>							m_rtMem[4];
1265e5c31af7Sopenharmony_ci	Move<vk::VkImageView>							m_rtView[4];
1266e5c31af7Sopenharmony_ci
1267e5c31af7Sopenharmony_ci	Move<vk::VkBuffer>								m_readImageBuffer[4];
1268e5c31af7Sopenharmony_ci	MovePtr<vk::Allocation>							m_readImageMem[4];
1269e5c31af7Sopenharmony_ci
1270e5c31af7Sopenharmony_ci	const Unique<vk::VkRenderPass>					m_renderPass;
1271e5c31af7Sopenharmony_ci	Move<vk::VkFramebuffer>							m_framebuffer;
1272e5c31af7Sopenharmony_ci	const PipelineProgram							m_program;
1273e5c31af7Sopenharmony_ci	const Unique<vk::VkDescriptorSetLayout>			m_descriptorSetLayout;
1274e5c31af7Sopenharmony_ci	const Unique<vk::VkPipelineLayout>				m_pipelineLayout;
1275e5c31af7Sopenharmony_ci	const Unique<vk::VkPipeline>					m_pipeline;
1276e5c31af7Sopenharmony_ci
1277e5c31af7Sopenharmony_ci	const Unique<vk::VkDescriptorPool>				m_descriptorPool;
1278e5c31af7Sopenharmony_ci	const Unique<vk::VkDescriptorSet>				m_descriptorSet;
1279e5c31af7Sopenharmony_ci
1280e5c31af7Sopenharmony_ci	const Unique<vk::VkCommandPool>					m_cmdPool;
1281e5c31af7Sopenharmony_ci	const Unique<vk::VkCommandBuffer>				m_cmdBuffer;
1282e5c31af7Sopenharmony_ci
1283e5c31af7Sopenharmony_ci	int												m_subCaseNdx;
1284e5c31af7Sopenharmony_ci};
1285e5c31af7Sopenharmony_ci
1286e5c31af7Sopenharmony_ciShaderCaseInstance::ShaderCaseInstance (Context& context, const ShaderCaseSpecification& spec)
1287e5c31af7Sopenharmony_ci	: TestInstance			(context)
1288e5c31af7Sopenharmony_ci	, m_spec				(spec)
1289e5c31af7Sopenharmony_ci
1290e5c31af7Sopenharmony_ci	, m_posNdxBuffer		(createBuffer(context, (vk::VkDeviceSize)TOTAL_POS_NDX_SIZE, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT|vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
1291e5c31af7Sopenharmony_ci	, m_posNdxMem			(vk::bindBuffer (context.getDeviceInterface(), context.getDevice(),m_context.getDefaultAllocator(), *m_posNdxBuffer, vk::MemoryRequirement::HostVisible))
1292e5c31af7Sopenharmony_ci
1293e5c31af7Sopenharmony_ci	, m_inputLayout			(computeStd430Layout(spec.values.inputs))
1294e5c31af7Sopenharmony_ci	, m_inputBuffer			(m_inputLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_inputLayout.size, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) : Move<vk::VkBuffer>())
1295e5c31af7Sopenharmony_ci	, m_inputMem			(m_inputLayout.size > 0 ? vk::bindBuffer (context.getDeviceInterface(), context.getDevice(),m_context.getDefaultAllocator(), *m_inputBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1296e5c31af7Sopenharmony_ci
1297e5c31af7Sopenharmony_ci	, m_referenceLayout		(computeStd140Layout(spec.values.outputs))
1298e5c31af7Sopenharmony_ci	, m_referenceBuffer		(m_referenceLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_referenceLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
1299e5c31af7Sopenharmony_ci	, m_referenceMem		(m_referenceLayout.size > 0 ? vk::bindBuffer (context.getDeviceInterface(), context.getDevice(),m_context.getDefaultAllocator(), *m_referenceBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1300e5c31af7Sopenharmony_ci
1301e5c31af7Sopenharmony_ci	, m_uniformLayout		(computeStd140Layout(spec.values.uniforms))
1302e5c31af7Sopenharmony_ci	, m_uniformBuffer		(m_uniformLayout.size > 0 ? createBuffer(context, (vk::VkDeviceSize)m_uniformLayout.size, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : Move<vk::VkBuffer>())
1303e5c31af7Sopenharmony_ci	, m_uniformMem			(m_uniformLayout.size > 0 ? vk::bindBuffer (context.getDeviceInterface(), context.getDevice(),m_context.getDefaultAllocator(), *m_uniformBuffer, vk::MemoryRequirement::HostVisible) : MovePtr<vk::Allocation>())
1304e5c31af7Sopenharmony_ci
1305e5c31af7Sopenharmony_ci	, m_rtFormat			(getRenderTargetFormat(spec.outputFormat))
1306e5c31af7Sopenharmony_ci	, m_outputCount			(((deUint32)m_spec.values.outputs.size() == 0 || m_spec.outputType == glu::sl::OUTPUT_RESULT) ? 1 : (deUint32)m_spec.values.outputs.size())
1307e5c31af7Sopenharmony_ci	, m_rtImage				()
1308e5c31af7Sopenharmony_ci	, m_rtMem				()
1309e5c31af7Sopenharmony_ci	, m_rtView				()
1310e5c31af7Sopenharmony_ci
1311e5c31af7Sopenharmony_ci	, m_readImageBuffer		()
1312e5c31af7Sopenharmony_ci	, m_readImageMem		()
1313e5c31af7Sopenharmony_ci
1314e5c31af7Sopenharmony_ci	, m_renderPass			(createRenderPass(context, m_rtFormat, m_outputCount))
1315e5c31af7Sopenharmony_ci	, m_framebuffer			()
1316e5c31af7Sopenharmony_ci	, m_program				(context, spec)
1317e5c31af7Sopenharmony_ci	, m_descriptorSetLayout	(createDescriptorSetLayout(context, m_program.getStages()))
1318e5c31af7Sopenharmony_ci	, m_pipelineLayout		(createPipelineLayout(context, *m_descriptorSetLayout))
1319e5c31af7Sopenharmony_ci	, m_pipeline			(createPipeline(context, spec.values.inputs, m_inputLayout, m_program, *m_renderPass, *m_pipelineLayout, tcu::UVec2(RENDER_WIDTH, RENDER_HEIGHT), m_outputCount))
1320e5c31af7Sopenharmony_ci
1321e5c31af7Sopenharmony_ci	, m_descriptorPool		(createDescriptorPool(context))
1322e5c31af7Sopenharmony_ci	, m_descriptorSet		(allocateDescriptorSet(context, *m_descriptorPool, *m_descriptorSetLayout))
1323e5c31af7Sopenharmony_ci
1324e5c31af7Sopenharmony_ci	, m_cmdPool				(createCommandPool(context))
1325e5c31af7Sopenharmony_ci	, m_cmdBuffer			(allocateCommandBuffer(context, *m_cmdPool))
1326e5c31af7Sopenharmony_ci
1327e5c31af7Sopenharmony_ci	, m_subCaseNdx			(0)
1328e5c31af7Sopenharmony_ci{
1329e5c31af7Sopenharmony_ci	{
1330e5c31af7Sopenharmony_ci		// Initialize the resources for each color attachment needed by the shader
1331e5c31af7Sopenharmony_ci		for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1332e5c31af7Sopenharmony_ci		{
1333e5c31af7Sopenharmony_ci			m_rtImage[outNdx] = createImage2D(context, RENDER_WIDTH, RENDER_HEIGHT, m_rtFormat, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|   vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1334e5c31af7Sopenharmony_ci			m_rtMem[outNdx] = allocateAndBindMemory(context, *m_rtImage[outNdx], vk::MemoryRequirement::Any);
1335e5c31af7Sopenharmony_ci			m_rtView[outNdx] = createAttachmentView(context, *m_rtImage[outNdx], m_rtFormat);
1336e5c31af7Sopenharmony_ci
1337e5c31af7Sopenharmony_ci			m_readImageBuffer[outNdx] = createBuffer(context, (vk::VkDeviceSize)(RENDER_WIDTH * RENDER_HEIGHT * tcu::getPixelSize(vk::mapVkFormat(m_rtFormat))), vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1338e5c31af7Sopenharmony_ci			m_readImageMem[outNdx]	= vk::bindBuffer (context.getDeviceInterface(), context.getDevice(),m_context.getDefaultAllocator(), *m_readImageBuffer[outNdx], vk::MemoryRequirement::HostVisible);
1339e5c31af7Sopenharmony_ci		}
1340e5c31af7Sopenharmony_ci		m_framebuffer = createFramebuffer(context, *m_renderPass, m_rtView, m_outputCount, RENDER_WIDTH, RENDER_HEIGHT);
1341e5c31af7Sopenharmony_ci	}
1342e5c31af7Sopenharmony_ci
1343e5c31af7Sopenharmony_ci	const vk::DeviceInterface&	vkd					= context.getDeviceInterface();
1344e5c31af7Sopenharmony_ci	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1345e5c31af7Sopenharmony_ci
1346e5c31af7Sopenharmony_ci	{
1347e5c31af7Sopenharmony_ci		const Vec2			s_positions[]	=
1348e5c31af7Sopenharmony_ci		{
1349e5c31af7Sopenharmony_ci			Vec2(-1.0f, -1.0f),
1350e5c31af7Sopenharmony_ci			Vec2(-1.0f, +1.0f),
1351e5c31af7Sopenharmony_ci			Vec2(+1.0f, -1.0f),
1352e5c31af7Sopenharmony_ci			Vec2(+1.0f, +1.0f)
1353e5c31af7Sopenharmony_ci		};
1354e5c31af7Sopenharmony_ci		const deUint16		s_indices[]		=
1355e5c31af7Sopenharmony_ci		{
1356e5c31af7Sopenharmony_ci			0, 1, 2,
1357e5c31af7Sopenharmony_ci			1, 3, 2
1358e5c31af7Sopenharmony_ci		};
1359e5c31af7Sopenharmony_ci
1360e5c31af7Sopenharmony_ci		DE_STATIC_ASSERT(sizeof(s_positions) == POSITIONS_SIZE);
1361e5c31af7Sopenharmony_ci		DE_STATIC_ASSERT(sizeof(s_indices) == INDICES_SIZE);
1362e5c31af7Sopenharmony_ci
1363e5c31af7Sopenharmony_ci		deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + POSITIONS_OFFSET,	&s_positions[0],	sizeof(s_positions));
1364e5c31af7Sopenharmony_ci		deMemcpy((deUint8*)m_posNdxMem->getHostPtr() + INDICES_OFFSET,		&s_indices[0],		sizeof(s_indices));
1365e5c31af7Sopenharmony_ci
1366e5c31af7Sopenharmony_ci		flushAlloc(m_context.getDeviceInterface(), context.getDevice(), *m_posNdxMem);
1367e5c31af7Sopenharmony_ci	}
1368e5c31af7Sopenharmony_ci
1369e5c31af7Sopenharmony_ci	if (!m_spec.values.uniforms.empty())
1370e5c31af7Sopenharmony_ci	{
1371e5c31af7Sopenharmony_ci		const vk::VkDescriptorBufferInfo	bufInfo	=
1372e5c31af7Sopenharmony_ci		{
1373e5c31af7Sopenharmony_ci			*m_uniformBuffer,
1374e5c31af7Sopenharmony_ci			(vk::VkDeviceSize)0,	// offset
1375e5c31af7Sopenharmony_ci			(vk::VkDeviceSize)m_uniformLayout.size
1376e5c31af7Sopenharmony_ci		};
1377e5c31af7Sopenharmony_ci
1378e5c31af7Sopenharmony_ci		vk::DescriptorSetUpdateBuilder()
1379e5c31af7Sopenharmony_ci			.writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(USER_UNIFORM_BINDING),
1380e5c31af7Sopenharmony_ci						 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
1381e5c31af7Sopenharmony_ci			.update(vkd, m_context.getDevice());
1382e5c31af7Sopenharmony_ci	}
1383e5c31af7Sopenharmony_ci
1384e5c31af7Sopenharmony_ci	if (!m_spec.values.outputs.empty())
1385e5c31af7Sopenharmony_ci	{
1386e5c31af7Sopenharmony_ci		const vk::VkDescriptorBufferInfo	bufInfo	=
1387e5c31af7Sopenharmony_ci		{
1388e5c31af7Sopenharmony_ci			*m_referenceBuffer,
1389e5c31af7Sopenharmony_ci			(vk::VkDeviceSize)0,	// offset
1390e5c31af7Sopenharmony_ci			(vk::VkDeviceSize)m_referenceLayout.size
1391e5c31af7Sopenharmony_ci		};
1392e5c31af7Sopenharmony_ci
1393e5c31af7Sopenharmony_ci		vk::DescriptorSetUpdateBuilder()
1394e5c31af7Sopenharmony_ci			.writeSingle(*m_descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(REFERENCE_UNIFORM_BINDING),
1395e5c31af7Sopenharmony_ci						 vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufInfo)
1396e5c31af7Sopenharmony_ci			.update(vkd, m_context.getDevice());
1397e5c31af7Sopenharmony_ci	}
1398e5c31af7Sopenharmony_ci
1399e5c31af7Sopenharmony_ci	// Record command buffer
1400e5c31af7Sopenharmony_ci
1401e5c31af7Sopenharmony_ci	beginCommandBuffer(vkd, *m_cmdBuffer, 0u);
1402e5c31af7Sopenharmony_ci
1403e5c31af7Sopenharmony_ci	{
1404e5c31af7Sopenharmony_ci		const vk::VkMemoryBarrier		vertFlushBarrier	=
1405e5c31af7Sopenharmony_ci		{
1406e5c31af7Sopenharmony_ci			vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,													// sType
1407e5c31af7Sopenharmony_ci			DE_NULL,																				// pNext
1408e5c31af7Sopenharmony_ci			vk::VK_ACCESS_HOST_WRITE_BIT,															// srcAccessMask
1409e5c31af7Sopenharmony_ci			vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT|vk::VK_ACCESS_UNIFORM_READ_BIT,					// dstAccessMask
1410e5c31af7Sopenharmony_ci		};
1411e5c31af7Sopenharmony_ci		vk::VkImageMemoryBarrier	colorAttBarrier	[4];
1412e5c31af7Sopenharmony_ci		for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1413e5c31af7Sopenharmony_ci		{
1414e5c31af7Sopenharmony_ci			vk::VkImageMemoryBarrier barrier =
1415e5c31af7Sopenharmony_ci			{
1416e5c31af7Sopenharmony_ci				vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// sType
1417e5c31af7Sopenharmony_ci				DE_NULL,										// pNext
1418e5c31af7Sopenharmony_ci				0u,												// srcAccessMask
1419e5c31af7Sopenharmony_ci				vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// dstAccessMask
1420e5c31af7Sopenharmony_ci				vk::VK_IMAGE_LAYOUT_UNDEFINED,					// oldLayout
1421e5c31af7Sopenharmony_ci				vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// newLayout
1422e5c31af7Sopenharmony_ci				queueFamilyIndex,								// srcQueueFamilyIndex
1423e5c31af7Sopenharmony_ci				queueFamilyIndex,								// destQueueFamilyIndex
1424e5c31af7Sopenharmony_ci				*m_rtImage[outNdx],								// image
1425e5c31af7Sopenharmony_ci				{
1426e5c31af7Sopenharmony_ci					vk::VK_IMAGE_ASPECT_COLOR_BIT,				// aspectMask
1427e5c31af7Sopenharmony_ci					0u,											// baseMipLevel
1428e5c31af7Sopenharmony_ci					1u,											// mipLevels
1429e5c31af7Sopenharmony_ci					0u,											// baseArraySlice
1430e5c31af7Sopenharmony_ci					1u,											// arraySize
1431e5c31af7Sopenharmony_ci				}												// subresourceRange
1432e5c31af7Sopenharmony_ci			};
1433e5c31af7Sopenharmony_ci			colorAttBarrier[outNdx]	= barrier;
1434e5c31af7Sopenharmony_ci		}
1435e5c31af7Sopenharmony_ci		vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (vk::VkDependencyFlags)0,
1436e5c31af7Sopenharmony_ci							   1, &vertFlushBarrier,
1437e5c31af7Sopenharmony_ci							   0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1438e5c31af7Sopenharmony_ci							   m_outputCount, &colorAttBarrier[0]);
1439e5c31af7Sopenharmony_ci	}
1440e5c31af7Sopenharmony_ci
1441e5c31af7Sopenharmony_ci	{
1442e5c31af7Sopenharmony_ci		vk::VkClearValue			clearValue[4];
1443e5c31af7Sopenharmony_ci		for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1444e5c31af7Sopenharmony_ci		{
1445e5c31af7Sopenharmony_ci			vk::VkClearValue value = vk::makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
1446e5c31af7Sopenharmony_ci			clearValue[outNdx] = value;
1447e5c31af7Sopenharmony_ci		}
1448e5c31af7Sopenharmony_ci		beginRenderPass(vkd, *m_cmdBuffer, *m_renderPass, *m_framebuffer, vk::makeRect2D(0, 0, RENDER_WIDTH, RENDER_HEIGHT), m_outputCount, clearValue);
1449e5c31af7Sopenharmony_ci	}
1450e5c31af7Sopenharmony_ci
1451e5c31af7Sopenharmony_ci	vkd.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1452e5c31af7Sopenharmony_ci
1453e5c31af7Sopenharmony_ci	if (!m_spec.values.uniforms.empty() || !m_spec.values.outputs.empty())
1454e5c31af7Sopenharmony_ci		vkd.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
1455e5c31af7Sopenharmony_ci
1456e5c31af7Sopenharmony_ci	{
1457e5c31af7Sopenharmony_ci		const vk::VkBuffer		buffers[]	= { *m_posNdxBuffer, *m_inputBuffer };
1458e5c31af7Sopenharmony_ci		const vk::VkDeviceSize	offsets[]	= { POSITIONS_OFFSET, 0u };
1459e5c31af7Sopenharmony_ci		const deUint32			numBuffers	= buffers[1] != 0 ? 2u : 1u;
1460e5c31af7Sopenharmony_ci		vkd.cmdBindVertexBuffers(*m_cmdBuffer, 0u, numBuffers, buffers, offsets);
1461e5c31af7Sopenharmony_ci	}
1462e5c31af7Sopenharmony_ci
1463e5c31af7Sopenharmony_ci	vkd.cmdBindIndexBuffer	(*m_cmdBuffer, *m_posNdxBuffer, (vk::VkDeviceSize)INDICES_OFFSET, vk::VK_INDEX_TYPE_UINT16);
1464e5c31af7Sopenharmony_ci	vkd.cmdDrawIndexed		(*m_cmdBuffer, 6u, 1u, 0u, 0u, 0u);
1465e5c31af7Sopenharmony_ci	endRenderPass			(vkd, *m_cmdBuffer);
1466e5c31af7Sopenharmony_ci
1467e5c31af7Sopenharmony_ci	{
1468e5c31af7Sopenharmony_ci		vk::VkImageMemoryBarrier	renderFinishBarrier[4];
1469e5c31af7Sopenharmony_ci		for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1470e5c31af7Sopenharmony_ci		{
1471e5c31af7Sopenharmony_ci			vk::VkImageMemoryBarrier	barrier =
1472e5c31af7Sopenharmony_ci			{
1473e5c31af7Sopenharmony_ci				vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// sType
1474e5c31af7Sopenharmony_ci				DE_NULL,										// pNext
1475e5c31af7Sopenharmony_ci				vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// srcAccessMask
1476e5c31af7Sopenharmony_ci				vk::VK_ACCESS_TRANSFER_READ_BIT,				// dstAccessMask
1477e5c31af7Sopenharmony_ci				vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// oldLayout
1478e5c31af7Sopenharmony_ci				vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// newLayout
1479e5c31af7Sopenharmony_ci				queueFamilyIndex,								// srcQueueFamilyIndex
1480e5c31af7Sopenharmony_ci				queueFamilyIndex,								// destQueueFamilyIndex
1481e5c31af7Sopenharmony_ci				*m_rtImage[outNdx],								// image
1482e5c31af7Sopenharmony_ci				{
1483e5c31af7Sopenharmony_ci					vk::VK_IMAGE_ASPECT_COLOR_BIT,				// aspectMask
1484e5c31af7Sopenharmony_ci					0u,											// baseMipLevel
1485e5c31af7Sopenharmony_ci					1u,											// mipLevels
1486e5c31af7Sopenharmony_ci					0u,											// baseArraySlice
1487e5c31af7Sopenharmony_ci					1u,											// arraySize
1488e5c31af7Sopenharmony_ci				}												// subresourceRange
1489e5c31af7Sopenharmony_ci			};
1490e5c31af7Sopenharmony_ci			renderFinishBarrier[outNdx] = barrier;
1491e5c31af7Sopenharmony_ci        }
1492e5c31af7Sopenharmony_ci
1493e5c31af7Sopenharmony_ci		vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0,
1494e5c31af7Sopenharmony_ci							   0, (const vk::VkMemoryBarrier*)DE_NULL,
1495e5c31af7Sopenharmony_ci							   0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
1496e5c31af7Sopenharmony_ci							   m_outputCount, &renderFinishBarrier[0]);
1497e5c31af7Sopenharmony_ci	}
1498e5c31af7Sopenharmony_ci
1499e5c31af7Sopenharmony_ci	{
1500e5c31af7Sopenharmony_ci		for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1501e5c31af7Sopenharmony_ci		{
1502e5c31af7Sopenharmony_ci			const vk::VkBufferImageCopy	copyParams	=
1503e5c31af7Sopenharmony_ci			{
1504e5c31af7Sopenharmony_ci				(vk::VkDeviceSize)0u,					// bufferOffset
1505e5c31af7Sopenharmony_ci				(deUint32)RENDER_WIDTH,					// bufferRowLength
1506e5c31af7Sopenharmony_ci				(deUint32)RENDER_HEIGHT,				// bufferImageHeight
1507e5c31af7Sopenharmony_ci				{
1508e5c31af7Sopenharmony_ci					vk::VK_IMAGE_ASPECT_COLOR_BIT,			// aspect
1509e5c31af7Sopenharmony_ci					0u,										// mipLevel
1510e5c31af7Sopenharmony_ci					0u,										// arrayLayer
1511e5c31af7Sopenharmony_ci					1u,										// arraySize
1512e5c31af7Sopenharmony_ci				},										// imageSubresource
1513e5c31af7Sopenharmony_ci				{ 0u, 0u, 0u },							// imageOffset
1514e5c31af7Sopenharmony_ci				{ RENDER_WIDTH, RENDER_HEIGHT, 1u }		// imageExtent
1515e5c31af7Sopenharmony_ci			};
1516e5c31af7Sopenharmony_ci
1517e5c31af7Sopenharmony_ci			vkd.cmdCopyImageToBuffer(*m_cmdBuffer, *m_rtImage[outNdx], vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_readImageBuffer[outNdx], 1u, &copyParams);
1518e5c31af7Sopenharmony_ci		}
1519e5c31af7Sopenharmony_ci	}
1520e5c31af7Sopenharmony_ci
1521e5c31af7Sopenharmony_ci	{
1522e5c31af7Sopenharmony_ci		const vk::VkDeviceSize			size				= (vk::VkDeviceSize)(RENDER_WIDTH * RENDER_HEIGHT * tcu::getPixelSize(vk::mapVkFormat(m_rtFormat)));
1523e5c31af7Sopenharmony_ci		vk::VkBufferMemoryBarrier	copyFinishBarrier[4];
1524e5c31af7Sopenharmony_ci		for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1525e5c31af7Sopenharmony_ci		{
1526e5c31af7Sopenharmony_ci			vk::VkBufferMemoryBarrier barrier =
1527e5c31af7Sopenharmony_ci			{
1528e5c31af7Sopenharmony_ci				vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		// sType
1529e5c31af7Sopenharmony_ci				DE_NULL,											// pNext
1530e5c31af7Sopenharmony_ci				vk::VK_ACCESS_TRANSFER_WRITE_BIT,					// srcAccessMask
1531e5c31af7Sopenharmony_ci				vk::VK_ACCESS_HOST_READ_BIT,						// dstAccessMask
1532e5c31af7Sopenharmony_ci				queueFamilyIndex,									// srcQueueFamilyIndex
1533e5c31af7Sopenharmony_ci				queueFamilyIndex,									// destQueueFamilyIndex
1534e5c31af7Sopenharmony_ci				*m_readImageBuffer[outNdx],									// buffer
1535e5c31af7Sopenharmony_ci				0u,													// offset
1536e5c31af7Sopenharmony_ci				size												// size
1537e5c31af7Sopenharmony_ci			};
1538e5c31af7Sopenharmony_ci			copyFinishBarrier[outNdx] = barrier;
1539e5c31af7Sopenharmony_ci		}
1540e5c31af7Sopenharmony_ci		vkd.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, (vk::VkDependencyFlags)0,
1541e5c31af7Sopenharmony_ci							   0, (const vk::VkMemoryBarrier*)DE_NULL,
1542e5c31af7Sopenharmony_ci							   m_outputCount, &copyFinishBarrier[0],
1543e5c31af7Sopenharmony_ci							   0, (const vk::VkImageMemoryBarrier*)DE_NULL);
1544e5c31af7Sopenharmony_ci	}
1545e5c31af7Sopenharmony_ci
1546e5c31af7Sopenharmony_ci	endCommandBuffer(vkd, *m_cmdBuffer);
1547e5c31af7Sopenharmony_ci}
1548e5c31af7Sopenharmony_ci
1549e5c31af7Sopenharmony_ciShaderCaseInstance::~ShaderCaseInstance (void)
1550e5c31af7Sopenharmony_ci{
1551e5c31af7Sopenharmony_ci}
1552e5c31af7Sopenharmony_ci
1553e5c31af7Sopenharmony_ciint getNumSubCases (const ValueBlock& values)
1554e5c31af7Sopenharmony_ci{
1555e5c31af7Sopenharmony_ci	if (!values.outputs.empty())
1556e5c31af7Sopenharmony_ci		return int(values.outputs[0].elements.size() / values.outputs[0].type.getScalarSize());
1557e5c31af7Sopenharmony_ci	else
1558e5c31af7Sopenharmony_ci		return 1; // Always run at least one iteration even if no output values are specified
1559e5c31af7Sopenharmony_ci}
1560e5c31af7Sopenharmony_ci
1561e5c31af7Sopenharmony_cibool checkResultImage (const ConstPixelBufferAccess& result)
1562e5c31af7Sopenharmony_ci{
1563e5c31af7Sopenharmony_ci	const tcu::IVec4	refPix	(255, 255, 255, 255);
1564e5c31af7Sopenharmony_ci
1565e5c31af7Sopenharmony_ci	for (int y = 0; y < result.getHeight(); y++)
1566e5c31af7Sopenharmony_ci	{
1567e5c31af7Sopenharmony_ci		for (int x = 0; x < result.getWidth(); x++)
1568e5c31af7Sopenharmony_ci		{
1569e5c31af7Sopenharmony_ci			const tcu::IVec4	resPix	= result.getPixelInt(x, y);
1570e5c31af7Sopenharmony_ci
1571e5c31af7Sopenharmony_ci			if (boolAny(notEqual(resPix, refPix)))
1572e5c31af7Sopenharmony_ci				return false;
1573e5c31af7Sopenharmony_ci		}
1574e5c31af7Sopenharmony_ci	}
1575e5c31af7Sopenharmony_ci
1576e5c31af7Sopenharmony_ci	return true;
1577e5c31af7Sopenharmony_ci}
1578e5c31af7Sopenharmony_ci
1579e5c31af7Sopenharmony_cibool checkResultImageWithReference (const ConstPixelBufferAccess& result, tcu::IVec4 refPix)
1580e5c31af7Sopenharmony_ci{
1581e5c31af7Sopenharmony_ci	for (int y = 0; y < result.getHeight(); y++)
1582e5c31af7Sopenharmony_ci	{
1583e5c31af7Sopenharmony_ci		for (int x = 0; x < result.getWidth(); x++)
1584e5c31af7Sopenharmony_ci		{
1585e5c31af7Sopenharmony_ci			const tcu::IVec4	resPix	= result.getPixelInt(x, y);
1586e5c31af7Sopenharmony_ci
1587e5c31af7Sopenharmony_ci			if (boolAny(notEqual(resPix, refPix)))
1588e5c31af7Sopenharmony_ci				return false;
1589e5c31af7Sopenharmony_ci		}
1590e5c31af7Sopenharmony_ci	}
1591e5c31af7Sopenharmony_ci
1592e5c31af7Sopenharmony_ci	return true;
1593e5c31af7Sopenharmony_ci}
1594e5c31af7Sopenharmony_ciTestStatus ShaderCaseInstance::iterate (void)
1595e5c31af7Sopenharmony_ci{
1596e5c31af7Sopenharmony_ci	const vk::DeviceInterface&	vkd		= m_context.getDeviceInterface();
1597e5c31af7Sopenharmony_ci	const vk::VkDevice			device	= m_context.getDevice();
1598e5c31af7Sopenharmony_ci	const vk::VkQueue			queue	= m_context.getUniversalQueue();
1599e5c31af7Sopenharmony_ci
1600e5c31af7Sopenharmony_ci	if (!m_spec.values.inputs.empty())
1601e5c31af7Sopenharmony_ci		writeValuesToMem(m_context, *m_inputMem, m_inputLayout, m_spec.values.inputs, m_subCaseNdx);
1602e5c31af7Sopenharmony_ci
1603e5c31af7Sopenharmony_ci	if (!m_spec.values.outputs.empty())
1604e5c31af7Sopenharmony_ci		writeValuesToMem(m_context, *m_referenceMem, m_referenceLayout, m_spec.values.outputs, m_subCaseNdx);
1605e5c31af7Sopenharmony_ci
1606e5c31af7Sopenharmony_ci	if (!m_spec.values.uniforms.empty())
1607e5c31af7Sopenharmony_ci		writeValuesToMem(m_context, *m_uniformMem, m_uniformLayout, m_spec.values.uniforms, m_subCaseNdx);
1608e5c31af7Sopenharmony_ci
1609e5c31af7Sopenharmony_ci	submitCommandsAndWait(vkd, device, queue, m_cmdBuffer.get());
1610e5c31af7Sopenharmony_ci
1611e5c31af7Sopenharmony_ci	// Result was checked in fragment shader
1612e5c31af7Sopenharmony_ci	if (m_spec.outputType == glu::sl::OUTPUT_RESULT)
1613e5c31af7Sopenharmony_ci	{
1614e5c31af7Sopenharmony_ci		const ConstPixelBufferAccess	imgAccess	(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), RENDER_WIDTH, RENDER_HEIGHT, 1, m_readImageMem[0]->getHostPtr());
1615e5c31af7Sopenharmony_ci
1616e5c31af7Sopenharmony_ci		invalidateAlloc(vkd, device, *m_readImageMem[0]);
1617e5c31af7Sopenharmony_ci
1618e5c31af7Sopenharmony_ci		if (!checkResultImage(imgAccess))
1619e5c31af7Sopenharmony_ci		{
1620e5c31af7Sopenharmony_ci			TestLog&	log		= m_context.getTestContext().getLog();
1621e5c31af7Sopenharmony_ci
1622e5c31af7Sopenharmony_ci			log << TestLog::Message << "ERROR: Got non-white pixels on sub-case " << m_subCaseNdx << TestLog::EndMessage
1623e5c31af7Sopenharmony_ci				<< TestLog::Image("Result", "Result", imgAccess);
1624e5c31af7Sopenharmony_ci
1625e5c31af7Sopenharmony_ci			dumpValues(log, m_spec.values, m_subCaseNdx);
1626e5c31af7Sopenharmony_ci
1627e5c31af7Sopenharmony_ci			return TestStatus::fail(string("Got invalid pixels at sub-case ") + de::toString(m_subCaseNdx));
1628e5c31af7Sopenharmony_ci		}
1629e5c31af7Sopenharmony_ci	}
1630e5c31af7Sopenharmony_ci	// Result was written to color buffer
1631e5c31af7Sopenharmony_ci	else
1632e5c31af7Sopenharmony_ci	{
1633e5c31af7Sopenharmony_ci		for (deUint32 outNdx = 0; outNdx < m_outputCount; outNdx++)
1634e5c31af7Sopenharmony_ci		{
1635e5c31af7Sopenharmony_ci			const ConstPixelBufferAccess	imgAccess		(vk::mapVkFormat(m_rtFormat), RENDER_WIDTH, RENDER_HEIGHT, 1, m_readImageMem[outNdx]->getHostPtr());
1636e5c31af7Sopenharmony_ci			const DataType					dataType		= m_spec.values.outputs[outNdx].type.getBasicType();
1637e5c31af7Sopenharmony_ci			const int						numComponents	= getDataTypeScalarSize(dataType);
1638e5c31af7Sopenharmony_ci			tcu::IVec4						reference		(0, 0, 0, 1);
1639e5c31af7Sopenharmony_ci
1640e5c31af7Sopenharmony_ci			for (int refNdx = 0; refNdx < numComponents; refNdx++)
1641e5c31af7Sopenharmony_ci			{
1642e5c31af7Sopenharmony_ci				if (isDataTypeFloatOrVec(dataType))
1643e5c31af7Sopenharmony_ci					reference[refNdx] = (int)m_spec.values.outputs[outNdx].elements[m_subCaseNdx * numComponents + refNdx].float32;
1644e5c31af7Sopenharmony_ci				else if (isDataTypeIntOrIVec(dataType))
1645e5c31af7Sopenharmony_ci					reference[refNdx] = m_spec.values.outputs[outNdx].elements[m_subCaseNdx * numComponents + refNdx].int32;
1646e5c31af7Sopenharmony_ci				else
1647e5c31af7Sopenharmony_ci					DE_FATAL("Unknown data type");
1648e5c31af7Sopenharmony_ci			}
1649e5c31af7Sopenharmony_ci
1650e5c31af7Sopenharmony_ci			invalidateAlloc(vkd, device, *m_readImageMem[outNdx]);
1651e5c31af7Sopenharmony_ci
1652e5c31af7Sopenharmony_ci			if (!checkResultImageWithReference(imgAccess, reference))
1653e5c31af7Sopenharmony_ci			{
1654e5c31af7Sopenharmony_ci				TestLog&	log		= m_context.getTestContext().getLog();
1655e5c31af7Sopenharmony_ci
1656e5c31af7Sopenharmony_ci				log << TestLog::Message << "ERROR: Got nonmatching pixels on sub-case " << m_subCaseNdx << " output " << outNdx << TestLog::EndMessage
1657e5c31af7Sopenharmony_ci					<< TestLog::Image("Result", "Result", imgAccess);
1658e5c31af7Sopenharmony_ci
1659e5c31af7Sopenharmony_ci				dumpValues(log, m_spec.values, m_subCaseNdx);
1660e5c31af7Sopenharmony_ci
1661e5c31af7Sopenharmony_ci				return TestStatus::fail(string("Got invalid pixels at sub-case ") + de::toString(m_subCaseNdx));
1662e5c31af7Sopenharmony_ci			}
1663e5c31af7Sopenharmony_ci		}
1664e5c31af7Sopenharmony_ci	}
1665e5c31af7Sopenharmony_ci
1666e5c31af7Sopenharmony_ci	if (++m_subCaseNdx < getNumSubCases(m_spec.values))
1667e5c31af7Sopenharmony_ci		return TestStatus::incomplete();
1668e5c31af7Sopenharmony_ci	else
1669e5c31af7Sopenharmony_ci		return TestStatus::pass("All sub-cases passed");
1670e5c31af7Sopenharmony_ci}
1671e5c31af7Sopenharmony_ci
1672e5c31af7Sopenharmony_ciclass ShaderCase : public TestCase
1673e5c31af7Sopenharmony_ci{
1674e5c31af7Sopenharmony_cipublic:
1675e5c31af7Sopenharmony_ci									ShaderCase		(tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec);
1676e5c31af7Sopenharmony_ci
1677e5c31af7Sopenharmony_ci
1678e5c31af7Sopenharmony_ci	void							initPrograms	(SourceCollections& programCollection) const;
1679e5c31af7Sopenharmony_ci	TestInstance*					createInstance	(Context& context) const;
1680e5c31af7Sopenharmony_ci
1681e5c31af7Sopenharmony_ciprivate:
1682e5c31af7Sopenharmony_ci	const ShaderCaseSpecification	m_spec;
1683e5c31af7Sopenharmony_ci};
1684e5c31af7Sopenharmony_ci
1685e5c31af7Sopenharmony_ciShaderCase::ShaderCase (tcu::TestContext& testCtx, const string& name, const string& description, const ShaderCaseSpecification& spec)
1686e5c31af7Sopenharmony_ci	: TestCase	(testCtx, name, description)
1687e5c31af7Sopenharmony_ci	, m_spec	(spec)
1688e5c31af7Sopenharmony_ci{
1689e5c31af7Sopenharmony_ci}
1690e5c31af7Sopenharmony_ci
1691e5c31af7Sopenharmony_civoid ShaderCase::initPrograms (SourceCollections& sourceCollection) const
1692e5c31af7Sopenharmony_ci{
1693e5c31af7Sopenharmony_ci	vector<ProgramSources>	specializedSources	(m_spec.programs.size());
1694e5c31af7Sopenharmony_ci
1695e5c31af7Sopenharmony_ci	DE_ASSERT(isValid(m_spec));
1696e5c31af7Sopenharmony_ci
1697e5c31af7Sopenharmony_ci	if (m_spec.expectResult != glu::sl::EXPECT_PASS)
1698e5c31af7Sopenharmony_ci		TCU_THROW(InternalError, "Only EXPECT_PASS is supported");
1699e5c31af7Sopenharmony_ci
1700e5c31af7Sopenharmony_ci	if (m_spec.caseType == glu::sl::CASETYPE_VERTEX_ONLY)
1701e5c31af7Sopenharmony_ci	{
1702e5c31af7Sopenharmony_ci		DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX].size() == 1);
1703e5c31af7Sopenharmony_ci		specializedSources[0] << glu::VertexSource(specializeVertexShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_VERTEX][0]))
1704e5c31af7Sopenharmony_ci							  << glu::FragmentSource(genFragmentShader(m_spec));
1705e5c31af7Sopenharmony_ci	}
1706e5c31af7Sopenharmony_ci	else if (m_spec.caseType == glu::sl::CASETYPE_FRAGMENT_ONLY)
1707e5c31af7Sopenharmony_ci	{
1708e5c31af7Sopenharmony_ci		DE_ASSERT(m_spec.programs.size() == 1 && m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT].size() == 1);
1709e5c31af7Sopenharmony_ci		specializedSources[0] << glu::VertexSource(genVertexShader(m_spec))
1710e5c31af7Sopenharmony_ci							  << glu::FragmentSource(specializeFragmentShader(m_spec, m_spec.programs[0].sources.sources[glu::SHADERTYPE_FRAGMENT][0]));
1711e5c31af7Sopenharmony_ci	}
1712e5c31af7Sopenharmony_ci	else
1713e5c31af7Sopenharmony_ci	{
1714e5c31af7Sopenharmony_ci		DE_ASSERT(m_spec.caseType == glu::sl::CASETYPE_COMPLETE);
1715e5c31af7Sopenharmony_ci
1716e5c31af7Sopenharmony_ci		const int	maxPatchVertices	= 4; // \todo [2015-08-05 pyry] Query
1717e5c31af7Sopenharmony_ci
1718e5c31af7Sopenharmony_ci		for (size_t progNdx = 0; progNdx < m_spec.programs.size(); progNdx++)
1719e5c31af7Sopenharmony_ci		{
1720e5c31af7Sopenharmony_ci			const ProgramSpecializationParams	progSpecParams	(m_spec, m_spec.programs[progNdx].requiredExtensions, maxPatchVertices);
1721e5c31af7Sopenharmony_ci
1722e5c31af7Sopenharmony_ci			specializeProgramSources(specializedSources[progNdx], m_spec.programs[progNdx].sources, progSpecParams);
1723e5c31af7Sopenharmony_ci		}
1724e5c31af7Sopenharmony_ci	}
1725e5c31af7Sopenharmony_ci
1726e5c31af7Sopenharmony_ci	for (size_t progNdx = 0; progNdx < specializedSources.size(); progNdx++)
1727e5c31af7Sopenharmony_ci	{
1728e5c31af7Sopenharmony_ci		for (int shaderType = 0; shaderType < glu::SHADERTYPE_LAST; shaderType++)
1729e5c31af7Sopenharmony_ci		{
1730e5c31af7Sopenharmony_ci			if (!specializedSources[progNdx].sources[shaderType].empty())
1731e5c31af7Sopenharmony_ci			{
1732e5c31af7Sopenharmony_ci				vk::GlslSource& curSrc	= sourceCollection.glslSources.add(getShaderName((glu::ShaderType)shaderType, progNdx));
1733e5c31af7Sopenharmony_ci				curSrc.sources[shaderType] = specializedSources[progNdx].sources[shaderType];
1734e5c31af7Sopenharmony_ci			}
1735e5c31af7Sopenharmony_ci		}
1736e5c31af7Sopenharmony_ci	}
1737e5c31af7Sopenharmony_ci}
1738e5c31af7Sopenharmony_ci
1739e5c31af7Sopenharmony_ciTestInstance* ShaderCase::createInstance (Context& context) const
1740e5c31af7Sopenharmony_ci{
1741e5c31af7Sopenharmony_ci	return new ShaderCaseInstance(context, m_spec);
1742e5c31af7Sopenharmony_ci}
1743e5c31af7Sopenharmony_ci
1744e5c31af7Sopenharmony_ciclass ShaderCaseFactory : public glu::sl::ShaderCaseFactory
1745e5c31af7Sopenharmony_ci{
1746e5c31af7Sopenharmony_cipublic:
1747e5c31af7Sopenharmony_ci	ShaderCaseFactory (tcu::TestContext& testCtx)
1748e5c31af7Sopenharmony_ci		: m_testCtx(testCtx)
1749e5c31af7Sopenharmony_ci	{
1750e5c31af7Sopenharmony_ci	}
1751e5c31af7Sopenharmony_ci
1752e5c31af7Sopenharmony_ci	tcu::TestCaseGroup* createGroup (const string& name, const string& description, const vector<tcu::TestNode*>& children)
1753e5c31af7Sopenharmony_ci	{
1754e5c31af7Sopenharmony_ci		return new tcu::TestCaseGroup(m_testCtx, name.c_str(), description.c_str(), children);
1755e5c31af7Sopenharmony_ci	}
1756e5c31af7Sopenharmony_ci
1757e5c31af7Sopenharmony_ci	tcu::TestCase* createCase (const string& name, const string& description, const ShaderCaseSpecification& spec)
1758e5c31af7Sopenharmony_ci	{
1759e5c31af7Sopenharmony_ci		return new ShaderCase(m_testCtx, name, description, spec);
1760e5c31af7Sopenharmony_ci	}
1761e5c31af7Sopenharmony_ci
1762e5c31af7Sopenharmony_ciprivate:
1763e5c31af7Sopenharmony_ci	tcu::TestContext&	m_testCtx;
1764e5c31af7Sopenharmony_ci};
1765e5c31af7Sopenharmony_ci
1766e5c31af7Sopenharmony_ciclass ShaderLibraryGroup : public tcu::TestCaseGroup
1767e5c31af7Sopenharmony_ci{
1768e5c31af7Sopenharmony_cipublic:
1769e5c31af7Sopenharmony_ci	ShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
1770e5c31af7Sopenharmony_ci		 : tcu::TestCaseGroup	(testCtx, name.c_str(), description.c_str())
1771e5c31af7Sopenharmony_ci		 , m_filename			(filename)
1772e5c31af7Sopenharmony_ci	{
1773e5c31af7Sopenharmony_ci	}
1774e5c31af7Sopenharmony_ci
1775e5c31af7Sopenharmony_ci	void init (void)
1776e5c31af7Sopenharmony_ci	{
1777e5c31af7Sopenharmony_ci		ShaderCaseFactory				caseFactory	(m_testCtx);
1778e5c31af7Sopenharmony_ci		const vector<tcu::TestNode*>	children	= glu::sl::parseFile(m_testCtx.getArchive(), m_filename, &caseFactory);
1779e5c31af7Sopenharmony_ci
1780e5c31af7Sopenharmony_ci		for (size_t ndx = 0; ndx < children.size(); ndx++)
1781e5c31af7Sopenharmony_ci		{
1782e5c31af7Sopenharmony_ci			try
1783e5c31af7Sopenharmony_ci			{
1784e5c31af7Sopenharmony_ci				addChild(children[ndx]);
1785e5c31af7Sopenharmony_ci			}
1786e5c31af7Sopenharmony_ci			catch (...)
1787e5c31af7Sopenharmony_ci			{
1788e5c31af7Sopenharmony_ci				for (; ndx < children.size(); ndx++)
1789e5c31af7Sopenharmony_ci					delete children[ndx];
1790e5c31af7Sopenharmony_ci				throw;
1791e5c31af7Sopenharmony_ci			}
1792e5c31af7Sopenharmony_ci		}
1793e5c31af7Sopenharmony_ci	}
1794e5c31af7Sopenharmony_ci
1795e5c31af7Sopenharmony_ciprivate:
1796e5c31af7Sopenharmony_ci	const string	m_filename;
1797e5c31af7Sopenharmony_ci};
1798e5c31af7Sopenharmony_ci
1799e5c31af7Sopenharmony_ci} // anonymous
1800e5c31af7Sopenharmony_ci
1801e5c31af7Sopenharmony_ciMovePtr<tcu::TestCaseGroup> createShaderLibraryGroup (tcu::TestContext& testCtx, const string& name, const string& description, const string& filename)
1802e5c31af7Sopenharmony_ci{
1803e5c31af7Sopenharmony_ci	return MovePtr<tcu::TestCaseGroup>(new ShaderLibraryGroup(testCtx, name, description, filename));
1804e5c31af7Sopenharmony_ci}
1805e5c31af7Sopenharmony_ci
1806e5c31af7Sopenharmony_ci} // vkt
1807