• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Texture test utilities.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktTextureTestUtil.hpp"
27 
28 #include "deFilePath.hpp"
29 #include "deMath.h"
30 #include "tcuCompressedTexture.hpp"
31 #include "tcuImageIO.hpp"
32 #include "tcuStringTemplate.hpp"
33 #include "tcuTestLog.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include <map>
41 #include <string>
42 #include <vector>
43 
44 using tcu::TestLog;
45 
46 using namespace vk;
47 using namespace glu::TextureTestUtil;
48 
49 namespace vkt
50 {
51 namespace texture
52 {
53 namespace util
54 {
55 
56 struct ShaderParameters {
57 	float		bias;				//!< User-supplied bias.
58 	float		ref;				//!< Reference value for shadow lookups.
59 	tcu::Vec2	padding;			//!< Shader uniform padding.
60 	tcu::Vec4	colorScale;			//!< Scale for texture color values.
61 	tcu::Vec4	colorBias;			//!< Bias for texture color values.
62 };
63 
getProgramName(Program program)64 const char* getProgramName(Program program)
65 {
66 	switch (program)
67 	{
68 		case PROGRAM_2D_FLOAT:			return "2D_FLOAT";
69 		case PROGRAM_2D_INT:			return "2D_INT";
70 		case PROGRAM_2D_UINT:			return "2D_UINT";
71 		case PROGRAM_2D_SHADOW:			return "2D_SHADOW";
72 		case PROGRAM_2D_FLOAT_BIAS:		return "2D_FLOAT_BIAS";
73 		case PROGRAM_2D_INT_BIAS:		return "2D_INT_BIAS";
74 		case PROGRAM_2D_UINT_BIAS:		return "2D_UINT_BIAS";
75 		case PROGRAM_2D_SHADOW_BIAS:	return "2D_SHADOW_BIAS";
76 		case PROGRAM_1D_FLOAT:			return "1D_FLOAT";
77 		case PROGRAM_1D_INT:			return "1D_INT";
78 		case PROGRAM_1D_UINT:			return "1D_UINT";
79 		case PROGRAM_1D_SHADOW:			return "1D_SHADOW";
80 		case PROGRAM_1D_FLOAT_BIAS:		return "1D_FLOAT_BIAS";
81 		case PROGRAM_1D_INT_BIAS:		return "1D_INT_BIAS";
82 		case PROGRAM_1D_UINT_BIAS:		return "1D_UINT_BIAS";
83 		case PROGRAM_1D_SHADOW_BIAS:	return "1D_SHADOW_BIAS";
84 		case PROGRAM_CUBE_FLOAT:		return "CUBE_FLOAT";
85 		case PROGRAM_CUBE_INT:			return "CUBE_INT";
86 		case PROGRAM_CUBE_UINT:			return "CUBE_UINT";
87 		case PROGRAM_CUBE_SHADOW:		return "CUBE_SHADOW";
88 		case PROGRAM_CUBE_FLOAT_BIAS:	return "CUBE_FLOAT_BIAS";
89 		case PROGRAM_CUBE_INT_BIAS:		return "CUBE_INT_BIAS";
90 		case PROGRAM_CUBE_UINT_BIAS:	return "CUBE_UINT_BIAS";
91 		case PROGRAM_CUBE_SHADOW_BIAS:	return "CUBE_SHADOW_BIAS";
92 		case PROGRAM_2D_ARRAY_FLOAT:	return "2D_ARRAY_FLOAT";
93 		case PROGRAM_2D_ARRAY_INT:		return "2D_ARRAY_INT";
94 		case PROGRAM_2D_ARRAY_UINT:		return "2D_ARRAY_UINT";
95 		case PROGRAM_2D_ARRAY_SHADOW:	return "2D_ARRAY_SHADOW";
96 		case PROGRAM_3D_FLOAT:			return "3D_FLOAT";
97 		case PROGRAM_3D_INT:			return "3D_INT";
98 		case PROGRAM_3D_UINT:			return "3D_UINT";
99 		case PROGRAM_3D_FLOAT_BIAS:		return "3D_FLOAT_BIAS";
100 		case PROGRAM_3D_INT_BIAS:		return "3D_INT_BIAS";
101 		case PROGRAM_3D_UINT_BIAS:		return "3D_UINT_BIAS";
102 		case PROGRAM_CUBE_ARRAY_FLOAT:	return "CUBE_ARRAY_FLOAT";
103 		case PROGRAM_CUBE_ARRAY_INT:	return "CUBE_ARRAY_INT";
104 		case PROGRAM_CUBE_ARRAY_UINT:	return "CUBE_ARRAY_UINT";
105 		case PROGRAM_CUBE_ARRAY_SHADOW:	return "CUBE_ARRAY_SHADOW";
106 		case PROGRAM_1D_ARRAY_FLOAT:	return "1D_ARRAY_FLOAT";
107 		case PROGRAM_1D_ARRAY_INT:		return "1D_ARRAY_INT";
108 		case PROGRAM_1D_ARRAY_UINT:		return "1D_ARRAY_UINT";
109 		case PROGRAM_1D_ARRAY_SHADOW:	return "1D_ARRAY_SHADOW";
110 		case PROGRAM_BUFFER_FLOAT:		return "BUFFER_FLOAT";
111 		case PROGRAM_BUFFER_INT:		return "BUFFER_INT";
112 		case PROGRAM_BUFFER_UINT:		return "BUFFER_UINT";
113 		default:
114 			DE_ASSERT(false);
115 	}
116 	return NULL;
117 }
118 
textureTypeToImageViewType(TextureBinding::Type type)119 VkImageViewType textureTypeToImageViewType (TextureBinding::Type type)
120 {
121 	switch (type)
122 	{
123 		case TextureBinding::TYPE_2D:			return VK_IMAGE_VIEW_TYPE_2D;
124 		case TextureBinding::TYPE_2D_ARRAY:		return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
125 		case TextureBinding::TYPE_CUBE_MAP:		return VK_IMAGE_VIEW_TYPE_CUBE;
126 		case TextureBinding::TYPE_3D:			return VK_IMAGE_VIEW_TYPE_3D;
127 		default:
128 			DE_ASSERT(false);
129 	}
130 
131 	return VK_IMAGE_VIEW_TYPE_2D;
132 }
133 
imageViewTypeToImageType(VkImageViewType type)134 VkImageType imageViewTypeToImageType (VkImageViewType type)
135 {
136 	switch (type)
137 	{
138 		case VK_IMAGE_VIEW_TYPE_2D:
139 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
140 		case VK_IMAGE_VIEW_TYPE_CUBE:			return VK_IMAGE_TYPE_2D;
141 		case VK_IMAGE_VIEW_TYPE_3D:				return VK_IMAGE_TYPE_3D;
142 		default:
143 			DE_ASSERT(false);
144 	}
145 
146 	return VK_IMAGE_TYPE_2D;
147 }
148 
initializePrograms(vk::SourceCollections & programCollection,glu::Precision texCoordPrecision,const std::vector<Program> & programs)149 void initializePrograms(vk::SourceCollections& programCollection, glu::Precision texCoordPrecision, const std::vector<Program>& programs)
150 {
151 	static const char* vertShaderTemplate =
152 		"${VTX_HEADER}"
153 		"layout(location = 0) ${VTX_IN} highp vec4 a_position;\n"
154 		"layout(location = 1) ${VTX_IN} ${PRECISION} ${TEXCOORD_TYPE} a_texCoord;\n"
155 		"layout(location = 0) ${VTX_OUT} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n"
156 		"${VTX_OUT} gl_PerVertex { vec4 gl_Position; };\n"
157 		"\n"
158 		"void main (void)\n"
159 		"{\n"
160 		"	gl_Position = a_position;\n"
161 		"	v_texCoord = a_texCoord;\n"
162 		"}\n";
163 
164 	static const char* fragShaderTemplate =
165 		"${FRAG_HEADER}"
166 		"layout(location = 0) ${FRAG_IN} ${PRECISION} ${TEXCOORD_TYPE} v_texCoord;\n"
167 		"layout(location = 0) out mediump vec4 ${FRAG_COLOR};\n"
168 		"layout (set=0, binding=0, std140) uniform Block \n"
169 		"{\n"
170 		"  ${PRECISION} float u_bias;\n"
171 		"  ${PRECISION} float u_ref;\n"
172 		"  ${PRECISION} vec4 u_colorScale;\n"
173 		"  ${PRECISION} vec4 u_colorBias;\n"
174 		"};\n\n"
175 		"layout (set=1, binding=0) uniform ${PRECISION} ${SAMPLER_TYPE} u_sampler;\n"
176 		"void main (void)\n"
177 		"{\n"
178 		"	${FRAG_COLOR} = ${LOOKUP} * u_colorScale + u_colorBias;\n"
179 		"}\n";
180 
181 	tcu::StringTemplate					vertexSource	(vertShaderTemplate);
182 	tcu::StringTemplate					fragmentSource	(fragShaderTemplate);
183 
184 	for (std::vector<Program>::const_iterator programIt = programs.begin(); programIt != programs.end(); ++programIt)
185 	{
186 		Program								program	= *programIt;
187 		std::map<std::string, std::string>	params;
188 
189 		bool	isCube		= de::inRange<int>(program, PROGRAM_CUBE_FLOAT, PROGRAM_CUBE_SHADOW_BIAS);
190 		bool	isArray		= de::inRange<int>(program, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_2D_ARRAY_SHADOW)
191 								|| de::inRange<int>(program, PROGRAM_1D_ARRAY_FLOAT, PROGRAM_1D_ARRAY_SHADOW);
192 
193 		bool	is1D		= de::inRange<int>(program, PROGRAM_1D_FLOAT, PROGRAM_1D_SHADOW_BIAS)
194 								|| de::inRange<int>(program, PROGRAM_1D_ARRAY_FLOAT, PROGRAM_1D_ARRAY_SHADOW)
195 								|| de::inRange<int>(program, PROGRAM_BUFFER_FLOAT, PROGRAM_BUFFER_UINT);
196 
197 		bool	is2D		= de::inRange<int>(program, PROGRAM_2D_FLOAT, PROGRAM_2D_SHADOW_BIAS)
198 								|| de::inRange<int>(program, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_2D_ARRAY_SHADOW);
199 
200 		bool	is3D		= de::inRange<int>(program, PROGRAM_3D_FLOAT, PROGRAM_3D_UINT_BIAS);
201 		bool	isCubeArray	= de::inRange<int>(program, PROGRAM_CUBE_ARRAY_FLOAT, PROGRAM_CUBE_ARRAY_SHADOW);
202 
203 		const std::string	version	= glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450);
204 
205 		params["FRAG_HEADER"]	= version + "\n";
206 		params["VTX_HEADER"]	= version + "\n";
207 		params["VTX_IN"]		= "in";
208 		params["VTX_OUT"]		= "out";
209 		params["FRAG_IN"]		= "in";
210 		params["FRAG_COLOR"]	= "dEQP_FragColor";
211 
212 		params["PRECISION"]		= glu::getPrecisionName(texCoordPrecision);
213 
214 		if (isCubeArray)
215 			params["TEXCOORD_TYPE"]	= "vec4";
216 		else if (isCube || (is2D && isArray) || is3D)
217 			params["TEXCOORD_TYPE"]	= "vec3";
218 		else if ((is1D && isArray) || is2D)
219 			params["TEXCOORD_TYPE"]	= "vec2";
220 		else if (is1D)
221 			params["TEXCOORD_TYPE"]	= "float";
222 		else
223 			DE_ASSERT(DE_FALSE);
224 
225 		const char*	sampler	= DE_NULL;
226 		const char*	lookup	= DE_NULL;
227 
228 		switch (program)
229 		{
230 			case PROGRAM_2D_FLOAT:			sampler = "sampler2D";				lookup = "texture(u_sampler, v_texCoord)";												break;
231 			case PROGRAM_2D_INT:			sampler = "isampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
232 			case PROGRAM_2D_UINT:			sampler = "usampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
233 			case PROGRAM_2D_SHADOW:			sampler = "sampler2DShadow";		lookup = "vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
234 			case PROGRAM_2D_FLOAT_BIAS:		sampler = "sampler2D";				lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
235 			case PROGRAM_2D_INT_BIAS:		sampler = "isampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
236 			case PROGRAM_2D_UINT_BIAS:		sampler = "usampler2D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
237 			case PROGRAM_2D_SHADOW_BIAS:	sampler = "sampler2DShadow";		lookup = "vec4(texture(u_sampler, vec3(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)";	break;
238 			case PROGRAM_1D_FLOAT:			sampler = "sampler1D";				lookup = "texture(u_sampler, v_texCoord)";												break;
239 			case PROGRAM_1D_INT:			sampler = "isampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
240 			case PROGRAM_1D_UINT:			sampler = "usampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
241 			case PROGRAM_1D_SHADOW:			sampler = "sampler1DShadow";		lookup = "vec4(texture(u_sampler, vec3(v_texCoord, 0.0, u_ref)), 0.0, 0.0, 1.0)";		break;
242 			case PROGRAM_1D_FLOAT_BIAS:		sampler = "sampler1D";				lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
243 			case PROGRAM_1D_INT_BIAS:		sampler = "isampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
244 			case PROGRAM_1D_UINT_BIAS:		sampler = "usampler1D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
245 			case PROGRAM_1D_SHADOW_BIAS:	sampler = "sampler1DShadow";		lookup = "vec4(texture(u_sampler, vec3(v_texCoord, 0.0, u_ref), u_bias), 0.0, 0.0, 1.0)";	break;
246 			case PROGRAM_CUBE_FLOAT:		sampler = "samplerCube";			lookup = "texture(u_sampler, v_texCoord)";												break;
247 			case PROGRAM_CUBE_INT:			sampler = "isamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
248 			case PROGRAM_CUBE_UINT:			sampler = "usamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
249 			case PROGRAM_CUBE_SHADOW:		sampler = "samplerCubeShadow";		lookup = "vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
250 			case PROGRAM_CUBE_FLOAT_BIAS:	sampler = "samplerCube";			lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
251 			case PROGRAM_CUBE_INT_BIAS:		sampler = "isamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
252 			case PROGRAM_CUBE_UINT_BIAS:	sampler = "usamplerCube";			lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
253 			case PROGRAM_CUBE_SHADOW_BIAS:	sampler = "samplerCubeShadow";		lookup = "vec4(texture(u_sampler, vec4(v_texCoord, u_ref), u_bias), 0.0, 0.0, 1.0)";	break;
254 			case PROGRAM_2D_ARRAY_FLOAT:	sampler = "sampler2DArray";			lookup = "texture(u_sampler, v_texCoord)";												break;
255 			case PROGRAM_2D_ARRAY_INT:		sampler = "isampler2DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
256 			case PROGRAM_2D_ARRAY_UINT:		sampler = "usampler2DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
257 			case PROGRAM_2D_ARRAY_SHADOW:	sampler = "sampler2DArrayShadow";	lookup = "vec4(texture(u_sampler, vec4(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
258 			case PROGRAM_3D_FLOAT:			sampler = "sampler3D";				lookup = "texture(u_sampler, v_texCoord)";												break;
259 			case PROGRAM_3D_INT:			sampler = "isampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
260 			case PROGRAM_3D_UINT:			sampler = "usampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
261 			case PROGRAM_3D_FLOAT_BIAS:		sampler = "sampler3D";				lookup = "texture(u_sampler, v_texCoord, u_bias)";										break;
262 			case PROGRAM_3D_INT_BIAS:		sampler = "isampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
263 			case PROGRAM_3D_UINT_BIAS:		sampler = "usampler3D";				lookup = "vec4(texture(u_sampler, v_texCoord, u_bias))";								break;
264 			case PROGRAM_CUBE_ARRAY_FLOAT:	sampler = "samplerCubeArray";		lookup = "texture(u_sampler, v_texCoord)";												break;
265 			case PROGRAM_CUBE_ARRAY_INT:	sampler = "isamplerCubeArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
266 			case PROGRAM_CUBE_ARRAY_UINT:	sampler = "usamplerCubeArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
267 			case PROGRAM_CUBE_ARRAY_SHADOW:	sampler = "samplerCubeArrayShadow";	lookup = "vec4(texture(u_sampler, v_texCoord, u_ref), 0.0, 0.0, 1.0)";			break;
268 			case PROGRAM_1D_ARRAY_FLOAT:	sampler = "sampler1DArray";			lookup = "texture(u_sampler, v_texCoord)";												break;
269 			case PROGRAM_1D_ARRAY_INT:		sampler = "isampler1DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
270 			case PROGRAM_1D_ARRAY_UINT:		sampler = "usampler1DArray";		lookup = "vec4(texture(u_sampler, v_texCoord))";										break;
271 			case PROGRAM_1D_ARRAY_SHADOW:	sampler = "sampler1DArrayShadow";	lookup = "vec4(texture(u_sampler, vec3(v_texCoord, u_ref)), 0.0, 0.0, 1.0)";			break;
272 			case PROGRAM_BUFFER_FLOAT:		sampler = "samplerBuffer";			lookup = "texelFetch(u_sampler, int(v_texCoord))";										break;
273 			case PROGRAM_BUFFER_INT:		sampler = "isamplerBuffer";			lookup = "vec4(texelFetch(u_sampler, int(v_texCoord)))";								break;
274 			case PROGRAM_BUFFER_UINT:		sampler = "usamplerBuffer";			lookup = "vec4(texelFetch(u_sampler, int(v_texCoord)))";								break;
275 			default:
276 				DE_ASSERT(false);
277 		}
278 
279 		params["SAMPLER_TYPE"]	= sampler;
280 		params["LOOKUP"]		= lookup;
281 
282 		programCollection.glslSources.add("vertext_" + std::string(getProgramName(program))) << glu::VertexSource(vertexSource.specialize(params));
283 		programCollection.glslSources.add("fragment_" + std::string(getProgramName(program))) << glu::FragmentSource(fragmentSource.specialize(params));
284 	}
285 }
286 
TextureBinding(Context & context)287 TextureBinding::TextureBinding (Context& context)
288 	: m_context			(context)
289 {
290 }
291 
TextureBinding(Context & context,const TestTextureSp & textureData,const TextureBinding::Type type)292 TextureBinding::TextureBinding (Context& context, const TestTextureSp& textureData, const TextureBinding::Type type)
293 	: m_context			(context)
294 	, m_type			(type)
295 	, m_textureData		(textureData)
296 {
297 	updateTextureData(m_textureData, m_type);
298 }
299 
updateTextureData(const TestTextureSp & textureData,const TextureBinding::Type textureType)300 void TextureBinding::updateTextureData (const TestTextureSp& textureData, const TextureBinding::Type textureType)
301 {
302 	const DeviceInterface&						vkd						= m_context.getDeviceInterface();
303 	const VkDevice								vkDevice				= m_context.getDevice();
304 	const VkQueue								queue					= m_context.getUniversalQueue();
305 	const deUint32								queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
306 	Allocator&									allocator				= m_context.getDefaultAllocator();
307 
308 	m_type			= textureType;
309 	m_textureData	= textureData;
310 
311 	const bool									isCube					= m_type == TYPE_CUBE_MAP;
312 	const VkImageCreateFlags					imageCreateFlags		= isCube ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
313 	const VkImageViewType						imageViewType			= textureTypeToImageViewType(textureType);
314 	const VkImageType							imageType				= imageViewTypeToImageType(imageViewType);
315 	const VkImageTiling							imageTiling				= VK_IMAGE_TILING_OPTIMAL;
316 	const VkImageUsageFlags						imageUsageFlags			= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
317 	const VkFormat								format					= mapTextureFormat(textureData->getTextureFormat());
318 	const tcu::UVec3							textureDimension		= textureData->getTextureDimension();
319 	const deUint32								mipLevels				= textureData->getNumLevels();
320 	const deUint32								arraySize				= textureData->getArraySize();
321 	vk::VkImageFormatProperties					imageFormatProperties;
322 	const VkResult								imageFormatQueryResult	= m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(), format, imageType, imageTiling, imageUsageFlags, imageCreateFlags, &imageFormatProperties);
323 
324 	if (imageFormatQueryResult == VK_ERROR_FORMAT_NOT_SUPPORTED)
325 	{
326 		TCU_THROW(NotSupportedError, (std::string("Format not supported: ") + vk::getFormatName(format)).c_str());
327 	}
328 	else
329 		VK_CHECK(imageFormatQueryResult);
330 
331 	if (imageFormatProperties.maxArrayLayers < arraySize)
332 		TCU_THROW(NotSupportedError, ("Maximum array layers number for this format is not enough for this test."));
333 
334 	if (imageFormatProperties.maxMipLevels < mipLevels)
335 		TCU_THROW(NotSupportedError, ("Maximum mimap level number for this format is not enough for this test."));
336 
337 	if (imageFormatProperties.maxExtent.width < textureDimension.x() ||
338 		imageFormatProperties.maxExtent.height < textureDimension.y() ||
339 		imageFormatProperties.maxExtent.depth < textureDimension.z())
340 	{
341 		TCU_THROW(NotSupportedError, ("Maximum image dimension for this format is not enough for this test."));
342 	}
343 
344 	// Create image
345 	const VkImageCreateInfo						imageParams				=
346 	{
347 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType;
348 		DE_NULL,														// const void*				pNext;
349 		imageCreateFlags,												// VkImageCreateFlags		flags;
350 		imageType,														// VkImageType				imageType;
351 		format,															// VkFormat					format;
352 		{																// VkExtent3D				extent;
353 			(deUint32)textureDimension.x(),
354 			(deUint32)textureDimension.y(),
355 			(deUint32)textureDimension.z()
356 		},
357 		mipLevels,														// deUint32					mipLevels;
358 		arraySize,														// deUint32					arrayLayers;
359 		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits	samples;
360 		imageTiling,													// VkImageTiling			tiling;
361 		imageUsageFlags,												// VkImageUsageFlags		usage;
362 		VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharingMode;
363 		1u,																// deUint32					queueFamilyIndexCount;
364 		&queueFamilyIndex,												// const deUint32*			pQueueFamilyIndices;
365 		VK_IMAGE_LAYOUT_UNDEFINED										// VkImageLayout			initialLayout;
366 	};
367 
368 	m_textureImage			= createImage(vkd, vkDevice, &imageParams);
369 	m_textureImageMemory	= allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_textureImage), MemoryRequirement::Any);
370 	VK_CHECK(vkd.bindImageMemory(vkDevice, *m_textureImage, m_textureImageMemory->getMemory(), m_textureImageMemory->getOffset()));
371 
372 	updateTextureViewMipLevels(0, mipLevels - 1);
373 
374 	pipeline::uploadTestTexture(vkd, vkDevice, queue, queueFamilyIndex, allocator, *m_textureData, *m_textureImage);
375 }
376 
updateTextureViewMipLevels(deUint32 baseLevel,deUint32 maxLevel)377 void TextureBinding::updateTextureViewMipLevels (deUint32 baseLevel, deUint32 maxLevel)
378 {
379 	const DeviceInterface&						vkd						= m_context.getDeviceInterface();
380 	const VkDevice								vkDevice				= m_context.getDevice();
381 	const vk::VkImageViewType					imageViewType			= textureTypeToImageViewType(m_type);
382 	const vk::VkFormat							format					= mapTextureFormat(m_textureData->getTextureFormat());
383 	const bool									isShadowTexture			= tcu::hasDepthComponent(m_textureData->getTextureFormat().order);
384 	const VkImageAspectFlags					aspectMask				= isShadowTexture ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
385 	const deUint32								layerCount				= m_textureData->getArraySize();
386 	const vk::VkImageViewCreateInfo				viewParams				=
387 	{
388 		vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
389 		NULL,											// const voide*				pNext;
390 		0u,												// VkImageViewCreateFlags	flags;
391 		*m_textureImage,								// VkImage					image;
392 		imageViewType,									// VkImageViewType			viewType;
393 		format,											// VkFormat					format;
394 		makeComponentMappingRGBA(),						// VkComponentMapping		components;
395 		{
396 			aspectMask,									// VkImageAspectFlags	aspectMask;
397 			baseLevel,									// deUint32				baseMipLevel;
398 			maxLevel-baseLevel+1,						// deUint32				levelCount;
399 			0,											// deUint32				baseArrayLayer;
400 			layerCount									// deUint32				layerCount;
401 		},												// VkImageSubresourceRange	subresourceRange;
402 	};
403 
404 	m_textureImageView		= createImageView(vkd, vkDevice, &viewParams);
405 }
406 
407 const deUint16		TextureRenderer::s_vertexIndices[6] = { 0, 1, 2, 2, 1, 3 };
408 const VkDeviceSize	TextureRenderer::s_vertexIndexBufferSize = sizeof(TextureRenderer::s_vertexIndices);
409 
TextureRenderer(Context & context,VkSampleCountFlagBits sampleCount,deUint32 renderWidth,deUint32 renderHeight)410 TextureRenderer::TextureRenderer (Context& context, VkSampleCountFlagBits sampleCount, deUint32 renderWidth, deUint32 renderHeight)
411 	: m_context					(context)
412 	, m_log						(context.getTestContext().getLog())
413 	, m_renderWidth				(renderWidth)
414 	, m_renderHeight			(renderHeight)
415 	, m_sampleCount				(sampleCount)
416 	, m_multisampling			(m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
417 	, m_imageFormat				(VK_FORMAT_R8G8B8A8_UNORM)
418 	, m_textureFormat			(vk::mapVkFormat(m_imageFormat))
419 	, m_uniformBufferSize		(sizeof(ShaderParameters))
420 	, m_resultBufferSize		(renderWidth * renderHeight * m_textureFormat.getPixelSize())
421 	, m_viewportOffsetX			(0.0f)
422 	, m_viewportOffsetY			(0.0f)
423 	, m_viewportWidth			((float)renderWidth)
424 	, m_viewportHeight			((float)renderHeight)
425 {
426 	const DeviceInterface&						vkd						= m_context.getDeviceInterface();
427 	const VkDevice								vkDevice				= m_context.getDevice();
428 	const deUint32								queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
429 	Allocator&									allocator				= m_context.getDefaultAllocator();
430 
431 	// Command Pool
432 	{
433 		const VkCommandPoolCreateInfo			cmdPoolCreateInfo		=
434 		{
435 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,					// VkStructureType             sType;
436 			DE_NULL,													// const void*                 pNext;
437 			VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,			// VkCommandPoolCreateFlags    flags;
438 			queueFamilyIndex											// deUint32                    queueFamilyIndex;
439 		};
440 
441 		m_commandPool = createCommandPool(vkd, vkDevice, &cmdPoolCreateInfo, DE_NULL);
442 	}
443 
444 	// Image
445 	{
446 		const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
447 		VkImageFormatProperties	properties;
448 
449 		if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
450 																					 m_imageFormat,
451 																					 VK_IMAGE_TYPE_2D,
452 																					 VK_IMAGE_TILING_OPTIMAL,
453 																					 imageUsage,
454 																					 0,
455 																					 &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
456 		{
457 			TCU_THROW(NotSupportedError, "Format not supported");
458 		}
459 
460 		if ((properties.sampleCounts & m_sampleCount) != m_sampleCount)
461 		{
462 			TCU_THROW(NotSupportedError, "Format not supported");
463 		}
464 
465 		const VkImageCreateInfo					imageCreateInfo			=
466 		{
467 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
468 			DE_NULL,									// const void*				pNext;
469 			0u,											// VkImageCreateFlags		flags;
470 			VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
471 			m_imageFormat,								// VkFormat					format;
472 			{ m_renderWidth, m_renderHeight, 1u },		// VkExtent3D				extent;
473 			1u,											// deUint32					mipLevels;
474 			1u,											// deUint32					arrayLayers;
475 			m_sampleCount,								// VkSampleCountFlagBits	samples;
476 			VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
477 			imageUsage,									// VkImageUsageFlags		usage;
478 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
479 			1u,											// deUint32					queueFamilyIndexCount;
480 			&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
481 			VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
482 		};
483 
484 		m_image = vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
485 
486 		m_imageMemory	= allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_image), MemoryRequirement::Any);
487 		VK_CHECK(vkd.bindImageMemory(vkDevice, *m_image, m_imageMemory->getMemory(), m_imageMemory->getOffset()));
488 	}
489 
490 	// Image View
491 	{
492 		const VkImageViewCreateInfo				imageViewCreateInfo		=
493 		{
494 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
495 			DE_NULL,									// const void*					pNext;
496 			0u,											// VkImageViewCreateFlags		flags;
497 			*m_image,									// VkImage						image;
498 			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
499 			m_imageFormat,								// VkFormat						format;
500 			makeComponentMappingRGBA(),					// VkComponentMapping			components;
501 			{
502 				VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
503 				0u,											// deUint32						baseMipLevel;
504 				1u,											// deUint32						mipLevels;
505 				0u,											// deUint32						baseArrayLayer;
506 				1u,											// deUint32						arraySize;
507 			},											// VkImageSubresourceRange		subresourceRange;
508 		};
509 
510 		m_imageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
511 	}
512 
513 	if (m_multisampling)
514 	{
515 		{
516 			// Resolved Image
517 			const VkImageUsageFlags	imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
518 			VkImageFormatProperties	properties;
519 
520 			if ((m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
521 																						 m_imageFormat,
522 																						 VK_IMAGE_TYPE_2D,
523 																						 VK_IMAGE_TILING_OPTIMAL,
524 																						 imageUsage,
525 																						 0,
526 																						 &properties) == VK_ERROR_FORMAT_NOT_SUPPORTED))
527 			{
528 				TCU_THROW(NotSupportedError, "Format not supported");
529 			}
530 
531 			const VkImageCreateInfo					imageCreateInfo			=
532 			{
533 				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
534 				DE_NULL,									// const void*				pNext;
535 				0u,											// VkImageCreateFlags		flags;
536 				VK_IMAGE_TYPE_2D,							// VkImageType				imageType;
537 				m_imageFormat,								// VkFormat					format;
538 				{ m_renderWidth, m_renderHeight, 1u },		// VkExtent3D				extent;
539 				1u,											// deUint32					mipLevels;
540 				1u,											// deUint32					arrayLayers;
541 				VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples;
542 				VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
543 				imageUsage,									// VkImageUsageFlags		usage;
544 				VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
545 				1u,											// deUint32					queueFamilyIndexCount;
546 				&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices;
547 				VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout;
548 			};
549 
550 			m_resolvedImage			= vk::createImage(vkd, vkDevice, &imageCreateInfo, DE_NULL);
551 			m_resolvedImageMemory	= allocator.allocate(getImageMemoryRequirements(vkd, vkDevice, *m_resolvedImage), MemoryRequirement::Any);
552 			VK_CHECK(vkd.bindImageMemory(vkDevice, *m_resolvedImage, m_resolvedImageMemory->getMemory(), m_resolvedImageMemory->getOffset()));
553 		}
554 
555 		// Resolved Image View
556 		{
557 			const VkImageViewCreateInfo				imageViewCreateInfo		=
558 			{
559 				VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType				sType;
560 				DE_NULL,									// const void*					pNext;
561 				0u,											// VkImageViewCreateFlags		flags;
562 				*m_resolvedImage,							// VkImage						image;
563 				VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType				viewType;
564 				m_imageFormat,								// VkFormat						format;
565 				makeComponentMappingRGBA(),					// VkComponentMapping			components;
566 				{
567 					VK_IMAGE_ASPECT_COLOR_BIT,					// VkImageAspectFlags			aspectMask;
568 					0u,											// deUint32						baseMipLevel;
569 					1u,											// deUint32						mipLevels;
570 					0u,											// deUint32						baseArrayLayer;
571 					1u,											// deUint32						arraySize;
572 				},											// VkImageSubresourceRange		subresourceRange;
573 			};
574 
575 			m_resolvedImageView = vk::createImageView(vkd, vkDevice, &imageViewCreateInfo, DE_NULL);
576 		}
577 	}
578 
579 	// Render Pass
580 	{
581 		const VkImageLayout						imageLayout				= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
582 		const VkAttachmentDescription			attachmentDesc[]		=
583 		{
584 			{
585 				0u,													// VkAttachmentDescriptionFlags		flags;
586 				m_imageFormat,										// VkFormat							format;
587 				m_sampleCount,										// VkSampleCountFlagBits			samples;
588 				VK_ATTACHMENT_LOAD_OP_LOAD,												// VkAttachmentLoadOp				loadOp;
589 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
590 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
591 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
592 				imageLayout,										// VkImageLayout					initialLayout;
593 				imageLayout,										// VkImageLayout					finalLayout;
594 			},
595 			{
596 				0u,													// VkAttachmentDescriptionFlags		flags;
597 				m_imageFormat,										// VkFormat							format;
598 				VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
599 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				loadOp;
600 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
601 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
602 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
603 				imageLayout,										// VkImageLayout					initialLayout;
604 				imageLayout,										// VkImageLayout					finalLayout;
605 			}
606 		};
607 
608 		const VkAttachmentReference				attachmentRef			=
609 		{
610 			0u,													// deUint32							attachment;
611 			imageLayout,										// VkImageLayout					layout;
612 		};
613 
614 		const VkAttachmentReference				resolveAttachmentRef	=
615 		{
616 			1u,													// deUint32							attachment;
617 			imageLayout,										// VkImageLayout					layout;
618 		};
619 
620 		const VkSubpassDescription				subpassDesc				=
621 		{
622 			0u,													// VkSubpassDescriptionFlags		flags;
623 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
624 			0u,													// deUint32							inputAttachmentCount;
625 			DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
626 			1u,													// deUint32							colorAttachmentCount;
627 			&attachmentRef,										// const VkAttachmentReference*		pColorAttachments;
628 			m_multisampling ? &resolveAttachmentRef : DE_NULL,	// const VkAttachmentReference*		pResolveAttachments;
629 			DE_NULL,											// const VkAttachmentReference*		pDepthStencilAttachment;
630 			0u,													// deUint32							preserveAttachmentCount;
631 			DE_NULL,											// const VkAttachmentReference*		pPreserveAttachments;
632 		};
633 
634 		const VkRenderPassCreateInfo			renderPassCreateInfo	=
635 		{
636 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
637 			DE_NULL,											// const void*						pNext;
638 			0u,													// VkRenderPassCreateFlags			flags;
639 			m_multisampling ? 2u : 1u,							// deUint32							attachmentCount;
640 			attachmentDesc,										// const VkAttachmentDescription*	pAttachments;
641 			1u,													// deUint32							subpassCount;
642 			&subpassDesc,										// const VkSubpassDescription*		pSubpasses;
643 			0u,													// deUint32							dependencyCount;
644 			DE_NULL,											// const VkSubpassDependency*		pDependencies;
645 		};
646 
647 		m_renderPass =  createRenderPass(vkd, vkDevice, &renderPassCreateInfo, DE_NULL);
648 	}
649 
650 	// Vertex index buffer
651 	{
652 		const VkBufferCreateInfo			indexBufferParams		=
653 		{
654 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
655 			DE_NULL,									// const void*			pNext;
656 			0u,											// VkBufferCreateFlags	flags;
657 			s_vertexIndexBufferSize,					// VkDeviceSize			size;
658 			VK_BUFFER_USAGE_INDEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
659 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
660 			1u,											// deUint32				queueFamilyCount;
661 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
662 		};
663 
664 		m_vertexIndexBuffer			= createBuffer(vkd, vkDevice, &indexBufferParams);
665 		m_vertexIndexBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_vertexIndexBuffer), MemoryRequirement::HostVisible);
666 
667 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_vertexIndexBuffer, m_vertexIndexBufferMemory->getMemory(), m_vertexIndexBufferMemory->getOffset()));
668 
669 		// Load vertices into vertex buffer
670 		deMemcpy(m_vertexIndexBufferMemory->getHostPtr(), s_vertexIndices, s_vertexIndexBufferSize);
671 		flushMappedMemoryRange(vkd, vkDevice, m_vertexIndexBufferMemory->getMemory(), m_vertexIndexBufferMemory->getOffset(), VK_WHOLE_SIZE);
672 	}
673 
674 	// FrameBuffer
675 	{
676 		const VkImageView						attachments[]			=
677 		{
678 			*m_imageView,
679 			*m_resolvedImageView,
680 		};
681 
682 		const VkFramebufferCreateInfo			framebufferCreateInfo	=
683 		{
684 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
685 			DE_NULL,									// const void*				pNext;
686 			0u,											// VkFramebufferCreateFlags	flags;
687 			*m_renderPass,								// VkRenderPass				renderPass;
688 			m_multisampling ? 2u : 1u,					// deUint32					attachmentCount;
689 			attachments,								// const VkImageView*		pAttachments;
690 			m_renderWidth,								// deUint32					width;
691 			m_renderHeight,								// deUint32					height;
692 			1u,											// deUint32					layers;
693 		};
694 
695 		m_frameBuffer = createFramebuffer(vkd, vkDevice, &framebufferCreateInfo, DE_NULL);
696 	}
697 
698 	// Uniform Buffer
699 	{
700 		const VkBufferCreateInfo				bufferCreateInfo		=
701 		{
702 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
703 			DE_NULL,									// const void*			pNext;
704 			0u,											// VkBufferCreateFlags	flags;
705 			m_uniformBufferSize,						// VkDeviceSize			size;
706 			VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,			// VkBufferUsageFlags	usage;
707 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
708 			1u,											// deUint32				queueFamilyIndexCount;
709 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
710 		};
711 
712 		m_uniformBuffer			= createBuffer(vkd, vkDevice, &bufferCreateInfo);
713 		m_uniformBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
714 
715 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset()));
716 	}
717 
718 	// DescriptorPool
719 	{
720 		DescriptorPoolBuilder					descriptorPoolBuilder;
721 
722 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
723 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
724 		m_descriptorPool = descriptorPoolBuilder.build(vkd, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u);
725 	}
726 
727 	// Fence
728 	{
729 		const VkFenceCreateInfo					fenceParams					=
730 		{
731 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	// VkStructureType		sType;
732 			DE_NULL,								// const void*			pNext;
733 			VK_FENCE_CREATE_SIGNALED_BIT			// VkFenceCreateFlags	flags;
734 		};
735 
736 		m_fence = createFence(vkd, vkDevice, &fenceParams);
737 	}
738 
739 	// Result Buffer
740 	{
741 		const VkBufferCreateInfo				bufferCreateInfo		=
742 		{
743 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
744 			DE_NULL,									// const void*			pNext;
745 			0u,											// VkBufferCreateFlags	flags;
746 			m_resultBufferSize,							// VkDeviceSize			size;
747 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
748 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
749 			1u,											// deUint32				queueFamilyIndexCount;
750 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
751 		};
752 
753 		m_resultBuffer			= createBuffer(vkd, vkDevice, &bufferCreateInfo);
754 		m_resultBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
755 
756 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset()));
757 	}
758 
759 	clearImage(*m_image);
760 	if(m_multisampling)
761 		clearImage(*m_resolvedImage);
762 }
763 
~TextureRenderer(void)764 TextureRenderer::~TextureRenderer (void)
765 {
766 }
767 
clearImage(VkImage image)768 void TextureRenderer::clearImage(VkImage image)
769 {
770 	const DeviceInterface&			vkd					= m_context.getDeviceInterface();
771 	const VkDevice					vkDevice			= m_context.getDevice();
772 	Move<VkCommandBuffer>			commandBuffer;
773 	const VkQueue					queue				= m_context.getUniversalQueue();
774 
775 	const VkImageSubresourceRange	subResourcerange	=
776 	{
777 		VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
778 		0,								// deUint32				baseMipLevel;
779 		1,								// deUint32				levelCount;
780 		0,								// deUint32				baseArrayLayer;
781 		1								// deUint32				layerCount;
782 	};
783 
784 	const VkCommandBufferAllocateInfo		cmdBufferAllocateInfo	=
785 	{
786 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// VkStructureType             sType;
787 		DE_NULL,													// const void*                 pNext;
788 		*m_commandPool,												// VkCommandPool               commandPool;
789 		VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// VkCommandBufferLevel        level;
790 		1															// deUint32                    commandBufferCount;
791 	};
792 
793 	commandBuffer = allocateCommandBuffer(vkd, vkDevice, &cmdBufferAllocateInfo);
794 
795 	const VkCommandBufferBeginInfo		cmdBufferBeginInfo		=
796 	{
797 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType							sType;
798 		DE_NULL,										// const void*								pNext;
799 		0u,												// VkCmdBufferOptimizeFlags					flags;
800 		DE_NULL											// const VkCommandBufferInheritanceInfo*	pInheritanceInfo;
801 	};
802 
803 	VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &cmdBufferBeginInfo));
804 
805 	addImageTransitionBarrier(*commandBuffer, image,
806 							  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags		srcStageMask
807 							  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,				// VkPipelineStageFlags		dstStageMask
808 							  0,												// VkAccessFlags			srcAccessMask
809 							  VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			dstAccessMask
810 							  VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
811 							  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);			// VkImageLayout			newLayout;
812 
813 	VkClearColorValue color = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f).color;
814 	vkd.cmdClearColorImage(*commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &subResourcerange);
815 
816 	addImageTransitionBarrier(*commandBuffer, image,
817 							  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// VkPipelineStageFlags		srcStageMask
818 							  VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,				// VkPipelineStageFlags		dstStageMask
819 							  VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			srcAccessMask
820 							  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask
821 							  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			oldLayout;
822 							  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);		// VkImageLayout			newLayout;
823 
824 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
825 
826 	const VkSubmitInfo					submitInfo				=
827 	{
828 		VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType				sType;
829 		DE_NULL,								// const void*					pNext;
830 		0u,										// deUint32						waitSemaphoreCount;
831 		DE_NULL,								// const VkSemaphore*			pWaitSemaphores;
832 		DE_NULL,								// const VkPipelineStageFlags*	pWaitDstStageMask;
833 		1u,										// deUint32						commandBufferCount;
834 		&commandBuffer.get(),					// const VkCommandBuffer*		pCommandBuffers;
835 		0u,										// deUint32						signalSemaphoreCount;
836 		DE_NULL,								// const VkSemaphore*			pSignalSemaphores;
837 	};
838 
839 	VK_CHECK(vkd.resetFences(vkDevice, 1, &m_fence.get()));
840 	VK_CHECK(vkd.queueSubmit(queue, 1, &submitInfo, *m_fence));
841 	VK_CHECK(vkd.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
842 }
843 
add2DTexture(const TestTexture2DSp & texture)844 void TextureRenderer::add2DTexture (const TestTexture2DSp& texture)
845 {
846 	m_textureBindings.push_back(TextureBindingSp(new TextureBinding(m_context, texture, TextureBinding::TYPE_2D)));
847 }
848 
addCubeTexture(const TestTextureCubeSp & texture)849 void TextureRenderer::addCubeTexture (const TestTextureCubeSp& texture)
850 {
851 	m_textureBindings.push_back(TextureBindingSp(new TextureBinding(m_context, texture, TextureBinding::TYPE_CUBE_MAP)));
852 }
853 
add2DArrayTexture(const TestTexture2DArraySp & texture)854 void TextureRenderer::add2DArrayTexture (const TestTexture2DArraySp& texture)
855 {
856 	m_textureBindings.push_back(TextureBindingSp(new TextureBinding(m_context, texture, TextureBinding::TYPE_2D_ARRAY)));
857 }
858 
add3DTexture(const TestTexture3DSp & texture)859 void TextureRenderer::add3DTexture (const TestTexture3DSp& texture)
860 {
861 	m_textureBindings.push_back(TextureBindingSp(new TextureBinding(m_context, texture, TextureBinding::TYPE_3D)));
862 }
863 
get2DTexture(int textureIndex) const864 const pipeline::TestTexture2D& TextureRenderer::get2DTexture (int textureIndex) const
865 {
866 	DE_ASSERT(m_textureBindings.size() > (size_t)textureIndex);
867 	DE_ASSERT(m_textureBindings[textureIndex]->getType() == TextureBinding::TYPE_2D);
868 
869 	return dynamic_cast<const pipeline::TestTexture2D&>(m_textureBindings[textureIndex]->getTestTexture());
870 }
871 
getCubeTexture(int textureIndex) const872 const pipeline::TestTextureCube& TextureRenderer::getCubeTexture (int textureIndex) const
873 {
874 	DE_ASSERT(m_textureBindings.size() > (size_t)textureIndex);
875 	DE_ASSERT(m_textureBindings[textureIndex]->getType() == TextureBinding::TYPE_CUBE_MAP);
876 
877 	return dynamic_cast<const pipeline::TestTextureCube&>(m_textureBindings[textureIndex]->getTestTexture());
878 }
879 
get2DArrayTexture(int textureIndex) const880 const pipeline::TestTexture2DArray& TextureRenderer::get2DArrayTexture (int textureIndex) const
881 {
882 	DE_ASSERT(m_textureBindings.size() > (size_t)textureIndex);
883 	DE_ASSERT(m_textureBindings[textureIndex]->getType() == TextureBinding::TYPE_2D_ARRAY);
884 
885 	return dynamic_cast<const pipeline::TestTexture2DArray&>(m_textureBindings[textureIndex]->getTestTexture());
886 }
887 
get3DTexture(int textureIndex) const888 const pipeline::TestTexture3D& TextureRenderer::get3DTexture (int textureIndex) const
889 {
890 	DE_ASSERT(m_textureBindings.size() > (size_t)textureIndex);
891 	DE_ASSERT(m_textureBindings[textureIndex]->getType() == TextureBinding::TYPE_3D);
892 
893 	return dynamic_cast<const pipeline::TestTexture3D&>(m_textureBindings[textureIndex]->getTestTexture());
894 }
895 
setViewport(float viewportX,float viewportY,float viewportW,float viewportH)896 void TextureRenderer::setViewport (float viewportX, float viewportY, float viewportW, float viewportH)
897 {
898 	m_viewportHeight = viewportH;
899 	m_viewportWidth = viewportW;
900 	m_viewportOffsetX = viewportX;
901 	m_viewportOffsetY = viewportY;
902 }
903 
getTextureBinding(int textureIndex) const904 TextureBinding* TextureRenderer::getTextureBinding (int textureIndex) const
905 {
906 	DE_ASSERT(m_textureBindings.size() > (size_t)textureIndex);
907 	return m_textureBindings[textureIndex].get();
908 }
909 
getRenderWidth(void) const910 deUint32 TextureRenderer::getRenderWidth (void) const
911 {
912 	return m_renderWidth;
913 }
914 
getRenderHeight(void) const915 deUint32 TextureRenderer::getRenderHeight (void) const
916 {
917 	return m_renderHeight;
918 }
919 
makeDescriptorSet(const VkDescriptorPool descriptorPool,const VkDescriptorSetLayout setLayout) const920 Move<VkDescriptorSet> TextureRenderer::makeDescriptorSet (const VkDescriptorPool descriptorPool, const VkDescriptorSetLayout setLayout) const
921 {
922 	const DeviceInterface&						vkd						= m_context.getDeviceInterface();
923 	const VkDevice								vkDevice				= m_context.getDevice();
924 
925 	const VkDescriptorSetAllocateInfo			allocateParams			=
926 	{
927 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType					sType
928 			DE_NULL,											// const void*						pNext
929 			descriptorPool,										// VkDescriptorPool					descriptorPool
930 			1u,													// deUint32							descriptorSetCount
931 			&setLayout,											// const VkDescriptorSetLayout*		pSetLayouts
932 	};
933 	return allocateDescriptorSet(vkd, vkDevice, &allocateParams);
934 }
935 
addImageTransitionBarrier(VkCommandBuffer commandBuffer,VkImage image,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkAccessFlags srcAccessMask,VkAccessFlags dstAccessMask,VkImageLayout oldLayout,VkImageLayout newLayout) const936 void TextureRenderer::addImageTransitionBarrier(VkCommandBuffer commandBuffer, VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout) const
937 {
938 	const DeviceInterface&			vkd					= m_context.getDeviceInterface();
939 
940 	const VkImageSubresourceRange	subResourcerange	=
941 	{
942 		VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags	aspectMask;
943 		0,								// deUint32				baseMipLevel;
944 		1,								// deUint32				levelCount;
945 		0,								// deUint32				baseArrayLayer;
946 		1								// deUint32				layerCount;
947 	};
948 
949 	const VkImageMemoryBarrier		imageBarrier		=
950 	{
951 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
952 		DE_NULL,									// const void*				pNext;
953 		srcAccessMask,								// VkAccessFlags			srcAccessMask;
954 		dstAccessMask,								// VkAccessFlags			dstAccessMask;
955 		oldLayout,									// VkImageLayout			oldLayout;
956 		newLayout,									// VkImageLayout			newLayout;
957 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
958 		VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
959 		image,										// VkImage					image;
960 		subResourcerange							// VkImageSubresourceRange	subresourceRange;
961 	};
962 
963 	vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
964 }
965 
966 
renderQuad(tcu::Surface & result,int texUnit,const float * texCoord,TextureType texType)967 void TextureRenderer::renderQuad (tcu::Surface& result, int texUnit, const float* texCoord, TextureType texType)
968 {
969 	renderQuad(result, texUnit, texCoord, ReferenceParams(texType));
970 }
971 
renderQuad(tcu::Surface & result,int texUnit,const float * texCoord,const ReferenceParams & params)972 void TextureRenderer::renderQuad (tcu::Surface& result, int texUnit, const float* texCoord, const ReferenceParams& params)
973 {
974 	const float	maxAnisotropy = 1.0f;
975 	float		positions[]	=
976 	{
977 		-1.0,	-1.0f,	0.0f,	1.0f,
978 		-1.0f,	+1.0f,	0.0f,	1.0f,
979 		+1.0f,	-1.0f,	0.0f,	1.0f,
980 		+1.0f,	+1.0f,	0.0f,	1.0f
981 	};
982 	renderQuad(result, positions, texUnit, texCoord, params, maxAnisotropy);
983 }
984 
renderQuad(tcu::Surface & result,const float * positions,int texUnit,const float * texCoord,const glu::TextureTestUtil::ReferenceParams & params,const float maxAnisotropy)985 void TextureRenderer::renderQuad (tcu::Surface&									result,
986 								  const float*									positions,
987 								  int											texUnit,
988 								  const float*									texCoord,
989 								  const glu::TextureTestUtil::ReferenceParams&	params,
990 								  const float									maxAnisotropy)
991 {
992 	const DeviceInterface&		vkd						= m_context.getDeviceInterface();
993 	const VkDevice				vkDevice				= m_context.getDevice();
994 	const VkQueue				queue					= m_context.getUniversalQueue();
995 	const deUint32				queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
996 	Allocator&					allocator				= m_context.getDefaultAllocator();
997 
998 	tcu::Vec4					wCoord					= params.flags & RenderParams::PROJECTED ? params.w : tcu::Vec4(1.0f);
999 	bool						useBias					= !!(params.flags & RenderParams::USE_BIAS);
1000 	bool						logUniforms				= !!(params.flags & RenderParams::LOG_UNIFORMS);
1001 
1002 	// Render quad with texture.
1003 	float						position[]				=
1004 	{
1005 		positions[0]*wCoord.x(),	positions[1]*wCoord.x(),	positions[2],	positions[3]*wCoord.x(),
1006 		positions[4]*wCoord.y(),	positions[5]*wCoord.y(),	positions[6],	positions[7]*wCoord.y(),
1007 		positions[8]*wCoord.z(),	positions[9]*wCoord.z(),	positions[10],	positions[11]*wCoord.z(),
1008 		positions[12]*wCoord.w(),	positions[13]*wCoord.w(),	positions[14],	positions[15]*wCoord.w()
1009 	};
1010 
1011 	Program						progSpec				= PROGRAM_LAST;
1012 	int							numComps				= 0;
1013 
1014 	if (params.texType == TEXTURETYPE_2D)
1015 	{
1016 		numComps = 2;
1017 
1018 		switch (params.samplerType)
1019 		{
1020 			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_2D_FLOAT_BIAS	: PROGRAM_2D_FLOAT;		break;
1021 			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_2D_INT_BIAS	: PROGRAM_2D_INT;		break;
1022 			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_2D_UINT_BIAS	: PROGRAM_2D_UINT;		break;
1023 			case SAMPLERTYPE_SHADOW:	progSpec = useBias ? PROGRAM_2D_SHADOW_BIAS	: PROGRAM_2D_SHADOW;	break;
1024 			default:					DE_ASSERT(false);
1025 		}
1026 	}
1027 	else if (params.texType == TEXTURETYPE_1D)
1028 	{
1029 		numComps = 1;
1030 
1031 		switch (params.samplerType)
1032 		{
1033 			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_1D_FLOAT_BIAS	: PROGRAM_1D_FLOAT;		break;
1034 			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_1D_INT_BIAS	: PROGRAM_1D_INT;		break;
1035 			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_1D_UINT_BIAS	: PROGRAM_1D_UINT;		break;
1036 			case SAMPLERTYPE_SHADOW:	progSpec = useBias ? PROGRAM_1D_SHADOW_BIAS	: PROGRAM_1D_SHADOW;	break;
1037 			default:					DE_ASSERT(false);
1038 		}
1039 	}
1040 	else if (params.texType == TEXTURETYPE_CUBE)
1041 	{
1042 		numComps = 3;
1043 
1044 		switch (params.samplerType)
1045 		{
1046 			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_CUBE_FLOAT_BIAS	: PROGRAM_CUBE_FLOAT;	break;
1047 			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_CUBE_INT_BIAS		: PROGRAM_CUBE_INT;		break;
1048 			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_CUBE_UINT_BIAS		: PROGRAM_CUBE_UINT;	break;
1049 			case SAMPLERTYPE_SHADOW:	progSpec = useBias ? PROGRAM_CUBE_SHADOW_BIAS	: PROGRAM_CUBE_SHADOW;	break;
1050 			default:					DE_ASSERT(false);
1051 		}
1052 	}
1053 	else if (params.texType == TEXTURETYPE_3D)
1054 	{
1055 		numComps = 3;
1056 
1057 		switch (params.samplerType)
1058 		{
1059 			case SAMPLERTYPE_FLOAT:		progSpec = useBias ? PROGRAM_3D_FLOAT_BIAS	: PROGRAM_3D_FLOAT;		break;
1060 			case SAMPLERTYPE_INT:		progSpec = useBias ? PROGRAM_3D_INT_BIAS	: PROGRAM_3D_INT;		break;
1061 			case SAMPLERTYPE_UINT:		progSpec = useBias ? PROGRAM_3D_UINT_BIAS	: PROGRAM_3D_UINT;		break;
1062 			default:					DE_ASSERT(false);
1063 		}
1064 	}
1065 	else if (params.texType == TEXTURETYPE_2D_ARRAY)
1066 	{
1067 		DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias.
1068 
1069 		numComps = 3;
1070 
1071 		switch (params.samplerType)
1072 		{
1073 			case SAMPLERTYPE_FLOAT:		progSpec = PROGRAM_2D_ARRAY_FLOAT;	break;
1074 			case SAMPLERTYPE_INT:		progSpec = PROGRAM_2D_ARRAY_INT;	break;
1075 			case SAMPLERTYPE_UINT:		progSpec = PROGRAM_2D_ARRAY_UINT;	break;
1076 			case SAMPLERTYPE_SHADOW:	progSpec = PROGRAM_2D_ARRAY_SHADOW;	break;
1077 			default:					DE_ASSERT(false);
1078 		}
1079 	}
1080 	else if (params.texType == TEXTURETYPE_CUBE_ARRAY)
1081 	{
1082 		DE_ASSERT(!useBias);
1083 
1084 		numComps = 4;
1085 
1086 		switch (params.samplerType)
1087 		{
1088 			case SAMPLERTYPE_FLOAT:		progSpec = PROGRAM_CUBE_ARRAY_FLOAT;	break;
1089 			case SAMPLERTYPE_INT:		progSpec = PROGRAM_CUBE_ARRAY_INT;		break;
1090 			case SAMPLERTYPE_UINT:		progSpec = PROGRAM_CUBE_ARRAY_UINT;		break;
1091 			case SAMPLERTYPE_SHADOW:	progSpec = PROGRAM_CUBE_ARRAY_SHADOW;	break;
1092 			default:					DE_ASSERT(false);
1093 		}
1094 	}
1095 	else if (params.texType == TEXTURETYPE_1D_ARRAY)
1096 	{
1097 		DE_ASSERT(!useBias); // \todo [2012-02-17 pyry] Support bias.
1098 
1099 		numComps = 2;
1100 
1101 		switch (params.samplerType)
1102 		{
1103 			case SAMPLERTYPE_FLOAT:		progSpec = PROGRAM_1D_ARRAY_FLOAT;	break;
1104 			case SAMPLERTYPE_INT:		progSpec = PROGRAM_1D_ARRAY_INT;	break;
1105 			case SAMPLERTYPE_UINT:		progSpec = PROGRAM_1D_ARRAY_UINT;	break;
1106 			case SAMPLERTYPE_SHADOW:	progSpec = PROGRAM_1D_ARRAY_SHADOW;	break;
1107 			default:					DE_ASSERT(false);
1108 		}
1109 	}
1110 	else if (params.texType == TEXTURETYPE_BUFFER)
1111 	{
1112 		numComps = 1;
1113 
1114 		switch (params.samplerType)
1115 		{
1116 			case SAMPLERTYPE_FETCH_FLOAT:	progSpec = PROGRAM_BUFFER_FLOAT;	break;
1117 			case SAMPLERTYPE_FETCH_INT:		progSpec = PROGRAM_BUFFER_INT;		break;
1118 			case SAMPLERTYPE_FETCH_UINT:	progSpec = PROGRAM_BUFFER_UINT;		break;
1119 			default:						DE_ASSERT(false);
1120 		}
1121 	}
1122 	else
1123 		DE_ASSERT(DE_FALSE);
1124 
1125 	Unique<VkShaderModule>					vertexShaderModule		(createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("vertext_" + std::string(getProgramName(progSpec))), 0));
1126 	Unique<VkShaderModule>					fragmentShaderModule	(createShaderModule(vkd, vkDevice, m_context.getBinaryCollection().get("fragment_" + std::string(getProgramName(progSpec))), 0));
1127 
1128 	Move<VkSampler>							sampler;
1129 	Move<VkDescriptorSet>					descriptorSet[2];
1130 	Move<VkDescriptorSetLayout>				descriptorSetLayout[2];
1131 	Move<VkPipelineLayout>					pipelineLayout;
1132 
1133 	Move<VkCommandBuffer>					commandBuffer;
1134 	Move<VkPipeline>						graphicsPipeline;
1135 	Move<VkBuffer>							vertexBuffer;
1136 	de::MovePtr<Allocation>					vertexBufferMemory;
1137 	const deUint32							positionDataSize		= deUint32(sizeof(float) * 4 * 4);
1138 	const deUint32							textureCoordDataSize	= deUint32(sizeof(float) * numComps * 4);
1139 
1140 	const VkPhysicalDeviceProperties		properties				= m_context.getDeviceProperties();
1141 
1142 	if (positionDataSize > properties.limits.maxVertexInputAttributeOffset)
1143 	{
1144 		std::stringstream message;
1145 		message << "Larger vertex input attribute offset is needed (" << positionDataSize << ") than the available maximum (" << properties.limits.maxVertexInputAttributeOffset << ").";
1146 		TCU_THROW(NotSupportedError, message.str().c_str());
1147 	}
1148 
1149 	// Create Graphics Pipeline
1150 	{
1151 		const VkPipelineShaderStageCreateInfo	shaderStageParams[2]	=
1152 		{
1153 			{
1154 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType					sType;
1155 				DE_NULL,													// const void*						pNext;
1156 				0,															// VkPipelineShaderStageCreateFlags flags;
1157 				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStage					stage;
1158 				*vertexShaderModule,										// VkShaderModule					shader;
1159 				"main",														// const char*						pName;
1160 				DE_NULL														// const VkSpecializationInfo*		pSpecializationInfo;
1161 			},
1162 			{
1163 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType					sType;
1164 				DE_NULL,													// const void*						pNext;
1165 				0,															// VkPipelineShaderStageCreateFlags flags;
1166 				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStage					stage;
1167 				*fragmentShaderModule,										// VkShaderModule					shader;
1168 				"main",														// const char*						pName;
1169 				DE_NULL														// const VkSpecializationInfo*		pSpecializationInfo;
1170 			}
1171 		};
1172 
1173 		const deUint32							vertexPositionStrideSize			= deUint32(sizeof(tcu::Vec4));
1174 		const deUint32							vertexTextureStrideSize				= deUint32(numComps * sizeof(float));
1175 
1176 		const VkVertexInputBindingDescription	vertexInputBindingDescription[2]	=
1177 		{
1178 			{
1179 				0u,								// deUint32					binding;
1180 				vertexPositionStrideSize,		// deUint32					strideInBytes;
1181 				VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	stepRate;
1182 			},
1183 			{
1184 				1u,								// deUint32					binding;
1185 				vertexTextureStrideSize,		// deUint32					strideInBytes;
1186 				VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	stepRate;
1187 			}
1188 		};
1189 
1190 		VkFormat								textureCoordinateFormat			= VK_FORMAT_R32G32B32A32_SFLOAT;
1191 
1192 		switch (numComps) {
1193 			case 1: textureCoordinateFormat = VK_FORMAT_R32_SFLOAT;				break;
1194 			case 2: textureCoordinateFormat = VK_FORMAT_R32G32_SFLOAT;			break;
1195 			case 3: textureCoordinateFormat = VK_FORMAT_R32G32B32_SFLOAT;		break;
1196 			case 4: textureCoordinateFormat = VK_FORMAT_R32G32B32A32_SFLOAT;	break;
1197 			default:
1198 				DE_ASSERT(false);
1199 		}
1200 
1201 		const VkVertexInputAttributeDescription	vertexInputAttributeDescriptions[2] =
1202 		{
1203 			{
1204 				0u,									// deUint32	location;
1205 				0u,									// deUint32	binding;
1206 				VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
1207 				0u									// deUint32	offsetInBytes;
1208 			},
1209 			{
1210 				1u,									// deUint32	location;
1211 				1u,									// deUint32	binding;
1212 				textureCoordinateFormat,			// VkFormat	format;
1213 				positionDataSize					// deUint32	offsetInBytes;
1214 			}
1215 		};
1216 
1217 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams =
1218 		{
1219 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1220 			DE_NULL,														// const void*								pNext;
1221 			0,																// VkPipelineVertexInputStateCreateFlags	flags;
1222 			2u,																// deUint32									bindingCount;
1223 			vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1224 			2u,																// deUint32									attributeCount;
1225 			vertexInputAttributeDescriptions								// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
1226 		};
1227 
1228 		const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyStateParams =
1229 		{
1230 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
1231 			DE_NULL,														// const void*								pNext;
1232 			0,																// VkPipelineInputAssemblyStateCreateFlags	flags;
1233 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology						topology;
1234 			VK_FALSE														// VkBool32									primitiveRestartEnable;
1235 		};
1236 
1237 		const VkViewport						viewport =
1238 		{
1239 			m_viewportOffsetX,			// float	originX;
1240 			m_viewportOffsetY,			// float	originY;
1241 			m_viewportWidth,			// float	width;
1242 			m_viewportHeight,			// float	height;
1243 			0.0f,						// float	minDepth;
1244 			1.0f						// float	maxDepth;
1245 		};
1246 
1247 		const VkRect2D							scissor =
1248 		{
1249 			{ 0, 0 },														// VkOffset2D  offset;
1250 			{ m_renderWidth, m_renderHeight }								// VkExtent2D  extent;
1251 		};
1252 
1253 		const VkPipelineViewportStateCreateInfo	viewportStateParams =
1254 		{
1255 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
1256 			DE_NULL,														// const void*							pNext;
1257 			0,																// VkPipelineViewportStateCreateFlags	flags;
1258 			1u,																// deUint32								viewportCount;
1259 			&viewport,														// const VkViewport*					pViewports;
1260 			1u,																// deUint32								scissorCount;
1261 			&scissor														// const VkRect2D*						pScissors;
1262 		};
1263 
1264 		const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1265 		{
1266 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
1267 			DE_NULL,														// const void*								pNext;
1268 			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
1269 			m_sampleCount,													// VkSampleCountFlagBits					rasterizationSamples;
1270 			VK_FALSE,														// VkBool32									sampleShadingEnable;
1271 			0.0f,															// float									minSampleShading;
1272 			DE_NULL,														// const VkSampleMask*						pSampleMask;
1273 			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
1274 			VK_FALSE														// VkBool32									alphaToOneEnable;
1275 		};
1276 
1277 		const VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
1278 		{
1279 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
1280 			DE_NULL,														// const void*								pNext;
1281 			0,																// VkPipelineRasterizationStateCreateFlags	flags;
1282 			VK_FALSE,														// VkBool32									depthClipEnable;
1283 			VK_FALSE,														// VkBool32									rasterizerDiscardEnable;
1284 			VK_POLYGON_MODE_FILL,											// VkFillMode								fillMode;
1285 			VK_CULL_MODE_NONE,												// VkCullMode								cullMode;
1286 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
1287 			VK_FALSE,														// VkBool32									depthBiasEnable;
1288 			0.0f,															// float									depthBias;
1289 			0.0f,															// float									depthBiasClamp;
1290 			0.0f,															// float									slopeScaledDepthBias;
1291 			1.0f,															// float									lineWidth;
1292 		};
1293 
1294 		const VkPipelineColorBlendAttachmentState	colorBlendAttachmentState	=
1295 		{
1296 			VK_FALSE,													// VkBool32			blendEnable;
1297 			VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendColor;
1298 			VK_BLEND_FACTOR_ZERO,										// VkBlend			destBlendColor;
1299 			VK_BLEND_OP_ADD,											// VkBlendOp		blendOpColor;
1300 			VK_BLEND_FACTOR_ONE,										// VkBlend			srcBlendAlpha;
1301 			VK_BLEND_FACTOR_ZERO,										// VkBlend			destBlendAlpha;
1302 			VK_BLEND_OP_ADD,											// VkBlendOp		blendOpAlpha;
1303 			(VK_COLOR_COMPONENT_R_BIT |
1304 			 VK_COLOR_COMPONENT_G_BIT |
1305 			 VK_COLOR_COMPONENT_B_BIT |
1306 			 VK_COLOR_COMPONENT_A_BIT)									// VkChannelFlags	channelWriteMask;
1307 		};
1308 
1309 		const VkPipelineColorBlendStateCreateInfo	colorBlendStateParams		=
1310 		{
1311 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1312 			DE_NULL,													// const void*									pNext;
1313 			0,															// VkPipelineColorBlendStateCreateFlags			flags;
1314 			VK_FALSE,													// VkBool32										logicOpEnable;
1315 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1316 			1u,															// deUint32										attachmentCount;
1317 			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
1318 			{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
1319 		};
1320 
1321 		VkSamplerCreateInfo					samplerCreateInfo			= mapSampler(params.sampler, m_textureBindings[texUnit]->getTestTexture().getTextureFormat(), params.minLod, params.maxLod);
1322 
1323 		if (maxAnisotropy > 1.0f)
1324 		{
1325 			samplerCreateInfo.anisotropyEnable = VK_TRUE;
1326 			samplerCreateInfo.maxAnisotropy = maxAnisotropy;
1327 		}
1328 
1329 		if (samplerCreateInfo.magFilter == VK_FILTER_LINEAR || samplerCreateInfo.minFilter == VK_FILTER_LINEAR || samplerCreateInfo.mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR)
1330 		{
1331 			const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), mapTextureFormat(m_textureBindings[texUnit]->getTestTexture().getTextureFormat()));
1332 			if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))
1333 				TCU_THROW(NotSupportedError, "Linear filtering for this image format is not supported");
1334 		}
1335 
1336 		sampler = createSampler(vkd, vkDevice, &samplerCreateInfo);
1337 
1338 		descriptorSetLayout[0] = DescriptorSetLayoutBuilder()
1339 											.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1340 												.build(vkd, vkDevice);
1341 
1342 		descriptorSetLayout[1] = DescriptorSetLayoutBuilder()
1343 											.addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &sampler.get())
1344 											.build(vkd, vkDevice);
1345 
1346 
1347 		descriptorSet[0] = makeDescriptorSet(*m_descriptorPool, *descriptorSetLayout[0]);
1348 		descriptorSet[1] = makeDescriptorSet(*m_descriptorPool, *descriptorSetLayout[1]);
1349 
1350 		{
1351 			const VkDescriptorBufferInfo			descriptorBufferInfo	=
1352 			{
1353 				*m_uniformBuffer,							// VkBuffer		buffer;
1354 				0u,											// VkDeviceSize	offset;
1355 				VK_WHOLE_SIZE								// VkDeviceSize	range;
1356 			};
1357 
1358 			DescriptorSetUpdateBuilder()
1359 				.writeSingle(*descriptorSet[0], DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorBufferInfo)
1360 				.update(vkd, vkDevice);
1361 		}
1362 
1363 		{
1364 			VkDescriptorImageInfo					descriptorImageInfo		=
1365 			{
1366 				*sampler,										// VkSampler		sampler;
1367 				m_textureBindings[texUnit]->getImageView(),		// VkImageView		imageView;
1368 				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL		// VkImageLayout	imageLayout;
1369 			};
1370 
1371 			DescriptorSetUpdateBuilder()
1372 				.writeSingle(*descriptorSet[1], DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfo)
1373 				.update(vkd, vkDevice);
1374 		}
1375 
1376 		// Pipeline Layout
1377 		{
1378 			VkDescriptorSetLayout					descriptorSetLayouts[2]		=
1379 			{
1380 				*descriptorSetLayout[0],
1381 				*descriptorSetLayout[1]
1382 			};
1383 
1384 			const VkPipelineLayoutCreateInfo		pipelineLayoutCreateInfo	=
1385 			{
1386 				VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
1387 				DE_NULL,											// const void*					pNext;
1388 				0u,													// VkPipelineLayoutCreateFlags	flags;
1389 				2u,													// deUint32						descriptorSetCount;
1390 				descriptorSetLayouts,								// const VkDescriptorSetLayout*	pSetLayouts;
1391 				0u,													// deUint32						pushConstantRangeCount;
1392 				DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
1393 			};
1394 
1395 			pipelineLayout = createPipelineLayout(vkd, vkDevice, &pipelineLayoutCreateInfo);
1396 		}
1397 
1398 		const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
1399 		{
1400 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
1401 			DE_NULL,											// const void*										pNext;
1402 			0u,													// VkPipelineCreateFlags							flags;
1403 			2u,													// deUint32											stageCount;
1404 			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
1405 			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
1406 			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
1407 			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
1408 			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
1409 			&rasterizationStateCreateInfo,						// const VkPipelineRasterStateCreateInfo*			pRasterizationState;
1410 			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
1411 			DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
1412 			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
1413 			DE_NULL,											// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
1414 			*pipelineLayout,									// VkPipelineLayout									layout;
1415 			*m_renderPass,										// VkRenderPass										renderPass;
1416 			0u,													// deUint32											subpass;
1417 			0u,													// VkPipeline										basePipelineHandle;
1418 			0u													// deInt32											basePipelineIndex;
1419 		};
1420 
1421 		graphicsPipeline		= createGraphicsPipeline(vkd, vkDevice, DE_NULL, &graphicsPipelineParams);
1422 	}
1423 
1424 	// Create Vertex Buffer
1425 	{
1426 		const VkBufferCreateInfo			vertexBufferParams		=
1427 		{
1428 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
1429 			DE_NULL,									// const void*			pNext;
1430 			0u,											// VkBufferCreateFlags	flags;
1431 			positionDataSize + textureCoordDataSize,	// VkDeviceSize			size;
1432 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
1433 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
1434 			1u,											// deUint32				queueFamilyCount;
1435 			&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
1436 		};
1437 
1438 		vertexBuffer		= createBuffer(vkd, vkDevice, &vertexBufferParams);
1439 		vertexBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vkd, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
1440 
1441 		VK_CHECK(vkd.bindBufferMemory(vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
1442 
1443 		// Load vertices into vertex buffer
1444 		deMemcpy(vertexBufferMemory->getHostPtr(), position, positionDataSize);
1445 		deMemcpy(reinterpret_cast<deUint8*>(vertexBufferMemory->getHostPtr()) +  positionDataSize, texCoord, textureCoordDataSize);
1446 		flushMappedMemoryRange(vkd, vkDevice, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset(), VK_WHOLE_SIZE);
1447 	}
1448 
1449 	// Create Command Buffer
1450 	{
1451 		const VkCommandBufferAllocateInfo		cmdBufferAllocateInfo	=
1452 		{
1453 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,				// VkStructureType             sType;
1454 			DE_NULL,													// const void*                 pNext;
1455 			*m_commandPool,												// VkCommandPool               commandPool;
1456 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,							// VkCommandBufferLevel        level;
1457 			1															// deUint32                    commandBufferCount;
1458 		};
1459 
1460 		commandBuffer = allocateCommandBuffer(vkd, vkDevice, &cmdBufferAllocateInfo);
1461 	}
1462 
1463 	// Begin Command Buffer
1464 	{
1465 		const VkCommandBufferBeginInfo		cmdBufferBeginInfo		=
1466 		{
1467 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType							sType;
1468 			DE_NULL,										// const void*								pNext;
1469 			0u,												// VkCmdBufferOptimizeFlags					flags;
1470 			DE_NULL											// const VkCommandBufferInheritanceInfo*	pInheritanceInfo;
1471 		};
1472 
1473 		VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &cmdBufferBeginInfo));
1474 	}
1475 
1476 	// Begin Render Pass
1477 	{
1478 		const VkRenderPassBeginInfo			renderPassBeginInfo		=
1479 		{
1480 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
1481 			DE_NULL,												// const void*			pNext;
1482 			*m_renderPass,											// VkRenderPass			renderPass;
1483 			*m_frameBuffer,											// VkFramebuffer		framebuffer;
1484 			{
1485 				{ 0, 0 },
1486 				{ m_renderWidth, m_renderHeight }
1487 			},														// VkRect2D				renderArea;
1488 			0u,														// deUint32				clearValueCount;
1489 			DE_NULL													// const VkClearValue*	pClearValues;
1490 		};
1491 
1492 		vkd.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1493 	}
1494 
1495 	const VkDeviceSize						vertexBufferOffset		= 0;
1496 
1497 	vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1498 	vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1, &descriptorSet[0].get(), 0u, DE_NULL);
1499 	vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 1u, 1, &descriptorSet[1].get(), 0u, DE_NULL);
1500 	vkd.cmdBindVertexBuffers(*commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
1501 	vkd.cmdBindVertexBuffers(*commandBuffer, 1, 1, &vertexBuffer.get(), &vertexBufferOffset);
1502 	vkd.cmdBindIndexBuffer(*commandBuffer, *m_vertexIndexBuffer, 0, VK_INDEX_TYPE_UINT16);
1503 	vkd.cmdDrawIndexed(*commandBuffer, 6, 1, 0, 0, 0);
1504 	vkd.cmdEndRenderPass(*commandBuffer);
1505 
1506 	// Copy Image
1507 	{
1508 		const VkBufferMemoryBarrier			bufferBarrier			=
1509 		{
1510 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType		sType;
1511 			DE_NULL,									// const void*			pNext;
1512 			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkMemoryOutputFlags	outputMask;
1513 			VK_ACCESS_HOST_READ_BIT,					// VkMemoryInputFlags	inputMask;
1514 			VK_QUEUE_FAMILY_IGNORED,					// deUint32				srcQueueFamilyIndex;
1515 			VK_QUEUE_FAMILY_IGNORED,					// deUint32				destQueueFamilyIndex;
1516 			*m_resultBuffer,							// VkBuffer				buffer;
1517 			0u,											// VkDeviceSize			offset;
1518 			m_resultBufferSize							// VkDeviceSize			size;
1519 		};
1520 
1521 		const VkBufferImageCopy				copyRegion				=
1522 		{
1523 			0u,											// VkDeviceSize				bufferOffset;
1524 			m_renderWidth,								// deUint32					bufferRowLength;
1525 			m_renderHeight,								// deUint32					bufferImageHeight;
1526 			{
1527 				VK_IMAGE_ASPECT_COLOR_BIT,
1528 				0u,
1529 				0u,
1530 				1u
1531 			},											// VkImageSubresourceCopy	imageSubresource;
1532 			{ 0, 0, 0 },								// VkOffset3D				imageOffset;
1533 			{ m_renderWidth, m_renderHeight, 1u }		// VkExtent3D				imageExtent;
1534 		};
1535 
1536 		addImageTransitionBarrier(*commandBuffer,
1537 								  m_multisampling ? *m_resolvedImage : *m_image,
1538 								  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,		// VkPipelineStageFlags		srcStageMask
1539 								  VK_PIPELINE_STAGE_TRANSFER_BIT,						// VkPipelineStageFlags		dstStageMask
1540 								  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,					// VkAccessFlags			srcAccessMask
1541 								  VK_ACCESS_TRANSFER_READ_BIT,							// VkAccessFlags			dstAccessMask
1542 								  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout			oldLayout;
1543 								  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);				// VkImageLayout			newLayout;
1544 
1545 		if (m_multisampling)
1546 			vkd.cmdCopyImageToBuffer(*commandBuffer, *m_resolvedImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, &copyRegion);
1547 		else
1548 			vkd.cmdCopyImageToBuffer(*commandBuffer, *m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *m_resultBuffer, 1, &copyRegion);
1549 
1550 		vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &bufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1551 
1552 		addImageTransitionBarrier(*commandBuffer,
1553 								  m_multisampling ? *m_resolvedImage : *m_image,
1554 								  VK_PIPELINE_STAGE_TRANSFER_BIT,					// VkPipelineStageFlags		srcStageMask
1555 								  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// VkPipelineStageFlags		dstStageMask
1556 								  VK_ACCESS_TRANSFER_READ_BIT,						// VkAccessFlags			srcAccessMask
1557 								  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask
1558 								  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,				// VkImageLayout			oldLayout;
1559 								  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);		// VkImageLayout			newLayout;
1560 	}
1561 
1562 	VK_CHECK(vkd.endCommandBuffer(*commandBuffer));
1563 
1564 	// Upload uniform buffer data
1565 	{
1566 		const ShaderParameters	shaderParameters	=
1567 		{
1568 			params.bias,			// float		bias;				//!< User-supplied bias.
1569 			params.ref,				// float		ref;				//!< Reference value for shadow lookups.
1570 			tcu::Vec2(),			// tcu::Vec2	padding;			//!< Shader uniform padding.
1571 			params.colorScale,		// tcu::Vec4	colorScale;			//!< Scale for texture color values.
1572 			params.colorBias		// tcu::Vec4	colorBias;			//!< Bias for texture color values.
1573 		};
1574 		deMemcpy(m_uniformBufferMemory->getHostPtr(), &shaderParameters, sizeof(shaderParameters));
1575 		flushMappedMemoryRange(vkd, vkDevice, m_uniformBufferMemory->getMemory(), m_uniformBufferMemory->getOffset(), VK_WHOLE_SIZE);
1576 
1577 		if (logUniforms)
1578 			m_log << TestLog::Message << "u_sampler = " << texUnit << TestLog::EndMessage;
1579 
1580 		if (useBias)
1581 		{
1582 			if (logUniforms)
1583 				m_log << TestLog::Message << "u_bias = " << shaderParameters.bias << TestLog::EndMessage;
1584 		}
1585 
1586 		if (params.samplerType == SAMPLERTYPE_SHADOW)
1587 		{
1588 			if (logUniforms)
1589 				m_log << TestLog::Message << "u_ref = " << shaderParameters.ref << TestLog::EndMessage;
1590 		}
1591 
1592 		if (logUniforms)
1593 		{
1594 			m_log << TestLog::Message << "u_colorScale = " << shaderParameters.colorScale << TestLog::EndMessage;
1595 			m_log << TestLog::Message << "u_colorBias = " << shaderParameters.colorBias << TestLog::EndMessage;
1596 		}
1597 	}
1598 
1599 	// Submit
1600 	{
1601 		const VkSubmitInfo					submitInfo				=
1602 		{
1603 			VK_STRUCTURE_TYPE_SUBMIT_INFO,			// VkStructureType				sType;
1604 			DE_NULL,								// const void*					pNext;
1605 			0u,										// deUint32						waitSemaphoreCount;
1606 			DE_NULL,								// const VkSemaphore*			pWaitSemaphores;
1607 			DE_NULL,								// const VkPipelineStageFlags*	pWaitDstStageMask;
1608 			1u,										// deUint32						commandBufferCount;
1609 			&commandBuffer.get(),					// const VkCommandBuffer*		pCommandBuffers;
1610 			0u,										// deUint32						signalSemaphoreCount;
1611 			DE_NULL,								// const VkSemaphore*			pSignalSemaphores;
1612 		};
1613 
1614 		VK_CHECK(vkd.resetFences(vkDevice, 1, &m_fence.get()));
1615 		VK_CHECK(vkd.queueSubmit(queue, 1, &submitInfo, *m_fence));
1616 		VK_CHECK(vkd.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
1617 	}
1618 
1619 	invalidateMappedMemoryRange(vkd, vkDevice, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset(), VK_WHOLE_SIZE);
1620 
1621 	tcu::copy(result.getAccess(), tcu::ConstPixelBufferAccess(m_textureFormat, tcu::IVec3(m_renderWidth, m_renderHeight, 1u), m_resultBufferMemory->getHostPtr()));
1622 }
1623 
1624 /*--------------------------------------------------------------------*//*!
1625  * \brief Map Vulkan sampler parameters to tcu::Sampler.
1626  *
1627  * If no mapping is found, throws tcu::InternalError.
1628  *
1629  * \param wrapU			U-component wrap mode
1630  * \param wrapV			V-component wrap mode
1631  * \param wrapW			W-component wrap mode
1632  * \param minFilterMode	Minification filter mode
1633  * \param magFilterMode	Magnification filter mode
1634  * \return Sampler description.
1635  *//*--------------------------------------------------------------------*/
createSampler(tcu::Sampler::WrapMode wrapU,tcu::Sampler::WrapMode wrapV,tcu::Sampler::WrapMode wrapW,tcu::Sampler::FilterMode minFilterMode,tcu::Sampler::FilterMode magFilterMode)1636 tcu::Sampler createSampler (tcu::Sampler::WrapMode wrapU, tcu::Sampler::WrapMode wrapV, tcu::Sampler::WrapMode wrapW, tcu::Sampler::FilterMode minFilterMode, tcu::Sampler::FilterMode magFilterMode)
1637 {
1638 	return tcu::Sampler(wrapU, wrapV, wrapW,
1639 						minFilterMode, magFilterMode,
1640 						0.0f /* lod threshold */,
1641 						true /* normalized coords */,
1642 						tcu::Sampler::COMPAREMODE_NONE /* no compare */,
1643 						0 /* compare channel */,
1644 						tcu::Vec4(0.0f) /* border color, not used */);
1645 }
1646 
1647 /*--------------------------------------------------------------------*//*!
1648  * \brief Map Vulkan sampler parameters to tcu::Sampler.
1649  *
1650  * If no mapping is found, throws tcu::InternalError.
1651  *
1652  * \param wrapU			U-component wrap mode
1653  * \param wrapV			V-component wrap mode
1654  * \param minFilterMode	Minification filter mode
1655  * \param minFilterMode	Magnification filter mode
1656  * \return Sampler description.
1657  *//*--------------------------------------------------------------------*/
createSampler(tcu::Sampler::WrapMode wrapU,tcu::Sampler::WrapMode wrapV,tcu::Sampler::FilterMode minFilterMode,tcu::Sampler::FilterMode magFilterMode)1658 tcu::Sampler createSampler (tcu::Sampler::WrapMode wrapU, tcu::Sampler::WrapMode wrapV, tcu::Sampler::FilterMode minFilterMode, tcu::Sampler::FilterMode magFilterMode)
1659 {
1660 	return createSampler(wrapU, wrapV, wrapU, minFilterMode, magFilterMode);
1661 }
1662 
1663 /*--------------------------------------------------------------------*//*!
1664  * \brief Map Vulkan sampler parameters to tcu::Sampler.
1665  *
1666  * If no mapping is found, throws tcu::InternalError.
1667  *
1668  * \param wrapU			U-component wrap mode
1669  * \param minFilterMode	Minification filter mode
1670  * \return Sampler description.
1671  *//*--------------------------------------------------------------------*/
createSampler(tcu::Sampler::WrapMode wrapU,tcu::Sampler::FilterMode minFilterMode,tcu::Sampler::FilterMode magFilterMode)1672 tcu::Sampler createSampler (tcu::Sampler::WrapMode wrapU, tcu::Sampler::FilterMode minFilterMode, tcu::Sampler::FilterMode magFilterMode)
1673 {
1674 	return createSampler(wrapU, wrapU, wrapU, minFilterMode, magFilterMode);
1675 }
1676 
loadTexture2D(const tcu::Archive & archive,const std::vector<std::string> & filenames)1677 TestTexture2DSp loadTexture2D (const tcu::Archive& archive, const std::vector<std::string>& filenames)
1678 {
1679 	DE_ASSERT(filenames.size() > 0);
1680 
1681 	TestTexture2DSp texture;
1682 
1683 	std::string ext = de::FilePath(filenames[0]).getFileExtension();
1684 
1685 	if (ext == "png")
1686 	{
1687 
1688 		for (size_t fileIndex = 0; fileIndex < filenames.size(); ++fileIndex)
1689 		{
1690 			tcu::TextureLevel level;
1691 
1692 			tcu::ImageIO::loadImage(level, archive, filenames[fileIndex].c_str());
1693 
1694 			TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
1695 											   level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));
1696 
1697 			if (fileIndex == 0)
1698 				texture = TestTexture2DSp(new pipeline::TestTexture2D(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), level.getWidth(), level.getHeight()));
1699 
1700 			tcu::copy(texture->getLevel((int)fileIndex, 0), level.getAccess());
1701 		}
1702 	}
1703 	else if (ext == "pkm")
1704 	{
1705 
1706 		for (size_t fileIndex = 0; fileIndex < filenames.size(); ++fileIndex)
1707 		{
1708 			// Compressed texture.
1709 			tcu::CompressedTexture	level;
1710 
1711 			tcu::ImageIO::loadPKM(level, archive, filenames[fileIndex].c_str());
1712 
1713 			tcu::TextureFormat		uncompressedFormat		= tcu::getUncompressedFormat(level.getFormat());
1714 			std::vector<deUint8>	uncompressedData		(uncompressedFormat.getPixelSize() * level.getWidth() * level.getHeight(), 0);
1715 			tcu::PixelBufferAccess	decompressedBuffer		(uncompressedFormat, level.getWidth(), level.getHeight(), 1, uncompressedData.data());
1716 
1717 			tcu::TextureFormat		commonFormat			= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1718 			std::vector<deUint8>	commonFromatData		(commonFormat.getPixelSize() * level.getWidth() * level.getHeight(), 0);
1719 			tcu::PixelBufferAccess	commonFormatBuffer		(commonFormat, level.getWidth(), level.getHeight(), 1, commonFromatData.data());
1720 
1721 			if (fileIndex == 0)
1722 				texture = TestTexture2DSp(new pipeline::TestTexture2D(commonFormat, level.getWidth(), level.getHeight()));
1723 
1724 			level.decompress(decompressedBuffer, tcu::TexDecompressionParams(tcu::TexDecompressionParams::ASTCMODE_LDR));
1725 
1726 			tcu::copy(commonFormatBuffer, decompressedBuffer);
1727 			tcu::copy(texture->getLevel((int)fileIndex, 0), commonFormatBuffer);
1728 		}
1729 	}
1730 	else
1731 		TCU_FAIL("Unsupported file format");
1732 
1733 	return texture;
1734 }
1735 
loadTextureCube(const tcu::Archive & archive,const std::vector<std::string> & filenames)1736 TestTextureCubeSp loadTextureCube (const tcu::Archive& archive, const std::vector<std::string>& filenames)
1737 {
1738 	DE_ASSERT(filenames.size() > 0);
1739 	DE_STATIC_ASSERT(tcu::CUBEFACE_LAST == 6);
1740 	TCU_CHECK((int)filenames.size() % tcu::CUBEFACE_LAST == 0);
1741 
1742 	TestTextureCubeSp texture;
1743 
1744 	std::string ext = de::FilePath(filenames[0]).getFileExtension();
1745 
1746 	if (ext == "png")
1747 	{
1748 
1749 		for (size_t fileIndex = 0; fileIndex < filenames.size(); ++fileIndex)
1750 		{
1751 			tcu::TextureLevel level;
1752 
1753 			tcu::ImageIO::loadImage(level, archive, filenames[fileIndex].c_str());
1754 
1755 			TCU_CHECK_INTERNAL(level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) ||
1756 											   level.getFormat() == tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8));
1757 
1758 			TCU_CHECK( level.getWidth() == level.getHeight());
1759 
1760 			if (fileIndex == 0)
1761 				texture = TestTextureCubeSp(new pipeline::TestTextureCube(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), level.getWidth()));
1762 
1763 			tcu::copy(texture->getLevel((int)fileIndex / 6, (int)fileIndex % 6), level.getAccess());
1764 		}
1765 	}
1766 	else if (ext == "pkm")
1767 	{
1768 		for (size_t fileIndex = 0; fileIndex < filenames.size(); ++fileIndex)
1769 		{
1770 			// Compressed texture.
1771 			tcu::CompressedTexture	level;
1772 
1773 			tcu::ImageIO::loadPKM(level, archive, filenames[fileIndex].c_str());
1774 
1775 			TCU_CHECK( level.getWidth() == level.getHeight());
1776 
1777 			tcu::TextureFormat		uncompressedFormat				= tcu::getUncompressedFormat(level.getFormat());
1778 			std::vector<deUint8>	uncompressedData				(uncompressedFormat.getPixelSize() * level.getWidth() * level.getHeight(), 0);
1779 			tcu::PixelBufferAccess	decompressedBuffer				(uncompressedFormat, level.getWidth(), level.getHeight(), 1, uncompressedData.data());
1780 
1781 			tcu::TextureFormat		commonFormat					= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1782 			std::vector<deUint8>	commonFromatData				(commonFormat.getPixelSize() * level.getWidth() * level.getHeight(), 0);
1783 			tcu::PixelBufferAccess	commonFormatBuffer				(commonFormat, level.getWidth(), level.getHeight(), 1, commonFromatData.data());
1784 
1785 			if (fileIndex == 0)
1786 				texture = TestTextureCubeSp(new pipeline::TestTextureCube(commonFormat, level.getWidth()));
1787 
1788 			level.decompress(decompressedBuffer, tcu::TexDecompressionParams(tcu::TexDecompressionParams::ASTCMODE_LDR));
1789 
1790 			tcu::copy(commonFormatBuffer, decompressedBuffer);
1791 			tcu::copy(texture->getLevel((int)fileIndex / 6, (int)fileIndex % 6), commonFormatBuffer);
1792 		}
1793 	}
1794 	else
1795 		TCU_FAIL("Unsupported file format");
1796 
1797 	return texture;
1798 }
1799 
TextureCommonTestCaseParameters(void)1800 TextureCommonTestCaseParameters::TextureCommonTestCaseParameters (void)
1801 	: sampleCount			(VK_SAMPLE_COUNT_1_BIT)
1802 	, texCoordPrecision		(glu::PRECISION_HIGHP)
1803 	, minFilter				(tcu::Sampler::LINEAR)
1804 	, magFilter				(tcu::Sampler::LINEAR)
1805 	, wrapS					(tcu::Sampler::REPEAT_GL)
1806 	, wrapT					(tcu::Sampler::REPEAT_GL)
1807 	, format				(VK_FORMAT_R8G8B8A8_UNORM)
1808 {
1809 }
1810 
Texture2DTestCaseParameters(void)1811 Texture2DTestCaseParameters::Texture2DTestCaseParameters (void)
1812 	: width					(64)
1813 	, height				(64)
1814 {
1815 }
1816 
TextureCubeTestCaseParameters(void)1817 TextureCubeTestCaseParameters::TextureCubeTestCaseParameters (void)
1818 	: size					(64)
1819 {
1820 }
1821 
Texture2DArrayTestCaseParameters(void)1822 Texture2DArrayTestCaseParameters::Texture2DArrayTestCaseParameters (void)
1823 	: numLayers				(8)
1824 {
1825 }
1826 
Texture3DTestCaseParameters(void)1827 Texture3DTestCaseParameters::Texture3DTestCaseParameters (void)
1828 	: wrapR					(tcu::Sampler::REPEAT_GL)
1829 	, depth					(64)
1830 {
1831 }
1832 
1833 } // util
1834 } // texture
1835 } // vkt
1836