Update Vulkan CTS to version 1.0.2.3 am: 148890e79f
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / sparse_resources / vktSparseResourcesShaderIntrinsicsStorage.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  vktSparseResourcesShaderIntrinsicsStorage.cpp
21  * \brief Sparse Resources Shader Intrinsics for storage images
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktSparseResourcesShaderIntrinsicsStorage.hpp"
25
26 using namespace vk;
27
28 namespace vkt
29 {
30 namespace sparse
31 {
32
33 tcu::UVec3 computeWorkGroupSize (const tcu::UVec3& gridSize)
34 {
35         const deUint32          maxComputeWorkGroupInvocations  = 128u;
36         const tcu::UVec3        maxComputeWorkGroupSize                 = tcu::UVec3(128u, 128u, 64u);
37
38         const deUint32 xWorkGroupSize = std::min(std::min(gridSize.x(), maxComputeWorkGroupSize.x()), maxComputeWorkGroupInvocations);
39         const deUint32 yWorkGroupSize = std::min(std::min(gridSize.y(), maxComputeWorkGroupSize.y()), maxComputeWorkGroupInvocations / xWorkGroupSize);
40         const deUint32 zWorkGroupSize = std::min(std::min(gridSize.z(), maxComputeWorkGroupSize.z()), maxComputeWorkGroupInvocations / (xWorkGroupSize*yWorkGroupSize));
41
42         return tcu::UVec3(xWorkGroupSize, yWorkGroupSize, zWorkGroupSize);
43 }
44
45 void SparseShaderIntrinsicsCaseStorage::initPrograms (vk::SourceCollections& programCollection) const
46 {
47         const std::string       imageTypeStr    = getShaderImageType(m_format, m_imageType);
48         const std::string       formatDataStr   = getShaderImageDataType(m_format);
49         const std::string       formatQualStr   = getShaderImageFormatQualifier(m_format);
50
51         const std::string  coordString          = getShaderImageCoordinates(m_imageType,
52                                                                                                                                         "%local_int_GlobalInvocationID_x",
53                                                                                                                                         "%local_ivec2_GlobalInvocationID_xy",
54                                                                                                                                         "%local_ivec3_GlobalInvocationID_xyz");
55         // Create compute program
56         std::ostringstream      src;
57
58         const std::string       typeImgComp                                     = getImageComponentTypeName(m_format);
59         const std::string       typeImgCompVec4                         = getImageComponentVec4TypeName(m_format);
60         const std::string       typeImageSparse                         = getSparseImageTypeName();
61         const std::string       typeUniformConstImageSparse     = getUniformConstSparseImageTypeName();
62
63         src << "OpCapability Shader\n"
64                 << "OpCapability ImageCubeArray\n"
65                 << "OpCapability SparseResidency\n"
66                 << "OpCapability StorageImageExtendedFormats\n"
67
68                 << "%ext_import = OpExtInstImport \"GLSL.std.450\"\n"
69                 << "OpMemoryModel Logical GLSL450\n"
70                 << "OpEntryPoint GLCompute %func_main \"main\" %input_GlobalInvocationID\n"
71                 << "OpExecutionMode %func_main LocalSize 1 1 1\n"
72                 << "OpSource GLSL 440\n"
73
74                 << "OpName %func_main \"main\"\n"
75
76                 << "OpName %input_GlobalInvocationID \"gl_GlobalInvocationID\"\n"
77                 << "OpName %input_WorkGroupSize \"gl_WorkGroupSize\"\n"
78
79                 << "OpName %uniform_image_sparse \"u_imageSparse\"\n"
80                 << "OpName %uniform_image_texels \"u_imageTexels\"\n"
81                 << "OpName %uniform_image_residency \"u_imageResidency\"\n"
82
83                 << "OpDecorate %input_GlobalInvocationID BuiltIn GlobalInvocationId\n"
84
85                 << "OpDecorate %input_WorkGroupSize BuiltIn WorkgroupSize\n"
86
87                 << "OpDecorate %constant_uint_grid_x SpecId 1\n"
88                 << "OpDecorate %constant_uint_grid_y SpecId 2\n"
89                 << "OpDecorate %constant_uint_grid_z SpecId 3\n"
90
91                 << "OpDecorate %constant_uint_work_group_size_x SpecId 4\n"
92                 << "OpDecorate %constant_uint_work_group_size_y SpecId 5\n"
93                 << "OpDecorate %constant_uint_work_group_size_z SpecId 6\n"
94
95                 << "OpDecorate %uniform_image_sparse DescriptorSet 0\n"
96                 << "OpDecorate %uniform_image_sparse Binding " << BINDING_IMAGE_SPARSE << "\n"
97
98                 << "OpDecorate %uniform_image_texels DescriptorSet 0\n"
99                 << "OpDecorate %uniform_image_texels Binding " << BINDING_IMAGE_TEXELS << "\n"
100                 << "OpDecorate %uniform_image_texels NonReadable\n"
101
102                 << "OpDecorate %uniform_image_residency DescriptorSet 0\n"
103                 << "OpDecorate %uniform_image_residency Binding " << BINDING_IMAGE_RESIDENCY << "\n"
104                 << "OpDecorate %uniform_image_residency NonReadable\n"
105
106                 // Declare data types
107                 << "%type_bool                                          = OpTypeBool\n"
108                 << "%type_int                                           = OpTypeInt 32 1\n"
109                 << "%type_uint                                          = OpTypeInt 32 0\n"
110                 << "%type_ivec2                                         = OpTypeVector %type_int  2\n"
111                 << "%type_ivec3                                         = OpTypeVector %type_int  3\n"
112                 << "%type_ivec4                                         = OpTypeVector %type_int  4\n"
113                 << "%type_uvec3                                         = OpTypeVector %type_uint 3\n"
114                 << "%type_uvec4                                         = OpTypeVector %type_uint 4\n"
115                 << "%type_struct_int_img_comp_vec4      = OpTypeStruct %type_int " << typeImgCompVec4 << "\n"
116
117                 << "%type_input_uint            = OpTypePointer Input %type_uint\n"
118                 << "%type_input_uvec3           = OpTypePointer Input %type_uvec3\n"
119
120                 << "%type_function_int                   = OpTypePointer Function %type_int\n"
121                 << "%type_function_img_comp_vec4 = OpTypePointer Function " << typeImgCompVec4 << "\n"
122
123                 << "%type_void                          = OpTypeVoid\n"
124                 << "%type_void_func                     = OpTypeFunction %type_void\n"
125
126                 // Sparse image without sampler type declaration
127                 << "%type_image_sparse = " << getOpTypeImageSparse(m_imageType, m_format, typeImgComp, false) << "\n"
128                 << "%type_uniformconst_image_sparse = OpTypePointer UniformConstant %type_image_sparse\n"
129
130                 // Sparse image with sampler type declaration
131                 << "%type_image_sparse_with_sampler = " << getOpTypeImageSparse(m_imageType, m_format, typeImgComp, true) << "\n"
132                 << "%type_uniformconst_image_sparse_with_sampler = OpTypePointer UniformConstant %type_image_sparse_with_sampler\n"
133
134                 // Residency image type declaration
135                 << "%type_image_residency                               = " << getOpTypeImageResidency(m_imageType) << "\n"
136                 << "%type_uniformconst_image_residency  = OpTypePointer UniformConstant %type_image_residency\n"
137
138                 // Declare sparse image variable
139                 << "%uniform_image_sparse = OpVariable " << typeUniformConstImageSparse << " UniformConstant\n"
140
141                 // Declare output image variable for storing texels
142                 << "%uniform_image_texels = OpVariable %type_uniformconst_image_sparse UniformConstant\n"
143
144                 // Declare output image variable for storing residency information
145                 << "%uniform_image_residency = OpVariable %type_uniformconst_image_residency UniformConstant\n"
146
147                 // Declare input variables
148                 << "%input_GlobalInvocationID = OpVariable %type_input_uvec3 Input\n"
149
150                 << "%constant_uint_grid_x                               = OpSpecConstant %type_uint 1\n"
151                 << "%constant_uint_grid_y                               = OpSpecConstant %type_uint 1\n"
152                 << "%constant_uint_grid_z                               = OpSpecConstant %type_uint 1\n"
153
154                 << "%constant_uint_work_group_size_x    = OpSpecConstant %type_uint 1\n"
155                 << "%constant_uint_work_group_size_y    = OpSpecConstant %type_uint 1\n"
156                 << "%constant_uint_work_group_size_z    = OpSpecConstant %type_uint 1\n"
157                 << "%input_WorkGroupSize = OpSpecConstantComposite %type_uvec3 %constant_uint_work_group_size_x %constant_uint_work_group_size_y %constant_uint_work_group_size_z\n"
158
159                 // Declare constants
160                 << "%constant_uint_0                            = OpConstant %type_uint 0\n"
161                 << "%constant_uint_1                            = OpConstant %type_uint 1\n"
162                 << "%constant_uint_2                            = OpConstant %type_uint 2\n"
163                 << "%constant_int_0                                     = OpConstant %type_int 0\n"
164                 << "%constant_int_1                                     = OpConstant %type_int 1\n"
165                 << "%constant_int_2                                     = OpConstant %type_int 2\n"
166                 << "%constant_bool_true                         = OpConstantTrue %type_bool\n"
167                 << "%constant_uint_resident                     = OpConstant %type_uint " << MEMORY_BLOCK_BOUND_VALUE << "\n"
168                 << "%constant_uvec4_resident            = OpConstantComposite %type_uvec4 %constant_uint_resident %constant_uint_resident %constant_uint_resident %constant_uint_resident\n"
169                 << "%constant_uint_not_resident         = OpConstant %type_uint " << MEMORY_BLOCK_NOT_BOUND_VALUE << "\n"
170                 << "%constant_uvec4_not_resident        = OpConstantComposite %type_uvec4 %constant_uint_not_resident %constant_uint_not_resident %constant_uint_not_resident %constant_uint_not_resident\n"
171
172                 // Call main function
173                 << "%func_main           = OpFunction %type_void None %type_void_func\n"
174                 << "%label_func_main = OpLabel\n"
175
176                 // Load GlobalInvocationID.xyz into local variables
177                 << "%access_GlobalInvocationID_x                = OpAccessChain %type_input_uint %input_GlobalInvocationID %constant_uint_0\n"
178                 << "%local_uint_GlobalInvocationID_x    = OpLoad %type_uint %access_GlobalInvocationID_x\n"
179                 << "%local_int_GlobalInvocationID_x             = OpBitcast %type_int %local_uint_GlobalInvocationID_x\n"
180
181                 << "%access_GlobalInvocationID_y                = OpAccessChain %type_input_uint %input_GlobalInvocationID %constant_uint_1\n"
182                 << "%local_uint_GlobalInvocationID_y    = OpLoad %type_uint %access_GlobalInvocationID_y\n"
183                 << "%local_int_GlobalInvocationID_y             = OpBitcast %type_int %local_uint_GlobalInvocationID_y\n"
184
185                 << "%access_GlobalInvocationID_z                = OpAccessChain %type_input_uint %input_GlobalInvocationID %constant_uint_2\n"
186                 << "%local_uint_GlobalInvocationID_z    = OpLoad %type_uint %access_GlobalInvocationID_z\n"
187                 << "%local_int_GlobalInvocationID_z             = OpBitcast %type_int %local_uint_GlobalInvocationID_z\n"
188
189                 << "%local_ivec2_GlobalInvocationID_xy  = OpCompositeConstruct %type_ivec2 %local_int_GlobalInvocationID_x %local_int_GlobalInvocationID_y\n"
190                 << "%local_ivec3_GlobalInvocationID_xyz = OpCompositeConstruct %type_ivec3 %local_int_GlobalInvocationID_x %local_int_GlobalInvocationID_y %local_int_GlobalInvocationID_z\n"
191
192                 << "%comparison_range_x = OpULessThan %type_bool %local_uint_GlobalInvocationID_x %constant_uint_grid_x\n"
193                 << "OpSelectionMerge %label_out_range_x None\n"
194                 << "OpBranchConditional %comparison_range_x %label_in_range_x %label_out_range_x\n"
195                 << "%label_in_range_x = OpLabel\n"
196
197                 << "%comparison_range_y = OpULessThan %type_bool %local_uint_GlobalInvocationID_y %constant_uint_grid_y\n"
198                 << "OpSelectionMerge %label_out_range_y None\n"
199                 << "OpBranchConditional %comparison_range_y %label_in_range_y %label_out_range_y\n"
200                 << "%label_in_range_y = OpLabel\n"
201
202                 << "%comparison_range_z = OpULessThan %type_bool %local_uint_GlobalInvocationID_z %constant_uint_grid_z\n"
203                 << "OpSelectionMerge %label_out_range_z None\n"
204                 << "OpBranchConditional %comparison_range_z %label_in_range_z %label_out_range_z\n"
205                 << "%label_in_range_z = OpLabel\n"
206
207                 // Load sparse image
208                 << "%local_image_sparse = OpLoad " << typeImageSparse << " %uniform_image_sparse\n"
209
210                 // Call OpImageSparse*
211                 << sparseImageOpString("%local_sparse_op_result", "%type_struct_int_img_comp_vec4", "%local_image_sparse", coordString, "%constant_int_0") << "\n"
212
213                 // Load the texel from the sparse image to local variable for OpImageSparse*
214                 << "%local_img_comp_vec4 = OpCompositeExtract " << typeImgCompVec4 << " %local_sparse_op_result 1\n"
215
216                 // Load residency code for OpImageSparse*
217                 << "%local_residency_code = OpCompositeExtract %type_int %local_sparse_op_result 0\n"
218                 // End Call OpImageSparse*
219
220                 // Load texels image
221                 << "%local_image_texels = OpLoad %type_image_sparse %uniform_image_texels\n"
222
223                 // Write the texel to output image via OpImageWrite
224                 << "OpImageWrite %local_image_texels " << coordString << " %local_img_comp_vec4\n"
225
226                 // Load residency info image
227                 << "%local_image_residency      = OpLoad %type_image_residency %uniform_image_residency\n"
228
229                 // Check if loaded texel is placed in resident memory
230                 << "%local_texel_resident = OpImageSparseTexelsResident %type_bool %local_residency_code\n"
231                 << "OpSelectionMerge %branch_texel_resident None\n"
232                 << "OpBranchConditional %local_texel_resident %label_texel_resident %label_texel_not_resident\n"
233                 << "%label_texel_resident = OpLabel\n"
234
235                 // Loaded texel is in resident memory
236                 << "OpImageWrite %local_image_residency " << coordString << " %constant_uvec4_resident\n"
237
238                 << "OpBranch %branch_texel_resident\n"
239                 << "%label_texel_not_resident = OpLabel\n"
240
241                 // Loaded texel is not in resident memory
242                 << "OpImageWrite %local_image_residency " << coordString << " %constant_uvec4_not_resident\n"
243
244                 << "OpBranch %branch_texel_resident\n"
245                 << "%branch_texel_resident = OpLabel\n"
246
247                 << "OpBranch %label_out_range_z\n"
248                 << "%label_out_range_z = OpLabel\n"
249
250                 << "OpBranch %label_out_range_y\n"
251                 << "%label_out_range_y = OpLabel\n"
252
253                 << "OpBranch %label_out_range_x\n"
254                 << "%label_out_range_x = OpLabel\n"
255
256                 << "OpReturn\n"
257                 << "OpFunctionEnd\n";
258
259         programCollection.spirvAsmSources.add("compute") << src.str();
260 }
261
262 std::string     SparseCaseOpImageSparseFetch::getSparseImageTypeName (void) const
263 {
264         return "%type_image_sparse_with_sampler";
265 }
266
267 std::string     SparseCaseOpImageSparseFetch::getUniformConstSparseImageTypeName (void) const
268 {
269         return "%type_uniformconst_image_sparse_with_sampler";
270 }
271
272 std::string     SparseCaseOpImageSparseFetch::sparseImageOpString  (const std::string& resultVariable,
273                                                                                                                                 const std::string& resultType,
274                                                                                                                                 const std::string& image,
275                                                                                                                                 const std::string& coord,
276                                                                                                                                 const std::string& mipLevel) const
277 {
278         std::ostringstream      src;
279
280         src << resultVariable << " = OpImageSparseFetch " << resultType << " " << image << " " << coord << " Lod " << mipLevel << "\n";
281
282         return src.str();
283 }
284
285 std::string     SparseCaseOpImageSparseRead::getSparseImageTypeName (void) const
286 {
287         return "%type_image_sparse";
288 }
289
290 std::string     SparseCaseOpImageSparseRead::getUniformConstSparseImageTypeName (void) const
291 {
292         return "%type_uniformconst_image_sparse";
293 }
294
295 std::string     SparseCaseOpImageSparseRead::sparseImageOpString (const std::string& resultVariable,
296                                                                                                                           const std::string& resultType,
297                                                                                                                           const std::string& image,
298                                                                                                                           const std::string& coord,
299                                                                                                                           const std::string& mipLevel) const
300 {
301         DE_UNREF(mipLevel);
302
303         std::ostringstream      src;
304
305         src << resultVariable << " = OpImageSparseRead " << resultType << " " << image << " " << coord << "\n";
306
307         return src.str();
308 }
309
310 class SparseShaderIntrinsicsInstanceStorage : public SparseShaderIntrinsicsInstanceBase
311 {
312 public:
313         SparseShaderIntrinsicsInstanceStorage   (Context&                                       context,
314                                                                                          const SpirVFunction            function,
315                                                                                          const ImageType                        imageType,
316                                                                                          const tcu::UVec3&                      imageSize,
317                                                                                          const tcu::TextureFormat&      format)
318                 : SparseShaderIntrinsicsInstanceBase(context, function, imageType, imageSize, format) {}
319
320         VkImageUsageFlags                               imageOutputUsageFlags   (void) const;
321
322         VkQueueFlags                                    getQueueFlags                   (void) const;
323
324         void                                                    recordCommands                  (const VkCommandBuffer          commandBuffer,
325                                                                                                                          const VkImageCreateInfo&       imageSparseInfo,
326                                                                                                                          const VkImage                          imageSparse,
327                                                                                                                          const VkImage                          imageTexels,
328                                                                                                                          const VkImage                          imageResidency);
329
330         virtual VkDescriptorType                imageSparseDescType             (void) const = 0;
331 };
332
333 VkImageUsageFlags SparseShaderIntrinsicsInstanceStorage::imageOutputUsageFlags (void) const
334 {
335         return VK_IMAGE_USAGE_STORAGE_BIT;
336 }
337
338 VkQueueFlags SparseShaderIntrinsicsInstanceStorage::getQueueFlags (void) const
339 {
340         return VK_QUEUE_COMPUTE_BIT;
341 }
342
343 void SparseShaderIntrinsicsInstanceStorage::recordCommands (const VkCommandBuffer               commandBuffer,
344                                                                                                                         const VkImageCreateInfo&        imageSparseInfo,
345                                                                                                                         const VkImage                           imageSparse,
346                                                                                                                         const VkImage                           imageTexels,
347                                                                                                                         const VkImage                           imageResidency)
348 {
349         const InstanceInterface&        instance                = m_context.getInstanceInterface();
350         const DeviceInterface&          deviceInterface = getDeviceInterface();
351         const VkPhysicalDevice          physicalDevice  = m_context.getPhysicalDevice();
352
353         // Check if device supports image format for storage image
354         if (!checkImageFormatFeatureSupport(instance, physicalDevice, imageSparseInfo.format, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
355                 TCU_THROW(NotSupportedError, "Device does not support image format for storage image");
356
357         // Make sure device supports VK_FORMAT_R32_UINT format for storage image
358         if (!checkImageFormatFeatureSupport(instance, physicalDevice, mapTextureFormat(m_residencyFormat), VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
359                 TCU_THROW(TestError, "Device does not support VK_FORMAT_R32_UINT format for storage image");
360
361         pipelines.resize(imageSparseInfo.mipLevels);
362         descriptorSets.resize(imageSparseInfo.mipLevels);
363         imageSparseViews.resize(imageSparseInfo.mipLevels);
364         imageTexelsViews.resize(imageSparseInfo.mipLevels);
365         imageResidencyViews.resize(imageSparseInfo.mipLevels);
366
367         // Create descriptor set layout
368         DescriptorSetLayoutBuilder descriptorLayerBuilder;
369
370         descriptorLayerBuilder.addSingleBinding(imageSparseDescType(), VK_SHADER_STAGE_COMPUTE_BIT);
371         descriptorLayerBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT);
372         descriptorLayerBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT);
373
374         const Unique<VkDescriptorSetLayout> descriptorSetLayout(descriptorLayerBuilder.build(deviceInterface, getDevice()));
375
376         // Create pipeline layout
377         const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(deviceInterface, getDevice(), *descriptorSetLayout));
378
379         // Create descriptor pool
380         DescriptorPoolBuilder descriptorPoolBuilder;
381
382         descriptorPoolBuilder.addType(imageSparseDescType(), imageSparseInfo.mipLevels);
383         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, imageSparseInfo.mipLevels);
384         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, imageSparseInfo.mipLevels);
385
386         descriptorPool = descriptorPoolBuilder.build(deviceInterface, getDevice(), VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, imageSparseInfo.mipLevels);
387
388         const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers);
389
390         {
391                 VkImageMemoryBarrier imageShaderAccessBarriers[3];
392
393                 imageShaderAccessBarriers[0] = makeImageMemoryBarrier
394                 (
395                         VK_ACCESS_TRANSFER_WRITE_BIT,
396                         VK_ACCESS_SHADER_READ_BIT,
397                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
398                         VK_IMAGE_LAYOUT_GENERAL,
399                         imageSparse,
400                         fullImageSubresourceRange
401                 );
402
403                 imageShaderAccessBarriers[1] = makeImageMemoryBarrier
404                 (
405                         0u,
406                         VK_ACCESS_SHADER_WRITE_BIT,
407                         VK_IMAGE_LAYOUT_UNDEFINED,
408                         VK_IMAGE_LAYOUT_GENERAL,
409                         imageTexels,
410                         fullImageSubresourceRange
411                 );
412
413                 imageShaderAccessBarriers[2] = makeImageMemoryBarrier
414                 (
415                         0u,
416                         VK_ACCESS_SHADER_WRITE_BIT,
417                         VK_IMAGE_LAYOUT_UNDEFINED,
418                         VK_IMAGE_LAYOUT_GENERAL,
419                         imageResidency,
420                         fullImageSubresourceRange
421                 );
422
423                 deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 3u, imageShaderAccessBarriers);
424         }
425
426         const VkSpecializationMapEntry specializationMapEntries[6] =
427         {
428                 { 1u, 0u * (deUint32)sizeof(deUint32), sizeof(deUint32) }, // GridSize.x
429                 { 2u, 1u * (deUint32)sizeof(deUint32), sizeof(deUint32) }, // GridSize.y
430                 { 3u, 2u * (deUint32)sizeof(deUint32), sizeof(deUint32) }, // GridSize.z
431                 { 4u, 3u * (deUint32)sizeof(deUint32), sizeof(deUint32) }, // WorkGroupSize.x
432                 { 5u, 4u * (deUint32)sizeof(deUint32), sizeof(deUint32) }, // WorkGroupSize.y
433                 { 6u, 5u * (deUint32)sizeof(deUint32), sizeof(deUint32) }, // WorkGroupSize.z
434         };
435
436         Unique<VkShaderModule> shaderModule(createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("compute"), 0u));
437
438         for (deUint32 mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx)
439         {
440                 const tcu::UVec3  gridSize                              = getShaderGridSize(m_imageType, m_imageSize, mipLevelNdx);
441                 const tcu::UVec3  workGroupSize                 = computeWorkGroupSize(gridSize);
442                 const tcu::UVec3 specializationData[2]  = { gridSize, workGroupSize };
443
444                 const VkSpecializationInfo specializationInfo =
445                 {
446                         (deUint32)DE_LENGTH_OF_ARRAY(specializationMapEntries), // mapEntryCount
447                         specializationMapEntries,                                                               // pMapEntries
448                         sizeof(specializationData),                                                             // dataSize
449                         specializationData,                                                                             // pData
450                 };
451
452                 // Create and bind compute pipeline
453                 pipelines[mipLevelNdx] = makeVkSharedPtr(makeComputePipeline(deviceInterface, getDevice(), *pipelineLayout, *shaderModule, &specializationInfo));
454                 const VkPipeline computePipeline = **pipelines[mipLevelNdx];
455
456                 deviceInterface.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline);
457
458                 // Create descriptor set
459                 descriptorSets[mipLevelNdx] = makeVkSharedPtr(makeDescriptorSet(deviceInterface, getDevice(), *descriptorPool, *descriptorSetLayout));
460                 const VkDescriptorSet descriptorSet = **descriptorSets[mipLevelNdx];
461
462                 // Bind resources
463                 const VkImageSubresourceRange mipLevelRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevelNdx, 1u, 0u, imageSparseInfo.arrayLayers);
464
465                 imageSparseViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageSparse, mapImageViewType(m_imageType), imageSparseInfo.format, mipLevelRange));
466                 const VkDescriptorImageInfo imageSparseDescInfo = makeDescriptorImageInfo(DE_NULL, **imageSparseViews[mipLevelNdx], VK_IMAGE_LAYOUT_GENERAL);
467
468                 imageTexelsViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageTexels, mapImageViewType(m_imageType), imageSparseInfo.format, mipLevelRange));
469                 const VkDescriptorImageInfo imageTexelsDescInfo = makeDescriptorImageInfo(DE_NULL, **imageTexelsViews[mipLevelNdx], VK_IMAGE_LAYOUT_GENERAL);
470
471                 imageResidencyViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageResidency, mapImageViewType(m_imageType), mapTextureFormat(m_residencyFormat), mipLevelRange));
472                 const VkDescriptorImageInfo imageResidencyDescInfo = makeDescriptorImageInfo(DE_NULL, **imageResidencyViews[mipLevelNdx], VK_IMAGE_LAYOUT_GENERAL);
473
474                 DescriptorSetUpdateBuilder descriptorUpdateBuilder;
475                 descriptorUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(BINDING_IMAGE_SPARSE), imageSparseDescType(), &imageSparseDescInfo);
476                 descriptorUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(BINDING_IMAGE_TEXELS), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageTexelsDescInfo);
477                 descriptorUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(BINDING_IMAGE_RESIDENCY), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageResidencyDescInfo);
478
479                 descriptorUpdateBuilder.update(deviceInterface, getDevice());
480
481                 deviceInterface.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
482
483                 const deUint32          xWorkGroupCount = gridSize.x() / workGroupSize.x() + (gridSize.x() % workGroupSize.x() ? 1u : 0u);
484                 const deUint32          yWorkGroupCount = gridSize.y() / workGroupSize.y() + (gridSize.y() % workGroupSize.y() ? 1u : 0u);
485                 const deUint32          zWorkGroupCount = gridSize.z() / workGroupSize.z() + (gridSize.z() % workGroupSize.z() ? 1u : 0u);
486                 const tcu::UVec3        maxWorkGroupCount = tcu::UVec3(65535u, 65535u, 65535u);
487
488                 if (maxWorkGroupCount.x() < xWorkGroupCount ||
489                         maxWorkGroupCount.y() < yWorkGroupCount ||
490                         maxWorkGroupCount.z() < zWorkGroupCount)
491                 {
492                         TCU_THROW(NotSupportedError, "Image size exceeds compute invocations limit");
493                 }
494
495                 deviceInterface.cmdDispatch(commandBuffer, xWorkGroupCount, yWorkGroupCount, zWorkGroupCount);
496         }
497
498         {
499                 VkImageMemoryBarrier imageOutputTransferSrcBarriers[2];
500
501                 imageOutputTransferSrcBarriers[0] = makeImageMemoryBarrier
502                 (
503                         VK_ACCESS_SHADER_WRITE_BIT,
504                         VK_ACCESS_TRANSFER_READ_BIT,
505                         VK_IMAGE_LAYOUT_GENERAL,
506                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
507                         imageTexels,
508                         fullImageSubresourceRange
509                 );
510
511                 imageOutputTransferSrcBarriers[1] = makeImageMemoryBarrier
512                 (
513                         VK_ACCESS_SHADER_WRITE_BIT,
514                         VK_ACCESS_TRANSFER_READ_BIT,
515                         VK_IMAGE_LAYOUT_GENERAL,
516                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
517                         imageResidency,
518                         fullImageSubresourceRange
519                 );
520
521                 deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputTransferSrcBarriers);
522         }
523 }
524
525 class SparseShaderIntrinsicsInstanceFetch : public SparseShaderIntrinsicsInstanceStorage
526 {
527 public:
528         SparseShaderIntrinsicsInstanceFetch                     (Context&                                       context,
529                                                                                                  const SpirVFunction            function,
530                                                                                                  const ImageType                        imageType,
531                                                                                                  const tcu::UVec3&                      imageSize,
532                                                                                                  const tcu::TextureFormat&      format)
533         : SparseShaderIntrinsicsInstanceStorage (context, function, imageType, imageSize, format) {}
534
535         VkImageUsageFlags       imageSparseUsageFlags   (void) const { return VK_IMAGE_USAGE_SAMPLED_BIT; }
536         VkDescriptorType        imageSparseDescType             (void) const { return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; }
537 };
538
539 TestInstance* SparseCaseOpImageSparseFetch::createInstance (Context& context) const
540 {
541         return new SparseShaderIntrinsicsInstanceFetch(context, m_function, m_imageType, m_imageSize, m_format);
542 }
543
544 class SparseShaderIntrinsicsInstanceRead : public SparseShaderIntrinsicsInstanceStorage
545 {
546 public:
547         SparseShaderIntrinsicsInstanceRead                      (Context&                                       context,
548                                                                                                  const SpirVFunction            function,
549                                                                                                  const ImageType                        imageType,
550                                                                                                  const tcu::UVec3&                      imageSize,
551                                                                                                  const tcu::TextureFormat&      format)
552         : SparseShaderIntrinsicsInstanceStorage (context, function, imageType, imageSize, format) {}
553
554         VkImageUsageFlags       imageSparseUsageFlags   (void) const { return VK_IMAGE_USAGE_STORAGE_BIT; }
555         VkDescriptorType        imageSparseDescType             (void) const { return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; }
556 };
557
558 TestInstance* SparseCaseOpImageSparseRead::createInstance (Context& context) const
559 {
560         return new SparseShaderIntrinsicsInstanceRead(context, m_function, m_imageType, m_imageSize, m_format);
561 }
562
563 } // sparse
564 } // vkt