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
44using tcu::TestLog;
45
46using namespace vk;
47using namespace glu::TextureTestUtil;
48
49namespace vkt
50{
51namespace texture
52{
53namespace util
54{
55
56struct 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
64const 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
119VkImageViewType 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
134VkImageType 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
149void 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
287TextureBinding::TextureBinding (Context& context)
288	: m_context			(context)
289{
290}
291
292TextureBinding::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
300void 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
377void 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
407const deUint16		TextureRenderer::s_vertexIndices[6] = { 0, 1, 2, 2, 1, 3 };
408const VkDeviceSize	TextureRenderer::s_vertexIndexBufferSize = sizeof(TextureRenderer::s_vertexIndices);
409
410TextureRenderer::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
764TextureRenderer::~TextureRenderer (void)
765{
766}
767
768void 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
844void TextureRenderer::add2DTexture (const TestTexture2DSp& texture)
845{
846	m_textureBindings.push_back(TextureBindingSp(new TextureBinding(m_context, texture, TextureBinding::TYPE_2D)));
847}
848
849void TextureRenderer::addCubeTexture (const TestTextureCubeSp& texture)
850{
851	m_textureBindings.push_back(TextureBindingSp(new TextureBinding(m_context, texture, TextureBinding::TYPE_CUBE_MAP)));
852}
853
854void TextureRenderer::add2DArrayTexture (const TestTexture2DArraySp& texture)
855{
856	m_textureBindings.push_back(TextureBindingSp(new TextureBinding(m_context, texture, TextureBinding::TYPE_2D_ARRAY)));
857}
858
859void TextureRenderer::add3DTexture (const TestTexture3DSp& texture)
860{
861	m_textureBindings.push_back(TextureBindingSp(new TextureBinding(m_context, texture, TextureBinding::TYPE_3D)));
862}
863
864const 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
872const 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
880const 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
888const 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
896void 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
904TextureBinding* TextureRenderer::getTextureBinding (int textureIndex) const
905{
906	DE_ASSERT(m_textureBindings.size() > (size_t)textureIndex);
907	return m_textureBindings[textureIndex].get();
908}
909
910deUint32 TextureRenderer::getRenderWidth (void) const
911{
912	return m_renderWidth;
913}
914
915deUint32 TextureRenderer::getRenderHeight (void) const
916{
917	return m_renderHeight;
918}
919
920Move<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
936void 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
967void TextureRenderer::renderQuad (tcu::Surface& result, int texUnit, const float* texCoord, TextureType texType)
968{
969	renderQuad(result, texUnit, texCoord, ReferenceParams(texType));
970}
971
972void 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
985void 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 *//*--------------------------------------------------------------------*/
1636tcu::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 *//*--------------------------------------------------------------------*/
1658tcu::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 *//*--------------------------------------------------------------------*/
1672tcu::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
1677TestTexture2DSp 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
1736TestTextureCubeSp 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
1800TextureCommonTestCaseParameters::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
1811Texture2DTestCaseParameters::Texture2DTestCaseParameters (void)
1812	: width					(64)
1813	, height				(64)
1814{
1815}
1816
1817TextureCubeTestCaseParameters::TextureCubeTestCaseParameters (void)
1818	: size					(64)
1819{
1820}
1821
1822Texture2DArrayTestCaseParameters::Texture2DArrayTestCaseParameters (void)
1823	: numLayers				(8)
1824{
1825}
1826
1827Texture3DTestCaseParameters::Texture3DTestCaseParameters (void)
1828	: wrapR					(tcu::Sampler::REPEAT_GL)
1829	, depth					(64)
1830{
1831}
1832
1833} // util
1834} // texture
1835} // vkt
1836