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