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