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
31using namespace vk;
32
33namespace vkt
34{
35namespace sparse
36{
37namespace
38{
39
40Move<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
144void 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
407std::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
421std::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
436std::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
505class SparseShaderIntrinsicsInstanceSampledBase : public SparseShaderIntrinsicsInstanceBase
506{
507public:
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
530private:
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
540VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageSparseUsageFlags (void) const
541{
542	return VK_IMAGE_USAGE_SAMPLED_BIT;
543}
544
545VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageOutputUsageFlags (void) const
546{
547	return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
548}
549
550VkQueueFlags SparseShaderIntrinsicsInstanceSampledBase::getQueueFlags (void) const
551{
552	return VK_QUEUE_GRAPHICS_BIT;
553}
554
555void 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
583void 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
939class SparseShaderIntrinsicsInstanceSampledExplicit : public SparseShaderIntrinsicsInstanceSampledBase
940{
941public:
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
949	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
957TestInstance* SparseShaderIntrinsicsCaseSampledExplicit::createInstance (Context& context) const
958{
959	return new SparseShaderIntrinsicsInstanceSampledExplicit(context, m_function, m_imageType, m_imageSize, m_format);
960}
961
962class SparseShaderIntrinsicsInstanceSampledImplicit : public SparseShaderIntrinsicsInstanceSampledBase
963{
964public:
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
972	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
979TestInstance* 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