Merge pull request #276 from Ella-0/master
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / sparse_resources / vktSparseResourcesShaderIntrinsicsSampled.cpp
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
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
144 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
396 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
409 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
424 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:
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
528 VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageSparseUsageFlags (void) const
529 {
530         return VK_IMAGE_USAGE_SAMPLED_BIT;
531 }
532
533 VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageOutputUsageFlags (void) const
534 {
535         return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
536 }
537
538 VkQueueFlags SparseShaderIntrinsicsInstanceSampledBase::getQueueFlags (void) const
539 {
540         return VK_QUEUE_GRAPHICS_BIT;
541 }
542
543 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
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:
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
937         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
945 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:
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
960         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
967 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