• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*
20  * \file  vktSparseResourcesShaderIntrinsicsSampled.cpp
21  * \brief Sparse Resources Shader Intrinsics for sampled images
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSparseResourcesShaderIntrinsicsSampled.hpp"
25 #include "vkTypeUtil.hpp"
26 #include "vkCmdUtil.hpp"
27 #include "vkObjUtil.hpp"
28 #include "vkBarrierUtil.hpp"
29 #include "vkBufferWithMemory.hpp"
30 
31 using namespace vk;
32 
33 namespace vkt
34 {
35 namespace sparse
36 {
37 namespace
38 {
39 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const VkShaderModule geometryModule)40 Move<VkPipeline> makeGraphicsPipeline	(const DeviceInterface&	vk,
41 										 const VkDevice			device,
42 										 const VkPipelineLayout	pipelineLayout,
43 										 const VkRenderPass		renderPass,
44 										 const VkShaderModule	vertexModule,
45 										 const VkShaderModule	fragmentModule,
46 										 const VkShaderModule	geometryModule)
47 {
48 	const std::vector<VkViewport>				noViewports;
49 	const std::vector<VkRect2D>					noScissors;
50 
51 	const VkFormat								format	= VK_FORMAT_R32G32_SFLOAT;
52 	const deUint32								size	= tcu::getPixelSize(mapVkFormat(format));
53 
54 	const VkVertexInputBindingDescription		vertexBinding =
55 	{
56 		0u,							// deUint32				binding;
57 		size * 2,					// deUint32				stride;
58 		VK_VERTEX_INPUT_RATE_VERTEX	// VkVertexInputRate	inputRate;
59 	};
60 
61 	const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[] =
62 	{
63 		// position
64 		{
65 			0u,		// deUint32	location;
66 			0u,		// deUint32	binding;
67 			format,	// VkFormat	format;
68 			0u		// deUint32	offset;
69 		},
70 		// texture coordinates
71 		{
72 			1u,		// deUint32	location;
73 			0u,		// deUint32	binding;
74 			format,	// VkFormat	format;
75 			size	// deUint32	offset;
76 		},
77 	};
78 
79 	const VkPipelineVertexInputStateCreateInfo	vertexInputStateCreateInfo	=
80 	{
81 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
82 		DE_NULL,													// const void*								pNext;
83 		(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags	flags;
84 		1u,															// deUint32									vertexBindingDescriptionCount;
85 		&vertexBinding,												// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
86 		2u,															// deUint32									vertexAttributeDescriptionCount;
87 		vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
88 	};
89 
90 	const VkColorComponentFlags					colorComponentsAll					= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
91 	const VkPipelineColorBlendAttachmentState	defaultColorBlendAttachmentState	=
92 	{
93 		VK_FALSE,				// VkBool32					blendEnable;
94 		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			srcColorBlendFactor;
95 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstColorBlendFactor;
96 		VK_BLEND_OP_ADD,		// VkBlendOp				colorBlendOp;
97 		VK_BLEND_FACTOR_ONE,	// VkBlendFactor			srcAlphaBlendFactor;
98 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor			dstAlphaBlendFactor;
99 		VK_BLEND_OP_ADD,		// VkBlendOp				alphaBlendOp;
100 		colorComponentsAll		// VkColorComponentFlags	colorWriteMask;
101 	};
102 
103 	const VkPipelineColorBlendAttachmentState	colorBlendAttachmentStates[] =
104 	{
105 		defaultColorBlendAttachmentState,
106 		defaultColorBlendAttachmentState
107 	};
108 
109 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
110 	{
111 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
112 		DE_NULL,													// const void*									pNext;
113 		(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags;
114 		VK_FALSE,													// VkBool32										logicOpEnable;
115 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
116 		DE_LENGTH_OF_ARRAY(colorBlendAttachmentStates),				// deUint32										attachmentCount;
117 		colorBlendAttachmentStates,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
118 		{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4];
119 	};
120 
121 	return vk::makeGraphicsPipeline(vk,										// const DeviceInterface&							vk
122 									device,									// const VkDevice									device
123 									pipelineLayout,							// const VkPipelineLayout							pipelineLayout
124 									vertexModule,							// const VkShaderModule								vertexShaderModule
125 									DE_NULL,								// const VkShaderModule								tessellationControlModule
126 									DE_NULL,								// const VkShaderModule								tessellationEvalModule
127 									geometryModule,							// const VkShaderModule								geometryShaderModule
128 									fragmentModule,							// const VkShaderModule								fragmentShaderModule
129 									renderPass,								// const VkRenderPass								renderPass
130 									noViewports,							// const std::vector<VkViewport>&					viewports
131 									noScissors,								// const std::vector<VkRect2D>&						scissors
132 									VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	// const VkPrimitiveTopology						topology
133 									0u,										// const deUint32									subpass
134 									0u,										// const deUint32									patchControlPoints
135 									&vertexInputStateCreateInfo,			// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
136 									DE_NULL,								// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
137 									DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
138 									DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
139 									&pipelineColorBlendStateInfo);			// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
140 }
141 
142 } // anonymous
143 
initPrograms(vk::SourceCollections & programCollection) const144 void SparseShaderIntrinsicsCaseSampledBase::initPrograms (vk::SourceCollections& programCollection) const
145 {
146 	const PlanarFormatDescription	formatDescription	= getPlanarFormatDescription(m_format);
147 	const deUint32					numLayers			= getNumLayers(m_imageType, m_imageSize);
148 	const std::string				coordString			= getShaderImageCoordinates(m_imageType, "%local_texCoord_x", "%local_texCoord_xy", "%local_texCoord_xyz");
149 
150 	// Create vertex shader
151 	std::ostringstream vs;
152 
153 	vs	<< "#version 440\n"
154 		<< "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n"
155 		<< "#extension GL_EXT_shader_image_int64 : require\n"
156 		<< "layout(location = 0) in highp vec2 vs_in_position;\n"
157 		<< "layout(location = 1) in highp vec2 vs_in_texCoord;\n"
158 		<< "\n"
159 		<< "layout(location = 0) out highp vec3 vs_out_texCoord;\n"
160 		<< "\n"
161 		<< "out gl_PerVertex {\n"
162 		<< "	vec4 gl_Position;\n"
163 		<< "};\n"
164 		<< "void main (void)\n"
165 		<< "{\n"
166 		<< "	gl_Position		= vec4(vs_in_position, 0.0f, 1.0f);\n"
167 		<< "	vs_out_texCoord = vec3(vs_in_texCoord, 0.0f);\n"
168 		<< "}\n";
169 
170 	programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
171 
172 	if (numLayers > 1u)
173 	{
174 		const deInt32 maxVertices = 3u * numLayers;
175 
176 		// Create geometry shader
177 		std::ostringstream gs;
178 
179 		gs << "#version 440\n"
180 			<< "layout(triangles) in;\n"
181 			<< "layout(triangle_strip, max_vertices = " << static_cast<deInt32>(maxVertices) << ") out;\n"
182 			<< "\n"
183 			<< "in gl_PerVertex {\n"
184 			<< "	vec4  gl_Position;\n"
185 			<< "} gl_in[];\n"
186 			<< "out gl_PerVertex {\n"
187 			<< "	vec4  gl_Position;\n"
188 			<< "};\n"
189 			<< "layout(location = 0) in  highp vec3 gs_in_texCoord[];\n"
190 			<< "\n"
191 			<< "layout(location = 0) out highp vec3 gs_out_texCoord;\n"
192 			<< "\n"
193 			<< "void main (void)\n"
194 			<< "{\n"
195 			<< "	for (int layerNdx = 0; layerNdx < " << static_cast<deInt32>(numLayers) << "; ++layerNdx)\n"
196 			<< "	{\n"
197 			<< "		for (int vertexNdx = 0; vertexNdx < gl_in.length(); ++vertexNdx)\n"
198 			<< "		{\n"
199 			<< "			gl_Layer		= layerNdx;\n"
200 			<< "			gl_Position		= gl_in[vertexNdx].gl_Position;\n"
201 			<< "			gs_out_texCoord	= vec3(gs_in_texCoord[vertexNdx].xy, float(layerNdx));\n"
202 			<< "			EmitVertex();\n"
203 			<< "		}\n"
204 			<< "		EndPrimitive();\n"
205 			<< "	}\n"
206 			<< "}\n";
207 
208 		programCollection.glslSources.add("geometry_shader") << glu::GeometrySource(gs.str());
209 	}
210 
211 	// Create fragment shader
212 	std::ostringstream fs;
213 
214 	const std::string	typeImgComp		= getImageComponentTypeName(formatDescription);
215 	const std::string	typeImgCompVec4	= getImageComponentVec4TypeName(formatDescription);
216 
217 	SpirvVersion	spirvVersion	= SPIRV_VERSION_1_0;
218 	std::string		interfaceList	= "";
219 
220 	if (m_operand.find("Nontemporal") != std::string::npos)
221 	{
222 		spirvVersion	= SPIRV_VERSION_1_6;
223 		interfaceList	= " %uniformconst_image_sparse %uniformblock_instance";
224 	}
225 
226 	fs	<< "OpCapability Shader\n"
227 		<< "OpCapability SampledCubeArray\n"
228 		<< "OpCapability ImageCubeArray\n"
229 		<< "OpCapability SparseResidency\n"
230 		<< "OpCapability StorageImageExtendedFormats\n";
231 
232 	if (formatIsR64(m_format))
233 	{
234 		fs	<< "OpCapability Int64\n"
235 			<< "OpCapability Int64ImageEXT\n"
236 			<< "OpExtension \"SPV_EXT_shader_image_int64\"\n";
237 	}
238 
239 	fs	<< "%ext_import = OpExtInstImport \"GLSL.std.450\"\n"
240 		<< "OpMemoryModel Logical GLSL450\n"
241 		<< "OpEntryPoint Fragment %func_main \"main\" %varying_texCoord %output_texel %output_residency " << interfaceList << "\n"
242 		<< "OpExecutionMode %func_main OriginUpperLeft\n"
243 		<< "OpSource GLSL 440\n"
244 
245 		<< "OpName %func_main \"main\"\n"
246 
247 		<< "OpName %varying_texCoord \"varying_texCoord\"\n"
248 
249 		<< "OpName %output_texel \"out_texel\"\n"
250 		<< "OpName %output_residency \"out_residency\"\n"
251 
252 		<< "OpName %type_uniformblock \"LodBlock\"\n"
253 		<< "OpMemberName %type_uniformblock 0 \"lod\"\n"
254 		<< "OpMemberName %type_uniformblock 1 \"size\"\n"
255 		<< "OpName %uniformblock_instance \"lodInstance\"\n"
256 
257 		<< "OpName %uniformconst_image_sparse \"u_imageSparse\"\n"
258 
259 		<< "OpDecorate %varying_texCoord Location 0\n"
260 
261 		<< "OpDecorate %output_texel	 Location 0\n"
262 		<< "OpDecorate %output_residency Location 1\n"
263 
264 		<< "OpDecorate		 %type_uniformblock Block\n"
265 		<< "OpMemberDecorate %type_uniformblock 0 Offset 0\n"
266 		<< "OpMemberDecorate %type_uniformblock 1 Offset 8\n"
267 
268 		<< "OpDecorate %uniformconst_image_sparse DescriptorSet 0\n"
269 		<< "OpDecorate %uniformconst_image_sparse Binding " << BINDING_IMAGE_SPARSE << "\n"
270 
271 		<< "%type_void = OpTypeVoid\n"
272 		<< "%type_void_func = OpTypeFunction %type_void\n"
273 
274 		<< "%type_bool							= OpTypeBool\n"
275 		<< "%type_int							= OpTypeInt 32 1\n"
276 		<< "%type_uint							= OpTypeInt 32 0\n"
277 		<< "%type_float							= OpTypeFloat 32\n"
278 		<< "%type_vec2							= OpTypeVector %type_float 2\n"
279 		<< "%type_vec3							= OpTypeVector %type_float 3\n"
280 		<< "%type_vec4							= OpTypeVector %type_float 4\n"
281 		<< "%type_ivec4							= OpTypeVector %type_int 4\n"
282 		<< "%type_uvec4							= OpTypeVector %type_uint 4\n"
283 		<< "%type_uniformblock					= OpTypeStruct %type_uint %type_vec2\n";
284 
285 		if (formatIsR64(m_format))
286 		{
287 			fs	<< "%type_int64						= OpTypeInt 64 1\n"
288 				<< "%type_uint64					= OpTypeInt 64 0\n"
289 				<< "%type_i64vec2					= OpTypeVector %type_int64 2\n"
290 				<< "%type_i64vec3					= OpTypeVector %type_int64 3\n"
291 				<< "%type_i64vec4					= OpTypeVector %type_int64 4\n"
292 				<< "%type_u64vec3					= OpTypeVector %type_uint64 3\n"
293 				<< "%type_u64vec4					= OpTypeVector %type_uint64 4\n";
294 		}
295 
296 	fs	<< "%type_struct_int_img_comp_vec4		= OpTypeStruct %type_int "<< typeImgCompVec4 << "\n"
297 		<< "%type_input_vec3					= OpTypePointer Input %type_vec3\n"
298 		<< "%type_input_float					= OpTypePointer Input %type_float\n";
299 
300 	if (formatIsR64(m_format))
301 		fs	<< "%type_output_img_comp_vec4			= OpTypePointer Output " << "%type_ivec4" << "\n";
302 	else
303 		fs	<< "%type_output_img_comp_vec4			= OpTypePointer Output " << typeImgCompVec4 << "\n";
304 
305 	fs	<< "%type_output_uint					= OpTypePointer Output %type_uint\n"
306 
307 		<< "%type_function_int					= OpTypePointer Function %type_int\n"
308 		<< "%type_function_img_comp_vec4		= OpTypePointer Function " << typeImgCompVec4 << "\n"
309 		<< "%type_function_int_img_comp_vec4	= OpTypePointer Function %type_struct_int_img_comp_vec4\n"
310 
311 		<< "%type_pushconstant_uniformblock				= OpTypePointer PushConstant %type_uniformblock\n"
312 		<< "%type_pushconstant_uniformblock_member_lod	= OpTypePointer PushConstant %type_uint\n"
313 		<< "%type_pushconstant_uniformblock_member_size	= OpTypePointer PushConstant %type_vec2\n"
314 
315 		<< "%type_image_sparse				= " << getOpTypeImageSparse(m_imageType, m_format, typeImgComp, true) << "\n"
316 		<< "%type_sampled_image_sparse		= OpTypeSampledImage %type_image_sparse\n"
317 		<< "%type_uniformconst_image_sparse = OpTypePointer UniformConstant %type_sampled_image_sparse\n"
318 
319 		<< "%varying_texCoord			= OpVariable %type_input_vec3 Input\n"
320 
321 		<< "%output_texel				= OpVariable %type_output_img_comp_vec4 Output\n"
322 		<< "%output_residency			= OpVariable %type_output_uint Output\n"
323 
324 		<< "%uniformconst_image_sparse	= OpVariable %type_uniformconst_image_sparse UniformConstant\n"
325 
326 		<< "%uniformblock_instance  = OpVariable %type_pushconstant_uniformblock PushConstant\n"
327 
328 		// Declare constants
329 		<< "%constant_uint_0				= OpConstant %type_uint 0\n"
330 		<< "%constant_uint_1				= OpConstant %type_uint 1\n"
331 		<< "%constant_uint_2				= OpConstant %type_uint 2\n"
332 		<< "%constant_uint_3				= OpConstant %type_uint 3\n"
333 		<< "%constant_int_0					= OpConstant %type_int  0\n"
334 		<< "%constant_int_1					= OpConstant %type_int  1\n"
335 		<< "%constant_int_2					= OpConstant %type_int  2\n"
336 		<< "%constant_int_3					= OpConstant %type_int  3\n"
337 		<< "%constant_float_0				= OpConstant %type_float 0.0\n"
338 		<< "%constant_float_half			= OpConstant %type_float 0.5\n"
339 		<< "%constant_texel_resident		= OpConstant %type_uint " << MEMORY_BLOCK_BOUND_VALUE << "\n"
340 		<< "%constant_texel_not_resident	= OpConstant %type_uint " << MEMORY_BLOCK_NOT_BOUND_VALUE << "\n"
341 
342 		// Call main function
343 		<< "%func_main		 = OpFunction %type_void None %type_void_func\n"
344 		<< "%label_func_main = OpLabel\n"
345 
346 		<< "%local_image_sparse = OpLoad %type_sampled_image_sparse %uniformconst_image_sparse\n"
347 
348 		<< "%texCoord = OpLoad %type_vec3 %varying_texCoord\n"
349 
350 		<< "%local_texCoord_x = OpCompositeExtract %type_float %texCoord 0\n"
351 		<< "%local_texCoord_y = OpCompositeExtract %type_float %texCoord 1\n"
352 		<< "%local_texCoord_z = OpCompositeExtract %type_float %texCoord 2\n"
353 
354 		<< "%local_texCoord_xy	= OpCompositeConstruct %type_vec2 %local_texCoord_x %local_texCoord_y\n"
355 		<< "%local_texCoord_xyz = OpCompositeConstruct %type_vec3 %local_texCoord_x %local_texCoord_y %local_texCoord_z\n"
356 
357 		<< "%access_uniformblock_member_uint_lod = OpAccessChain %type_pushconstant_uniformblock_member_lod %uniformblock_instance %constant_int_0\n"
358 		<< "%local_uniformblock_member_uint_lod  = OpLoad %type_uint %access_uniformblock_member_uint_lod\n"
359 		<< "%local_uniformblock_member_float_lod = OpConvertUToF %type_float %local_uniformblock_member_uint_lod\n"
360 		<< "%access_uniformblock_member_size	 = OpAccessChain %type_pushconstant_uniformblock_member_size %uniformblock_instance %constant_int_1\n"
361 		<< "%local_uniformblock_member_size		 = OpLoad %type_vec2 %access_uniformblock_member_size\n"
362 
363 		<< sparseImageOpString("%local_sparse_op_result", "%type_struct_int_img_comp_vec4", "%local_image_sparse", coordString, "%local_uniformblock_member_float_lod") << "\n"
364 
365 		// Load texel value
366 		<< "%local_img_comp_vec4 = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_op_result 1\n";
367 
368 		if (formatIsR64(m_format))
369 		{
370 			fs	<< "%local_img_comp32b = OpSConvert %type_ivec4 %local_img_comp_vec4\n"
371 				<< "OpStore %output_texel %local_img_comp32b\n";
372 		}
373 		else
374 		{
375 			fs	<< "OpStore %output_texel %local_img_comp_vec4\n";
376 		}
377 
378 		// Load residency code
379 	fs	<< "%local_residency_code = OpCompositeExtract %type_int %local_sparse_op_result 0\n"
380 
381 		// Check if loaded texel is placed in resident memory
382 		<< "%local_texel_resident = OpImageSparseTexelsResident %type_bool %local_residency_code\n"
383 		<< "OpSelectionMerge %branch_texel_resident None\n"
384 		<< "OpBranchConditional %local_texel_resident %label_texel_resident %label_texel_not_resident\n"
385 		<< "%label_texel_resident = OpLabel\n"
386 
387 		// Loaded texel is in resident memory
388 		<< "OpStore %output_residency %constant_texel_resident\n"
389 
390 		<< "OpBranch %branch_texel_resident\n"
391 		<< "%label_texel_not_resident = OpLabel\n"
392 
393 		// Loaded texel is not in resident memory
394 		<< "OpStore %output_residency %constant_texel_not_resident\n"
395 
396 		<< "OpBranch %branch_texel_resident\n"
397 		<< "%branch_texel_resident = OpLabel\n"
398 
399 		<< "OpReturn\n"
400 		<< "OpFunctionEnd\n";
401 
402 	programCollection.spirvAsmSources.add("fragment_shader") << fs.str()
403 		<< vk::SpirVAsmBuildOptions(programCollection.usedVulkanVersion, spirvVersion);
404 
405 }
406 
sparseImageOpString(const std::string & resultVariable,const std::string & resultType,const std::string & image,const std::string & coord,const std::string & miplevel) const407 std::string	SparseCaseOpImageSparseSampleExplicitLod::sparseImageOpString (const std::string& resultVariable,
408 																		   const std::string& resultType,
409 																		   const std::string& image,
410 																		   const std::string& coord,
411 																		   const std::string& miplevel) const
412 {
413 	std::ostringstream	src;
414 	std::string			additionalOperand = (m_operand.empty() ? " " : (std::string("|") + m_operand + " "));
415 
416 	src << resultVariable << " = OpImageSparseSampleExplicitLod " << resultType << " " << image << " " << coord << " Lod" << additionalOperand << miplevel << "\n";
417 
418 	return src.str();
419 }
420 
sparseImageOpString(const std::string & resultVariable,const std::string & resultType,const std::string & image,const std::string & coord,const std::string & miplevel) const421 std::string	SparseCaseOpImageSparseSampleImplicitLod::sparseImageOpString (const std::string& resultVariable,
422 																		   const std::string& resultType,
423 																		   const std::string& image,
424 																		   const std::string& coord,
425 																		   const std::string& miplevel) const
426 {
427 	DE_UNREF(miplevel);
428 
429 	std::ostringstream	src;
430 
431 	src << resultVariable << " = OpImageSparseSampleImplicitLod " << resultType << " " << image << " " << coord << " " << m_operand << "\n";
432 
433 	return src.str();
434 }
435 
sparseImageOpString(const std::string & resultVariable,const std::string & resultType,const std::string & image,const std::string & coord,const std::string & miplevel) const436 std::string	SparseCaseOpImageSparseGather::sparseImageOpString (const std::string& resultVariable,
437 																const std::string& resultType,
438 																const std::string& image,
439 																const std::string& coord,
440 																const std::string& miplevel) const
441 {
442 	DE_UNREF(miplevel);
443 
444 	std::ostringstream	src;
445 
446 	const PlanarFormatDescription	formatDescription	= getPlanarFormatDescription(m_format);
447 	const std::string				typeImgComp			= getImageComponentTypeName(formatDescription);
448 	const std::string				typeImgCompVec4		= getImageComponentVec4TypeName(formatDescription);
449 
450 	// Bias the coord value by half a texel, so we sample from center of 2x2 gather rectangle
451 
452 	src << "%local_image_width	= OpCompositeExtract %type_float %local_uniformblock_member_size 0\n";
453 	src << "%local_image_height	= OpCompositeExtract %type_float %local_uniformblock_member_size 1\n";
454 	src << "%local_coord_x_bias	= OpFDiv %type_float %constant_float_half %local_image_width\n";
455 	src << "%local_coord_y_bias	= OpFDiv %type_float %constant_float_half %local_image_height\n";
456 
457 	switch (m_imageType)
458 	{
459 		case IMAGE_TYPE_2D:
460 		{
461 			src << "%local_coord_bias	= OpCompositeConstruct %type_vec2 %local_coord_x_bias %local_coord_y_bias\n";
462 			src << "%local_coord_biased	= OpFAdd %type_vec2 " << coord << " %local_coord_bias\n";
463 
464 			break;
465 		}
466 
467 		case IMAGE_TYPE_2D_ARRAY:
468 		case IMAGE_TYPE_3D:
469 		{
470 			src << "%local_coord_bias	= OpCompositeConstruct %type_vec3 %local_coord_x_bias %local_coord_y_bias %constant_float_0\n";
471 			src << "%local_coord_biased	= OpFAdd %type_vec3 " << coord << " %local_coord_bias\n";
472 
473 			break;
474 		}
475 
476 		default:
477 		{
478 			DE_FATAL("Unexpected image type");
479 		}
480 	}
481 
482 	src << "%local_sparse_gather_result_x = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_0 " + m_operand + "\n";
483 	src << "%local_sparse_gather_result_y = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_1 " + m_operand + "\n";
484 	src << "%local_sparse_gather_result_z = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_2 " + m_operand + "\n";
485 	src << "%local_sparse_gather_result_w = OpImageSparseGather " << resultType << " " << image << " %local_coord_biased %constant_int_3 " + m_operand + "\n";
486 
487 	src << "%local_gather_residency_code = OpCompositeExtract %type_int %local_sparse_gather_result_x 0\n";
488 
489 	src << "%local_gather_texels_x = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_x 1\n";
490 	src << "%local_gather_texels_y = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_y 1\n";
491 	src << "%local_gather_texels_z = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_z 1\n";
492 	src << "%local_gather_texels_w = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_gather_result_w 1\n";
493 
494 	src << "%local_gather_primary_texel_x = OpCompositeExtract " << typeImgComp << " %local_gather_texels_x 3\n";
495 	src << "%local_gather_primary_texel_y = OpCompositeExtract " << typeImgComp << " %local_gather_texels_y 3\n";
496 	src << "%local_gather_primary_texel_z = OpCompositeExtract " << typeImgComp << " %local_gather_texels_z 3\n";
497 	src << "%local_gather_primary_texel_w = OpCompositeExtract " << typeImgComp << " %local_gather_texels_w 3\n";
498 
499 	src << "%local_gather_primary_texel	= OpCompositeConstruct " << typeImgCompVec4 << " %local_gather_primary_texel_x %local_gather_primary_texel_y %local_gather_primary_texel_z %local_gather_primary_texel_w\n";
500 	src << resultVariable << " = OpCompositeConstruct " << resultType << " %local_gather_residency_code %local_gather_primary_texel\n";
501 
502 	return src.str();
503 }
504 
505 class SparseShaderIntrinsicsInstanceSampledBase : public SparseShaderIntrinsicsInstanceBase
506 {
507 public:
SparseShaderIntrinsicsInstanceSampledBase(Context & context,const SpirVFunction function,const ImageType imageType,const tcu::UVec3 & imageSize,const VkFormat format)508 	SparseShaderIntrinsicsInstanceSampledBase		(Context&				context,
509 													 const SpirVFunction	function,
510 													 const ImageType		imageType,
511 													 const tcu::UVec3&		imageSize,
512 													 const VkFormat			format)
513 		: SparseShaderIntrinsicsInstanceBase(context, function, imageType, imageSize, format) {}
514 
515 	VkImageUsageFlags		imageSparseUsageFlags	(void) const;
516 	VkImageUsageFlags		imageOutputUsageFlags	(void) const;
517 
518 	VkQueueFlags			getQueueFlags			(void) const;
519 
520 	void					recordCommands			(const VkCommandBuffer		commandBuffer,
521 													 const VkImageCreateInfo&	imageSparseInfo,
522 													 const VkImage				imageSparse,
523 													 const VkImage				imageTexels,
524 													 const VkImage				imageResidency);
525 
526 	virtual void			checkSupport			(VkImageCreateInfo imageSparseInfo) const;
527 
528 	virtual VkImageSubresourceRange	sampledImageRangeToBind(const VkImageCreateInfo& imageSparseInfo, const deUint32 mipLevel) const = 0;
529 
530 private:
531 	typedef de::SharedPtr< vk::Unique<VkFramebuffer> > VkFramebufferSp;
532 
533 	Move<VkBuffer>					m_vertexBuffer;
534 	de::MovePtr<Allocation>			m_vertexBufferAlloc;
535 	std::vector<VkFramebufferSp>	m_framebuffers;
536 	Move<VkRenderPass>				m_renderPass;
537 	Move<VkSampler>					m_sampler;
538 };
539 
imageSparseUsageFlags(void) const540 VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageSparseUsageFlags (void) const
541 {
542 	return VK_IMAGE_USAGE_SAMPLED_BIT;
543 }
544 
imageOutputUsageFlags(void) const545 VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageOutputUsageFlags (void) const
546 {
547 	return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
548 }
549 
getQueueFlags(void) const550 VkQueueFlags SparseShaderIntrinsicsInstanceSampledBase::getQueueFlags (void) const
551 {
552 	return VK_QUEUE_GRAPHICS_BIT;
553 }
554 
checkSupport(VkImageCreateInfo imageSparseInfo) const555 void SparseShaderIntrinsicsInstanceSampledBase::checkSupport(VkImageCreateInfo imageSparseInfo) const
556 {
557 	const InstanceInterface&		 instance			= m_context.getInstanceInterface();
558 	const VkPhysicalDevice			 physicalDevice		= m_context.getPhysicalDevice();
559 	const VkPhysicalDeviceProperties deviceProperties	= getPhysicalDeviceProperties(instance, physicalDevice);
560 
561 	SparseShaderIntrinsicsInstanceBase::checkSupport(imageSparseInfo);
562 
563 	if (imageSparseInfo.extent.width  > deviceProperties.limits.maxFramebufferWidth  ||
564 		imageSparseInfo.extent.height > deviceProperties.limits.maxFramebufferHeight ||
565 		imageSparseInfo.arrayLayers   > deviceProperties.limits.maxFramebufferLayers)
566 	{
567 		TCU_THROW(NotSupportedError, "Image size exceeds allowed framebuffer dimensions");
568 	}
569 
570 	// Check if device supports image format for sampled images
571 	if (!checkImageFormatFeatureSupport(instance, physicalDevice, imageSparseInfo.format, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
572 		TCU_THROW(NotSupportedError, "Device does not support image format for sampled images");
573 
574 	// Check if device supports image format for color attachment
575 	if (!checkImageFormatFeatureSupport(instance, physicalDevice, imageSparseInfo.format, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
576 		TCU_THROW(NotSupportedError, "Device does not support image format for color attachment");
577 
578 	// Make sure device supports VK_FORMAT_R32_UINT format for color attachment
579 	if (!checkImageFormatFeatureSupport(instance, physicalDevice, mapTextureFormat(m_residencyFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
580 		TCU_THROW(TestError, "Device does not support VK_FORMAT_R32_UINT format for color attachment");
581 }
582 
recordCommands(const VkCommandBuffer commandBuffer,const VkImageCreateInfo & imageSparseInfo,const VkImage imageSparse,const VkImage imageTexels,const VkImage imageResidency)583 void SparseShaderIntrinsicsInstanceSampledBase::recordCommands (const VkCommandBuffer		commandBuffer,
584 																const VkImageCreateInfo&	imageSparseInfo,
585 																const VkImage				imageSparse,
586 																const VkImage				imageTexels,
587 																const VkImage				imageResidency)
588 {
589 	const InstanceInterface&		 instance			= m_context.getInstanceInterface();
590 	const VkPhysicalDevice			 physicalDevice		= m_context.getPhysicalDevice();
591 	const DeviceInterface&			 deviceInterface	= getDeviceInterface();
592 
593 	// Create buffer storing vertex data
594 	std::vector<tcu::Vec2> vertexData;
595 
596 	vertexData.push_back(tcu::Vec2(-1.0f,-1.0f));
597 	vertexData.push_back(tcu::Vec2( 0.0f, 0.0f));
598 
599 	vertexData.push_back(tcu::Vec2(-1.0f, 1.0f));
600 	vertexData.push_back(tcu::Vec2( 0.0f, 1.0f));
601 
602 	vertexData.push_back(tcu::Vec2( 1.0f,-1.0f));
603 	vertexData.push_back(tcu::Vec2( 1.0f, 0.0f));
604 
605 	vertexData.push_back(tcu::Vec2( 1.0f, 1.0f));
606 	vertexData.push_back(tcu::Vec2( 1.0f, 1.0f));
607 
608 	const VkDeviceSize			vertexDataSizeInBytes	= sizeInBytes(vertexData);
609 	const VkBufferCreateInfo	vertexBufferCreateInfo	= makeBufferCreateInfo(vertexDataSizeInBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
610 
611 	m_vertexBuffer		= createBuffer(deviceInterface, getDevice(), &vertexBufferCreateInfo);
612 	m_vertexBufferAlloc	= bindBuffer(deviceInterface, getDevice(), getAllocator(), *m_vertexBuffer, MemoryRequirement::HostVisible);
613 
614 	deMemcpy(m_vertexBufferAlloc->getHostPtr(), &vertexData[0], static_cast<std::size_t>(vertexDataSizeInBytes));
615 	flushAlloc(deviceInterface, getDevice(), *m_vertexBufferAlloc);
616 
617 	// Create render pass
618 	const VkAttachmentDescription texelsAttachmentDescription =
619 	{
620 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
621 		imageSparseInfo.format,								// VkFormat							format;
622 		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
623 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
624 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
625 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
626 		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
627 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
628 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
629 	};
630 
631 	const VkAttachmentDescription residencyAttachmentDescription =
632 	{
633 		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
634 		mapTextureFormat(m_residencyFormat),				// VkFormat							format;
635 		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
636 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
637 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
638 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
639 		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
640 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
641 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
642 	};
643 
644 	const VkAttachmentDescription colorAttachmentsDescription[] = { texelsAttachmentDescription, residencyAttachmentDescription };
645 
646 	const VkAttachmentReference texelsAttachmentReference =
647 	{
648 		0u,													// deUint32			attachment;
649 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
650 	};
651 
652 	const VkAttachmentReference residencyAttachmentReference =
653 	{
654 		1u,													// deUint32			attachment;
655 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
656 	};
657 
658 	const VkAttachmentReference colorAttachmentsReference[] = { texelsAttachmentReference, residencyAttachmentReference };
659 
660 	const VkAttachmentReference depthAttachmentReference =
661 	{
662 		VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
663 		VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
664 	};
665 
666 	const VkSubpassDescription subpassDescription =
667 	{
668 		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
669 		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
670 		0u,													// deUint32							inputAttachmentCount;
671 		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
672 		2u,													// deUint32							colorAttachmentCount;
673 		colorAttachmentsReference,							// const VkAttachmentReference*		pColorAttachments;
674 		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
675 		&depthAttachmentReference,							// const VkAttachmentReference*		pDepthStencilAttachment;
676 		0u,													// deUint32							preserveAttachmentCount;
677 		DE_NULL												// const deUint32*					pPreserveAttachments;
678 	};
679 
680 	const VkRenderPassCreateInfo renderPassInfo =
681 	{
682 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
683 		DE_NULL,											// const void*						pNext;
684 		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
685 		2u,													// deUint32							attachmentCount;
686 		colorAttachmentsDescription,						// const VkAttachmentDescription*	pAttachments;
687 		1u,													// deUint32							subpassCount;
688 		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
689 		0u,													// deUint32							dependencyCount;
690 		DE_NULL												// const VkSubpassDependency*		pDependencies;
691 	};
692 
693 	m_renderPass = createRenderPass(deviceInterface, getDevice(), &renderPassInfo);
694 
695 	// Create descriptor set layout
696 	DescriptorSetLayoutBuilder descriptorLayerBuilder;
697 
698 	descriptorLayerBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
699 
700 	const Unique<VkDescriptorSetLayout> descriptorSetLayout(descriptorLayerBuilder.build(deviceInterface, getDevice()));
701 
702 	// Create descriptor pool
703 	DescriptorPoolBuilder descriptorPoolBuilder;
704 
705 	descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageSparseInfo.mipLevels);
706 
707 	descriptorPool = descriptorPoolBuilder.build(deviceInterface, getDevice(), VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, imageSparseInfo.mipLevels);
708 
709 	VkSamplerCreateInfo	samplerCreateInfo =
710 	{
711 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
712 		DE_NULL,
713 		(VkSamplerCreateFlags)0,
714 		mapFilterMode(tcu::Sampler::NEAREST),					// magFilter
715 		mapFilterMode(tcu::Sampler::NEAREST_MIPMAP_NEAREST),	// minFilter
716 		mapMipmapMode(tcu::Sampler::NEAREST_MIPMAP_NEAREST),	// mipMode
717 		mapWrapMode(tcu::Sampler::REPEAT_GL),					// addressU
718 		mapWrapMode(tcu::Sampler::REPEAT_GL),					// addressV
719 		mapWrapMode(tcu::Sampler::REPEAT_GL),					// addressW
720 		0.0f,													// mipLodBias
721 		VK_FALSE,												// anisotropyEnable
722 		1.0f,													// maxAnisotropy
723 		VK_FALSE,												// compareEnable
724 		mapCompareMode(tcu::Sampler::COMPAREMODE_ALWAYS),		// compareOp
725 		0.0f,													// minLod
726 		1000.0f,												// maxLod
727 		VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,					// borderColor
728 		VK_FALSE,												// unnormalizedCoords
729 	};
730 	m_sampler = createSampler(deviceInterface, getDevice(), &samplerCreateInfo);
731 
732 	struct PushConstants
733 	{
734 		deUint32	lod;
735 		deUint32	padding;			// padding needed to satisfy std430 rules
736 		float		lodWidth;
737 		float		lodHeight;
738 	};
739 
740 	// Create pipeline layout
741 	const VkPushConstantRange lodConstantRange =
742 	{
743 		VK_SHADER_STAGE_FRAGMENT_BIT,	// VkShaderStageFlags	stageFlags;
744 		0u,								// deUint32			offset;
745 		sizeof(PushConstants),			// deUint32			size;
746 	};
747 
748 	const VkPipelineLayoutCreateInfo pipelineLayoutParams =
749 	{
750 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
751 		DE_NULL,											// const void*						pNext;
752 		0u,													// VkPipelineLayoutCreateFlags		flags;
753 		1u,													// deUint32							setLayoutCount;
754 		&descriptorSetLayout.get(),							// const VkDescriptorSetLayout*		pSetLayouts;
755 		1u,													// deUint32							pushConstantRangeCount;
756 		&lodConstantRange,									// const VkPushConstantRange*		pPushConstantRanges;
757 	};
758 
759 	pipelineLayout = createPipelineLayout(deviceInterface, getDevice(), &pipelineLayoutParams);
760 
761 	// Create graphics pipeline
762 	{
763 		Move<VkShaderModule> vertexModule	= createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0);
764 		Move<VkShaderModule> fragmentModule	= createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0);
765 		Move<VkShaderModule> geometryModule;
766 
767 		if (imageSparseInfo.arrayLayers > 1u)
768 		{
769 			requireFeatures(instance, physicalDevice, FEATURE_GEOMETRY_SHADER);
770 			geometryModule = createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("geometry_shader"), (VkShaderModuleCreateFlags)0);
771 		}
772 
773 		pipelines.push_back(makeVkSharedPtr(makeGraphicsPipeline(
774 			deviceInterface, getDevice(), *pipelineLayout, *m_renderPass, *vertexModule, *fragmentModule, *geometryModule)));
775 	}
776 
777 	const VkPipeline graphicsPipeline = **pipelines[0];
778 
779 	{
780 		const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers);
781 
782 		VkImageMemoryBarrier imageShaderAccessBarriers[3];
783 
784 		imageShaderAccessBarriers[0] = makeImageMemoryBarrier
785 		(
786 			VK_ACCESS_TRANSFER_WRITE_BIT,
787 			VK_ACCESS_SHADER_READ_BIT,
788 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
789 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
790 			imageSparse,
791 			fullImageSubresourceRange
792 		);
793 
794 		imageShaderAccessBarriers[1] = makeImageMemoryBarrier
795 		(
796 			0u,
797 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
798 			VK_IMAGE_LAYOUT_UNDEFINED,
799 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
800 			imageTexels,
801 			fullImageSubresourceRange
802 		);
803 
804 		imageShaderAccessBarriers[2] = makeImageMemoryBarrier
805 		(
806 			0u,
807 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
808 			VK_IMAGE_LAYOUT_UNDEFINED,
809 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
810 			imageResidency,
811 			fullImageSubresourceRange
812 		);
813 
814 		deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 3u, imageShaderAccessBarriers);
815 	}
816 
817 	imageSparseViews.resize(imageSparseInfo.mipLevels);
818 	imageTexelsViews.resize(imageSparseInfo.mipLevels);
819 	imageResidencyViews.resize(imageSparseInfo.mipLevels);
820 	m_framebuffers.resize(imageSparseInfo.mipLevels);
821 	descriptorSets.resize(imageSparseInfo.mipLevels);
822 
823 	std::vector<VkClearValue> clearValues;
824 	clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
825 	clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
826 
827 	for (deUint32 mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx)
828 	{
829 		const VkExtent3D				mipLevelSize	= mipLevelExtents(imageSparseInfo.extent, mipLevelNdx);
830 		const VkRect2D					renderArea		= makeRect2D(mipLevelSize);
831 		const VkViewport				viewport		= makeViewport(mipLevelSize);
832 		const VkImageSubresourceRange	mipLevelRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevelNdx, 1u, 0u, imageSparseInfo.arrayLayers);
833 
834 		// Create color attachments image views
835 		imageTexelsViews[mipLevelNdx]		= makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageTexels, mapImageViewType(m_imageType), imageSparseInfo.format, mipLevelRange));
836 		imageResidencyViews[mipLevelNdx]	= makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageResidency, mapImageViewType(m_imageType), mapTextureFormat(m_residencyFormat), mipLevelRange));
837 
838 		const VkImageView attachmentsViews[] = { **imageTexelsViews[mipLevelNdx], **imageResidencyViews[mipLevelNdx] };
839 
840 		// Create framebuffer
841 		const VkFramebufferCreateInfo framebufferInfo =
842 		{
843 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
844 			DE_NULL,									// const void*				pNext;
845 			(VkFramebufferCreateFlags)0,				// VkFramebufferCreateFlags	flags;
846 			*m_renderPass,								// VkRenderPass				renderPass;
847 			2u,											// uint32_t					attachmentCount;
848 			attachmentsViews,							// const VkImageView*		pAttachments;
849 			mipLevelSize.width,							// uint32_t					width;
850 			mipLevelSize.height,						// uint32_t					height;
851 			imageSparseInfo.arrayLayers,				// uint32_t					layers;
852 		};
853 
854 		m_framebuffers[mipLevelNdx] = makeVkSharedPtr(createFramebuffer(deviceInterface, getDevice(), &framebufferInfo));
855 
856 		// Create descriptor set
857 		descriptorSets[mipLevelNdx] = makeVkSharedPtr(makeDescriptorSet(deviceInterface, getDevice(), *descriptorPool, *descriptorSetLayout));
858 		const VkDescriptorSet descriptorSet = **descriptorSets[mipLevelNdx];
859 
860 		// Update descriptor set
861 		const VkImageSubresourceRange sparseImageSubresourceRange = sampledImageRangeToBind(imageSparseInfo, mipLevelNdx);
862 
863 		imageSparseViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageSparse, mapImageViewType(m_imageType), imageSparseInfo.format, sparseImageSubresourceRange));
864 
865 		const VkDescriptorImageInfo imageSparseDescInfo = makeDescriptorImageInfo(*m_sampler, **imageSparseViews[mipLevelNdx], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
866 
867 		DescriptorSetUpdateBuilder descriptorUpdateBuilder;
868 
869 		descriptorUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(BINDING_IMAGE_SPARSE), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSparseDescInfo);
870 		descriptorUpdateBuilder.update(deviceInterface, getDevice());
871 
872 		beginRenderPass(deviceInterface, commandBuffer, *m_renderPass, **m_framebuffers[mipLevelNdx], renderArea, (deUint32)clearValues.size(), &clearValues[0]);
873 
874 		// Bind graphics pipeline
875 		deviceInterface.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
876 
877 		// Bind descriptor set
878 		deviceInterface.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
879 
880 		// Bind vertex buffer
881 		{
882 			const VkDeviceSize offset = 0ull;
883 			deviceInterface.cmdBindVertexBuffers(commandBuffer, 0u, 1u, &m_vertexBuffer.get(), &offset);
884 		}
885 
886 		// Bind Viewport
887 		deviceInterface.cmdSetViewport(commandBuffer, 0u, 1u, &viewport);
888 
889 		// Bind Scissor Rectangle
890 		deviceInterface.cmdSetScissor(commandBuffer, 0u, 1u, &renderArea);
891 
892 		const PushConstants pushConstants =
893 		{
894 			mipLevelNdx,
895 			0u,											// padding
896 			static_cast<float>(mipLevelSize.width),
897 			static_cast<float>(mipLevelSize.height)
898 		};
899 
900 		// Update push constants
901 		deviceInterface.cmdPushConstants(commandBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(PushConstants), &pushConstants);
902 
903 		// Draw full screen quad
904 		deviceInterface.cmdDraw(commandBuffer, 4u, 1u, 0u, 0u);
905 
906 		// End render pass
907 		endRenderPass(deviceInterface, commandBuffer);
908 	}
909 
910 	{
911 		const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers);
912 
913 		VkImageMemoryBarrier imageOutputTransferSrcBarriers[2];
914 
915 		imageOutputTransferSrcBarriers[0] = makeImageMemoryBarrier
916 		(
917 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
918 			VK_ACCESS_TRANSFER_READ_BIT,
919 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
920 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
921 			imageTexels,
922 			fullImageSubresourceRange
923 		);
924 
925 		imageOutputTransferSrcBarriers[1] = makeImageMemoryBarrier
926 		(
927 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
928 			VK_ACCESS_TRANSFER_READ_BIT,
929 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
930 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
931 			imageResidency,
932 			fullImageSubresourceRange
933 		);
934 
935 		deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputTransferSrcBarriers);
936 	}
937 }
938 
939 class SparseShaderIntrinsicsInstanceSampledExplicit : public SparseShaderIntrinsicsInstanceSampledBase
940 {
941 public:
SparseShaderIntrinsicsInstanceSampledExplicit(Context & context,const SpirVFunction function,const ImageType imageType,const tcu::UVec3 & imageSize,const VkFormat format)942 	SparseShaderIntrinsicsInstanceSampledExplicit	(Context&				context,
943 													 const SpirVFunction	function,
944 													 const ImageType		imageType,
945 													 const tcu::UVec3&		imageSize,
946 													 const VkFormat			format)
947 		: SparseShaderIntrinsicsInstanceSampledBase(context, function, imageType, imageSize, format) {}
948 
sampledImageRangeToBind(const VkImageCreateInfo & imageSparseInfo,const deUint32 mipLevel) const949 	VkImageSubresourceRange sampledImageRangeToBind (const VkImageCreateInfo&	imageSparseInfo,
950 													 const deUint32				mipLevel) const
951 	{
952 		DE_UNREF(mipLevel);
953 		return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers);
954 	}
955 };
956 
createInstance(Context & context) const957 TestInstance* SparseShaderIntrinsicsCaseSampledExplicit::createInstance (Context& context) const
958 {
959 	return new SparseShaderIntrinsicsInstanceSampledExplicit(context, m_function, m_imageType, m_imageSize, m_format);
960 }
961 
962 class SparseShaderIntrinsicsInstanceSampledImplicit : public SparseShaderIntrinsicsInstanceSampledBase
963 {
964 public:
SparseShaderIntrinsicsInstanceSampledImplicit(Context & context,const SpirVFunction function,const ImageType imageType,const tcu::UVec3 & imageSize,const VkFormat format)965 	SparseShaderIntrinsicsInstanceSampledImplicit	(Context&				context,
966 													 const SpirVFunction	function,
967 													 const ImageType		imageType,
968 													 const tcu::UVec3&		imageSize,
969 													 const VkFormat			format)
970 		: SparseShaderIntrinsicsInstanceSampledBase(context, function, imageType, imageSize, format) {}
971 
sampledImageRangeToBind(const VkImageCreateInfo & imageSparseInfo,const deUint32 mipLevel) const972 	VkImageSubresourceRange	sampledImageRangeToBind	(const VkImageCreateInfo&	imageSparseInfo,
973 													 const deUint32				mipLevel) const
974 	{
975 		return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, 0u, imageSparseInfo.arrayLayers);
976 	}
977 };
978 
createInstance(Context & context) const979 TestInstance* SparseShaderIntrinsicsCaseSampledImplicit::createInstance (Context& context) const
980 {
981 	return new SparseShaderIntrinsicsInstanceSampledImplicit(context, m_function, m_imageType, m_imageSize, m_format);
982 }
983 
984 } // sparse
985 } // vkt
986