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