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