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