Merge gerrit/vulkan-cts-1.0.0 into gerrit/vulkan-cts-1.0.1
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / sparse_resources / vktSparseResourcesShaderIntrinsicsSampled.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*
20  * \file  vktSparseResourcesShaderIntrinsicsSampled.cpp
21  * \brief Sparse Resources Shader Intrinsics for sampled images
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktSparseResourcesShaderIntrinsicsSampled.hpp"
25
26 using namespace vk;
27
28 namespace vkt
29 {
30 namespace sparse
31 {
32
33 void SparseShaderIntrinsicsCaseSampledBase::initPrograms (vk::SourceCollections& programCollection) const
34 {
35         const deUint32          numLayers       = getNumLayers(m_imageType, m_imageSize);
36         const std::string       coordString = getShaderImageCoordinates(m_imageType, "%local_texCoord_x", "%local_texCoord_xy", "%local_texCoord_xyz");
37
38         // Create vertex shader
39         std::ostringstream vs;
40
41         vs      << "#version 440\n"
42                 << "layout(location = 0) in  highp vec2 vs_in_position;\n"
43                 << "layout(location = 1) in  highp vec2 vs_in_texCoord;\n"
44                 << "\n"
45                 << "layout(location = 0) out highp vec3 vs_out_texCoord;\n"
46                 << "\n"
47                 << "out gl_PerVertex {\n"
48                 << "    vec4  gl_Position;\n"
49                 << "};\n"
50                 << "void main (void)\n"
51                 << "{\n"
52                 << "    gl_Position             = vec4(vs_in_position, 0.0f, 1.0f);\n"
53                 << "    vs_out_texCoord = vec3(vs_in_texCoord, 0.0f);\n"
54                 << "}\n";
55
56         programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
57
58         if (numLayers > 1u)
59         {
60                 const deInt32 maxVertices = 3u * numLayers;
61
62                 // Create geometry shader
63                 std::ostringstream gs;
64
65                 gs << "#version 440\n"
66                         << "layout(triangles) in;\n"
67                         << "layout(triangle_strip, max_vertices = " << static_cast<deInt32>(maxVertices) << ") out;\n"
68                         << "\n"
69                         << "in gl_PerVertex {\n"
70                         << "    vec4  gl_Position;\n"
71                         << "} gl_in[];\n"
72                         << "out gl_PerVertex {\n"
73                         << "    vec4  gl_Position;\n"
74                         << "};\n"
75                         << "layout(location = 0) in  highp vec3 gs_in_texCoord[];\n"
76                         << "\n"
77                         << "layout(location = 0) out highp vec3 gs_out_texCoord;\n"
78                         << "\n"
79                         << "void main (void)\n"
80                         << "{\n"
81                         << "    for (int layerNdx = 0; layerNdx < " << static_cast<deInt32>(numLayers) << "; ++layerNdx)\n"
82                         << "    {\n"
83                         << "            for (int vertexNdx = 0; vertexNdx < gl_in.length(); ++vertexNdx)\n"
84                         << "            {\n"
85                         << "                    gl_Layer                = layerNdx;\n"
86                         << "                    gl_Position             = gl_in[vertexNdx].gl_Position;\n"
87                         << "                    gs_out_texCoord = vec3(gs_in_texCoord[vertexNdx].xy, float(layerNdx));\n"
88                         << "                    EmitVertex();\n"
89                         << "            }\n"
90                         << "            EndPrimitive();\n"
91                         << "    }\n"
92                         << "}\n";
93
94                 programCollection.glslSources.add("geometry_shader") << glu::GeometrySource(gs.str());
95         }
96
97         // Create fragment shader
98         std::ostringstream fs;
99
100         fs      << "OpCapability Shader\n"
101                 << "OpCapability SampledCubeArray\n"
102                 << "OpCapability ImageCubeArray\n"
103                 << "OpCapability SparseResidency\n"
104                 << "OpCapability StorageImageExtendedFormats\n"
105
106                 << "%ext_import = OpExtInstImport \"GLSL.std.450\"\n"
107                 << "OpMemoryModel Logical GLSL450\n"
108                 << "OpEntryPoint Fragment %func_main \"main\" %varying_texCoord %output_texel %output_residency\n"
109                 << "OpExecutionMode %func_main OriginUpperLeft\n"
110                 << "OpSource GLSL 440\n"
111
112                 << "OpName %func_main \"main\"\n"
113
114                 << "OpName %varying_texCoord \"varying_texCoord\"\n"
115
116                 << "OpName %output_texel \"out_texel\"\n"
117                 << "OpName %output_residency \"out_residency\"\n"
118
119                 << "OpName %type_uniformblock_lod \"LodBlock\"\n"
120                 << "OpMemberName %type_uniformblock_lod 0 \"lod\"\n"
121                 << "OpName %uniformblock_lod_instance \"lodInstance\"\n"
122
123                 << "OpName %uniformconst_image_sparse \"u_imageSparse\"\n"
124
125                 << "OpDecorate %varying_texCoord Location 0\n"
126
127                 << "OpDecorate %output_texel     Location 0\n"
128                 << "OpDecorate %output_residency Location 1\n"
129
130                 << "OpDecorate           %type_uniformblock_lod Block\n"
131                 << "OpMemberDecorate %type_uniformblock_lod 0 Offset 0\n"
132
133                 << "OpDecorate %uniformconst_image_sparse DescriptorSet 0\n"
134                 << "OpDecorate %uniformconst_image_sparse Binding " << BINDING_IMAGE_SPARSE << "\n"
135
136                 << "%type_void = OpTypeVoid\n"
137                 << "%type_void_func = OpTypeFunction %type_void\n"
138
139                 << "%type_bool                                                  = OpTypeBool\n"
140                 << "%type_int                                                   = OpTypeInt 32 1\n"
141                 << "%type_uint                                                  = OpTypeInt 32 0\n"
142                 << "%type_float                                                 = OpTypeFloat 32\n"
143                 << "%type_vec2                                                  = OpTypeVector %type_float 2\n"
144                 << "%type_vec3                                                  = OpTypeVector %type_float 3\n"
145                 << "%type_vec4                                                  = OpTypeVector %type_float 4\n"
146                 << "%type_uniformblock_lod                              = OpTypeStruct %type_uint\n"
147                 << "%type_img_comp                                              = " << getOpTypeImageComponent(m_format) << "\n"
148                 << "%type_img_comp_vec4                                 = OpTypeVector %type_img_comp 4\n"
149                 << "%type_struct_int_img_comp_vec4              = OpTypeStruct %type_int %type_img_comp_vec4\n"
150
151                 << "%type_input_vec3                                    = OpTypePointer Input %type_vec3\n"
152                 << "%type_input_float                                   = OpTypePointer Input %type_float\n"
153
154                 << "%type_output_img_comp_vec4                  = OpTypePointer Output %type_img_comp_vec4\n"
155                 << "%type_output_uint                                   = OpTypePointer Output %type_uint\n"
156
157                 << "%type_function_int                                  = OpTypePointer Function %type_int\n"
158                 << "%type_function_img_comp                             = OpTypePointer Function %type_img_comp\n"
159                 << "%type_function_img_comp_vec4                = OpTypePointer Function %type_img_comp_vec4\n"
160                 << "%type_function_int_img_comp_vec4    = OpTypePointer Function %type_struct_int_img_comp_vec4\n"
161
162                 << "%type_pushconstant_uniformblock_lod                 = OpTypePointer PushConstant %type_uniformblock_lod\n"
163                 << "%type_pushconstant_uniformblock_member_lod  = OpTypePointer PushConstant %type_uint\n"
164
165                 << "%type_image_sparse                          = " << getOpTypeImageSparse(m_imageType, m_format, "%type_img_comp", true) << "\n"
166                 << "%type_sampled_image_sparse          = OpTypeSampledImage %type_image_sparse\n"
167                 << "%type_uniformconst_image_sparse = OpTypePointer UniformConstant %type_sampled_image_sparse\n"
168
169                 << "%varying_texCoord                   = OpVariable %type_input_vec3 Input\n"
170
171                 << "%output_texel                               = OpVariable %type_output_img_comp_vec4 Output\n"
172                 << "%output_residency                   = OpVariable %type_output_uint Output\n"
173
174                 << "%uniformconst_image_sparse  = OpVariable %type_uniformconst_image_sparse UniformConstant\n"
175
176                 << "%uniformblock_lod_instance  = OpVariable %type_pushconstant_uniformblock_lod PushConstant\n"
177
178                 // Declare constants
179                 << "%constant_uint_0                            = OpConstant %type_uint 0\n"
180                 << "%constant_uint_1                            = OpConstant %type_uint 1\n"
181                 << "%constant_uint_2                            = OpConstant %type_uint 2\n"
182                 << "%constant_uint_3                            = OpConstant %type_uint 3\n"
183                 << "%constant_int_0                                     = OpConstant %type_int  0\n"
184                 << "%constant_int_1                                     = OpConstant %type_int  1\n"
185                 << "%constant_int_2                                     = OpConstant %type_int  2\n"
186                 << "%constant_int_3                                     = OpConstant %type_int  3\n"
187                 << "%constant_texel_resident            = OpConstant %type_uint " << MEMORY_BLOCK_BOUND_VALUE << "\n"
188                 << "%constant_texel_not_resident        = OpConstant %type_uint " << MEMORY_BLOCK_NOT_BOUND_VALUE << "\n"
189
190                 // Call main function
191                 << "%func_main           = OpFunction %type_void None %type_void_func\n"
192                 << "%label_func_main = OpLabel\n"
193
194                 << "%local_image_sparse = OpLoad %type_sampled_image_sparse %uniformconst_image_sparse\n"
195
196                 << "%local_texCoord_x = OpCompositeExtract %type_float %varying_texCoord 0\n"
197                 << "%local_texCoord_y = OpCompositeExtract %type_float %varying_texCoord 1\n"
198                 << "%local_texCoord_z = OpCompositeExtract %type_float %varying_texCoord 2\n"
199
200                 << "%local_texCoord_xy  = OpCompositeConstruct %type_vec2 %local_texCoord_x %local_texCoord_y\n"
201                 << "%local_texCoord_xyz = OpCompositeConstruct %type_vec3 %local_texCoord_x %local_texCoord_y %local_texCoord_z\n"
202
203                 << "%access_uniformblock_member_uint_lod = OpAccessChain %type_pushconstant_uniformblock_member_lod %uniformblock_lod_instance %constant_int_0\n"
204                 << "%local_uniformblock_member_uint_lod  = OpLoad %type_uint %access_uniformblock_member_uint_lod\n"
205                 << "%local_uniformblock_member_float_lod = OpConvertUToF %type_float %local_uniformblock_member_uint_lod\n"
206
207                 << sparseImageOpString("%local_sparse_op_result", "%type_struct_int_img_comp_vec4", "%local_image_sparse", coordString, "%local_uniformblock_member_float_lod") << "\n"
208
209                 // Load texel value
210                 << "%local_img_comp_vec4 = OpCompositeExtract %type_img_comp_vec4 %local_sparse_op_result 1\n"
211
212                 << "OpStore %output_texel %local_img_comp_vec4\n"
213
214                 // Load residency code
215                 << "%local_residency_code = OpCompositeExtract %type_int %local_sparse_op_result 0\n"
216
217                 // Check if loaded texel is placed in resident memory
218                 << "%local_texel_resident = OpImageSparseTexelsResident %type_bool %local_residency_code\n"
219                 << "OpSelectionMerge %branch_texel_resident None\n"
220                 << "OpBranchConditional %local_texel_resident %label_texel_resident %label_texel_not_resident\n"
221                 << "%label_texel_resident = OpLabel\n"
222
223                 // Loaded texel is in resident memory
224                 << "OpStore %output_residency %constant_texel_resident\n"
225
226                 << "OpBranch %branch_texel_resident\n"
227                 << "%label_texel_not_resident = OpLabel\n"
228
229                 // Loaded texel is not in resident memory
230                 << "OpStore %output_residency %constant_texel_not_resident\n"
231
232                 << "OpBranch %branch_texel_resident\n"
233                 << "%branch_texel_resident = OpLabel\n"
234
235                 << "OpReturn\n"
236                 << "OpFunctionEnd\n";
237
238         programCollection.spirvAsmSources.add("fragment_shader") << fs.str();
239 }
240
241 std::string     SparseCaseOpImageSparseSampleExplicitLod::sparseImageOpString (const std::string& resultVariable,
242                                                                                                                                                    const std::string& resultType,
243                                                                                                                                                    const std::string& image,
244                                                                                                                                                    const std::string& coord,
245                                                                                                                                                    const std::string& miplevel) const
246 {
247         std::ostringstream      src;
248
249         src << resultVariable << " = OpImageSparseSampleExplicitLod " << resultType << " " << image << " " << coord << " Lod " << miplevel << "\n";
250
251         return src.str();
252 }
253
254 std::string     SparseCaseOpImageSparseSampleImplicitLod::sparseImageOpString  (const std::string& resultVariable,
255                                                                                                                                                         const std::string& resultType,
256                                                                                                                                                         const std::string& image,
257                                                                                                                                                         const std::string& coord,
258                                                                                                                                                         const std::string& miplevel) const
259 {
260         DE_UNREF(miplevel);
261
262         std::ostringstream      src;
263
264         src << resultVariable << " = OpImageSparseSampleImplicitLod " << resultType << " " << image << " " << coord << "\n";
265
266         return src.str();
267 }
268
269 std::string     SparseCaseOpImageSparseGather::sparseImageOpString (const std::string& resultVariable,
270                                                                                                                                 const std::string& resultType,
271                                                                                                                                 const std::string& image,
272                                                                                                                                 const std::string& coord,
273                                                                                                                                 const std::string& miplevel) const
274 {
275         DE_UNREF(miplevel);
276
277         std::ostringstream      src;
278
279         src << "%local_sparse_gather_result_x = OpImageSparseGather " << resultType << " " << image << " " << coord << " %constant_int_0\n";
280         src << "%local_sparse_gather_result_y = OpImageSparseGather " << resultType << " " << image << " " << coord << " %constant_int_1\n";
281         src << "%local_sparse_gather_result_z = OpImageSparseGather " << resultType << " " << image << " " << coord << " %constant_int_2\n";
282         src << "%local_sparse_gather_result_w = OpImageSparseGather " << resultType << " " << image << " " << coord << " %constant_int_3\n";
283
284         src << "%local_gather_residency_code = OpCompositeExtract %type_int %local_sparse_gather_result_x 0\n";
285
286         src << "%local_gather_texels_x = OpCompositeExtract %type_img_comp_vec4 %local_sparse_gather_result_x 1\n";
287         src << "%local_gather_texels_y = OpCompositeExtract %type_img_comp_vec4 %local_sparse_gather_result_y 1\n";
288         src << "%local_gather_texels_z = OpCompositeExtract %type_img_comp_vec4 %local_sparse_gather_result_z 1\n";
289         src << "%local_gather_texels_w = OpCompositeExtract %type_img_comp_vec4 %local_sparse_gather_result_w 1\n";
290
291         src << "%local_gather_primary_texel_x = OpCompositeExtract %type_img_comp %local_gather_texels_x 3\n";
292         src << "%local_gather_primary_texel_y = OpCompositeExtract %type_img_comp %local_gather_texels_y 3\n";
293         src << "%local_gather_primary_texel_z = OpCompositeExtract %type_img_comp %local_gather_texels_z 3\n";
294         src << "%local_gather_primary_texel_w = OpCompositeExtract %type_img_comp %local_gather_texels_w 3\n";
295
296         src << "%local_gather_primary_texel     = OpCompositeConstruct %type_img_comp_vec4 %local_gather_primary_texel_x %local_gather_primary_texel_y %local_gather_primary_texel_z %local_gather_primary_texel_w\n";
297         src << resultVariable << " = OpCompositeConstruct " << resultType << " %local_gather_residency_code %local_gather_primary_texel\n";
298
299         return src.str();
300 }
301
302 class SparseShaderIntrinsicsInstanceSampledBase : public SparseShaderIntrinsicsInstanceBase
303 {
304 public:
305         SparseShaderIntrinsicsInstanceSampledBase       (Context&                                       context,
306                                                                                                  const SpirVFunction            function,
307                                                                                                  const ImageType                        imageType,
308                                                                                                  const tcu::UVec3&                      imageSize,
309                                                                                                  const tcu::TextureFormat&      format)
310         : SparseShaderIntrinsicsInstanceBase(context, function, imageType, imageSize, format) {}
311
312         VkImageUsageFlags               imageSparseUsageFlags   (void) const;
313         VkImageUsageFlags               imageOutputUsageFlags   (void) const;
314
315         VkQueueFlags                    getQueueFlags                   (void) const;
316
317         void                                    recordCommands                  (vk::Allocator&                         allocator,
318                                                                                                          const VkCommandBuffer          commandBuffer,
319                                                                                                          const VkImageCreateInfo&       imageSparseInfo,
320                                                                                                          const VkImage                          imageSparse,
321                                                                                                          const VkImage                          imageTexels,
322                                                                                                          const VkImage                          imageResidency);
323
324         virtual VkImageSubresourceRange sampledImageRangeToBind(const VkImageCreateInfo& imageSparseInfo, const deUint32 mipLevel) const = 0;
325
326 private:
327
328         typedef de::SharedPtr< vk::Unique<vk::VkFramebuffer> > SharedVkFramebuffer;
329
330         de::SharedPtr<Buffer>                           vertexBuffer;
331         std::vector<SharedVkFramebuffer>        framebuffers;
332         Move<VkRenderPass>                                      renderPass;
333         Move<VkSampler>                                         sampler;
334 };
335
336 VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageSparseUsageFlags (void) const
337 {
338         return VK_IMAGE_USAGE_SAMPLED_BIT;
339 }
340
341 VkImageUsageFlags SparseShaderIntrinsicsInstanceSampledBase::imageOutputUsageFlags (void) const
342 {
343         return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
344 }
345
346 VkQueueFlags SparseShaderIntrinsicsInstanceSampledBase::getQueueFlags (void) const
347 {
348         return VK_QUEUE_GRAPHICS_BIT;
349 }
350
351 void SparseShaderIntrinsicsInstanceSampledBase::recordCommands (vk::Allocator&                          allocator,
352                                                                                                                                 const VkCommandBuffer           commandBuffer,
353                                                                                                                                 const VkImageCreateInfo&        imageSparseInfo,
354                                                                                                                                 const VkImage                           imageSparse,
355                                                                                                                                 const VkImage                           imageTexels,
356                                                                                                                                 const VkImage                           imageResidency)
357 {
358         const InstanceInterface&                 instance                       = m_context.getInstanceInterface();
359         const DeviceInterface&                   deviceInterface        = m_context.getDeviceInterface();
360         const VkPhysicalDevice                   physicalDevice         = m_context.getPhysicalDevice();
361         const VkPhysicalDeviceProperties deviceProperties       = getPhysicalDeviceProperties(instance, physicalDevice);
362
363         if (imageSparseInfo.extent.width  > deviceProperties.limits.maxFramebufferWidth  ||
364                 imageSparseInfo.extent.height > deviceProperties.limits.maxFramebufferHeight ||
365                 imageSparseInfo.arrayLayers   > deviceProperties.limits.maxFramebufferLayers)
366         {
367                 TCU_THROW(NotSupportedError, "Image size exceeds allowed framebuffer dimensions");
368         }
369
370         // Check if device supports image format for sampled images
371         if (!checkImageFormatFeatureSupport(instance, physicalDevice, imageSparseInfo.format, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
372                 TCU_THROW(NotSupportedError, "Device does not support image format for sampled images");
373
374         // Check if device supports image format for color attachment
375         if (!checkImageFormatFeatureSupport(instance, physicalDevice, imageSparseInfo.format, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
376                 TCU_THROW(NotSupportedError, "Device does not support image format for color attachment");
377
378         // Make sure device supports VK_FORMAT_R32_UINT format for color attachment
379         if (!checkImageFormatFeatureSupport(instance, physicalDevice, mapTextureFormat(m_residencyFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
380                 TCU_THROW(TestError, "Device does not support VK_FORMAT_R32_UINT format for color attachment");
381
382         // Create buffer storing vertex data
383         std::vector<tcu::Vec2> vertexData;
384
385         vertexData.push_back(tcu::Vec2(-1.0f,-1.0f));
386         vertexData.push_back(tcu::Vec2( 0.0f, 0.0f));
387
388         vertexData.push_back(tcu::Vec2(-1.0f, 1.0f));
389         vertexData.push_back(tcu::Vec2( 0.0f, 1.0f));
390
391         vertexData.push_back(tcu::Vec2( 1.0f,-1.0f));
392         vertexData.push_back(tcu::Vec2( 1.0f, 0.0f));
393
394         vertexData.push_back(tcu::Vec2( 1.0f, 1.0f));
395         vertexData.push_back(tcu::Vec2( 1.0f, 1.0f));
396
397         const VkFormat          vertexFormatPosition            = VK_FORMAT_R32G32_SFLOAT;
398         const VkFormat          vertexFormatTexCoord            = VK_FORMAT_R32G32_SFLOAT;
399
400         const deUint32          vertexSizePosition                      = tcu::getPixelSize(mapVkFormat(vertexFormatPosition));
401         const deUint32          vertexSizeTexCoord                      = tcu::getPixelSize(mapVkFormat(vertexFormatTexCoord));
402
403         const VkDeviceSize      vertexBufferStartOffset         = 0ull;
404         const deUint32          vertexBufferOffsetPosition      = 0ull;
405         const deUint32          vertexBufferOffsetTexCoord      = vertexSizePosition;
406
407         const deUint32          vertexDataStride                        = vertexSizePosition + vertexSizeTexCoord;
408         const VkDeviceSize      vertexDataSizeInBytes           = sizeInBytes(vertexData);
409
410         vertexBuffer = de::SharedPtr<Buffer>(new Buffer(deviceInterface, *m_logicalDevice, allocator, makeBufferCreateInfo(vertexDataSizeInBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
411         const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation();
412
413         deMemcpy(vertexBufferAllocation.getHostPtr(), &vertexData[0], static_cast<std::size_t>(vertexDataSizeInBytes));
414         flushMappedMemoryRange(deviceInterface, *m_logicalDevice, vertexBufferAllocation.getMemory(), vertexBufferAllocation.getOffset(), vertexDataSizeInBytes);
415
416         // Create render pass
417         const VkAttachmentDescription texelsAttachmentDescription =
418         {
419                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
420                 imageSparseInfo.format,                                                         // VkFormat                                                     format;
421                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
422                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
423                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
424                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
425                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
426                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
427                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout                                        finalLayout;
428         };
429
430         const VkAttachmentDescription residencyAttachmentDescription =
431         {
432                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
433                 mapTextureFormat(m_residencyFormat),                            // VkFormat                                                     format;
434                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
435                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
436                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
437                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
438                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
439                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
440                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout                                        finalLayout;
441         };
442
443         const VkAttachmentDescription colorAttachmentsDescription[] = { texelsAttachmentDescription, residencyAttachmentDescription };
444
445         const VkAttachmentReference texelsAttachmentReference =
446         {
447                 0u,                                                                                                     // deUint32                     attachment;
448                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
449         };
450
451         const VkAttachmentReference residencyAttachmentReference =
452         {
453                 1u,                                                                                                     // deUint32                     attachment;
454                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
455         };
456
457         const VkAttachmentReference colorAttachmentsReference[] = { texelsAttachmentReference, residencyAttachmentReference };
458
459         const VkAttachmentReference depthAttachmentReference =
460         {
461                 VK_ATTACHMENT_UNUSED,                                                           // deUint32                     attachment;
462                 VK_IMAGE_LAYOUT_UNDEFINED                                                       // VkImageLayout        layout;
463         };
464
465         const VkSubpassDescription subpassDescription =
466         {
467                 (VkSubpassDescriptionFlags)0,                                           // VkSubpassDescriptionFlags            flags;
468                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
469                 0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
470                 DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
471                 2u,                                                                                                     // deUint32                                                     colorAttachmentCount;
472                 colorAttachmentsReference,                                                      // const VkAttachmentReference*         pColorAttachments;
473                 DE_NULL,                                                                                        // const VkAttachmentReference*         pResolveAttachments;
474                 &depthAttachmentReference,                                                      // const VkAttachmentReference*         pDepthStencilAttachment;
475                 0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
476                 DE_NULL                                                                                         // const deUint32*                                      pPreserveAttachments;
477         };
478
479         const VkRenderPassCreateInfo renderPassInfo =
480         {
481                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
482                 DE_NULL,                                                                                        // const void*                                          pNext;
483                 (VkRenderPassCreateFlags)0,                                                     // VkRenderPassCreateFlags                      flags;
484                 2u,                                                                                                     // deUint32                                                     attachmentCount;
485                 colorAttachmentsDescription,                                            // const VkAttachmentDescription*       pAttachments;
486                 1u,                                                                                                     // deUint32                                                     subpassCount;
487                 &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
488                 0u,                                                                                                     // deUint32                                                     dependencyCount;
489                 DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
490         };
491
492         renderPass = createRenderPass(deviceInterface, *m_logicalDevice, &renderPassInfo);
493
494         // Create descriptor set layout
495         DescriptorSetLayoutBuilder descriptorLayerBuilder;
496
497         descriptorLayerBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
498
499         const Unique<VkDescriptorSetLayout> descriptorSetLayout(descriptorLayerBuilder.build(deviceInterface, *m_logicalDevice));
500
501         // Create descriptor pool
502         DescriptorPoolBuilder descriptorPoolBuilder;
503
504         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageSparseInfo.mipLevels);
505
506         descriptorPool = descriptorPoolBuilder.build(deviceInterface, *m_logicalDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, imageSparseInfo.mipLevels);
507
508         // Create sampler object
509         const tcu::Sampler                      samplerObject(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::NEAREST_MIPMAP_NEAREST, tcu::Sampler::NEAREST);
510         const VkSamplerCreateInfo       samplerCreateInfo = mapSampler(samplerObject, m_format);
511         sampler = createSampler(deviceInterface, *m_logicalDevice, &samplerCreateInfo);
512
513         // Create pipeline layout
514         const VkPushConstantRange lodConstantRange =
515         {
516                 VK_SHADER_STAGE_FRAGMENT_BIT,   // VkShaderStageFlags   stageFlags;
517                 0u,                                                             // deUint32                     offset;
518                 sizeof(deUint32),                               // deUint32                     size;
519         };
520
521         const VkPipelineLayoutCreateInfo pipelineLayoutParams =
522         {
523                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                                      sType;
524                 DE_NULL,                                                                                        // const void*                                          pNext;
525                 0u,                                                                                                     // VkPipelineLayoutCreateFlags          flags;
526                 1u,                                                                                                     // deUint32                                                     setLayoutCount;
527                 &descriptorSetLayout.get(),                                                     // const VkDescriptorSetLayout*         pSetLayouts;
528                 1u,                                                                                                     // deUint32                                                     pushConstantRangeCount;
529                 &lodConstantRange,                                                                      // const VkPushConstantRange*           pPushConstantRanges;
530         };
531
532         const Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(deviceInterface, *m_logicalDevice, &pipelineLayoutParams));
533
534         // Create graphics pipeline
535         const VkVertexInputBindingDescription vertexBinding =
536         {
537                 0u,                                                     // deUint32                             binding;
538                 vertexDataStride,                       // deUint32                             stride;
539                 VK_VERTEX_INPUT_RATE_VERTEX     // VkVertexInputRate    inputRate;
540         };
541
542         const VkVertexInputAttributeDescription vertexAttributePosition =
543         {
544                 0u,                                                     // deUint32     location;
545                 0u,                                                     // deUint32     binding;
546                 vertexFormatPosition,           // VkFormat     format;
547                 vertexBufferOffsetPosition,     // deUint32     offset;
548         };
549
550         const VkVertexInputAttributeDescription vertexAttributeTexCoord =
551         {
552                 1u,                                                     // deUint32     location;
553                 0u,                                                     // deUint32     binding;
554                 vertexFormatTexCoord,           // VkFormat     format;
555                 vertexBufferOffsetTexCoord,     // deUint32     offset;
556         };
557
558         {
559                 GraphicsPipelineBuilder graphicPipelineBuilder;
560
561                 graphicPipelineBuilder.addVertexBinding(vertexBinding);
562                 graphicPipelineBuilder.addVertexAttribute(vertexAttributePosition);
563                 graphicPipelineBuilder.addVertexAttribute(vertexAttributeTexCoord);
564                 graphicPipelineBuilder.setPrimitiveTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
565                 graphicPipelineBuilder.addDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
566                 graphicPipelineBuilder.addDynamicState(VK_DYNAMIC_STATE_SCISSOR);
567                 graphicPipelineBuilder.setAttachmentsCount(2u);
568                 graphicPipelineBuilder.setShader(deviceInterface, *m_logicalDevice, VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vertex_shader"), DE_NULL);
569                 graphicPipelineBuilder.setShader(deviceInterface, *m_logicalDevice, VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("fragment_shader"), DE_NULL);
570
571                 if (imageSparseInfo.arrayLayers > 1u)
572                 {
573                         requireFeatures(instance, physicalDevice, FEATURE_GEOMETRY_SHADER);
574                         graphicPipelineBuilder.setShader(deviceInterface, *m_logicalDevice, VK_SHADER_STAGE_GEOMETRY_BIT, m_context.getBinaryCollection().get("geometry_shader"), DE_NULL);
575                 }
576
577                 pipelines.push_back(makeVkSharedPtr(graphicPipelineBuilder.build(deviceInterface, *m_logicalDevice, *pipelineLayout, *renderPass)));
578         }
579
580         const VkPipeline graphicsPipeline = **pipelines[0];
581
582         {
583                 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers);
584
585                 VkImageMemoryBarrier imageShaderAccessBarriers[3];
586
587                 imageShaderAccessBarriers[0] = makeImageMemoryBarrier
588                 (
589                         VK_ACCESS_TRANSFER_WRITE_BIT,
590                         VK_ACCESS_SHADER_READ_BIT,
591                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
592                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
593                         imageSparse,
594                         fullImageSubresourceRange
595                 );
596
597                 imageShaderAccessBarriers[1] = makeImageMemoryBarrier
598                 (
599                         0u,
600                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
601                         VK_IMAGE_LAYOUT_UNDEFINED,
602                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
603                         imageTexels,
604                         fullImageSubresourceRange
605                 );
606
607                 imageShaderAccessBarriers[2] = makeImageMemoryBarrier
608                 (
609                         0u,
610                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
611                         VK_IMAGE_LAYOUT_UNDEFINED,
612                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
613                         imageResidency,
614                         fullImageSubresourceRange
615                 );
616
617                 deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 3u, imageShaderAccessBarriers);
618         }
619
620         imageSparseViews.resize(imageSparseInfo.mipLevels);
621         imageTexelsViews.resize(imageSparseInfo.mipLevels);
622         imageResidencyViews.resize(imageSparseInfo.mipLevels);
623         framebuffers.resize(imageSparseInfo.mipLevels);
624         descriptorSets.resize(imageSparseInfo.mipLevels);
625
626         std::vector<VkClearValue> clearValues;
627         clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
628         clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
629
630         for (deUint32 mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx)
631         {
632                 const vk::VkExtent3D mipLevelSize = mipLevelExtents(imageSparseInfo.extent, mipLevelNdx);
633
634                 const vk::VkRect2D renderArea =
635                 {
636                         makeOffset2D(0u, 0u),
637                         makeExtent2D(mipLevelSize.width, mipLevelSize.height),
638                 };
639
640                 const VkViewport viewport = makeViewport
641                 (
642                         0.0f, 0.0f,
643                         static_cast<float>(mipLevelSize.width), static_cast<float>(mipLevelSize.height),
644                         0.0f, 1.0f
645                 );
646
647                 const VkImageSubresourceRange mipLevelRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevelNdx, 1u, 0u, imageSparseInfo.arrayLayers);
648
649                 // Create color attachments image views
650                 imageTexelsViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, *m_logicalDevice, imageTexels, mapImageViewType(m_imageType), imageSparseInfo.format, mipLevelRange));
651                 imageResidencyViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, *m_logicalDevice, imageResidency, mapImageViewType(m_imageType), mapTextureFormat(m_residencyFormat), mipLevelRange));
652
653                 const VkImageView attachmentsViews[] = { **imageTexelsViews[mipLevelNdx], **imageResidencyViews[mipLevelNdx] };
654
655                 // Create framebuffer
656                 const VkFramebufferCreateInfo framebufferInfo =
657                 {
658                         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType                             sType;
659                         DE_NULL,                                                                        // const void*                                 pNext;
660                         (VkFramebufferCreateFlags)0,                            // VkFramebufferCreateFlags                    flags;
661                         *renderPass,                                                            // VkRenderPass                                renderPass;
662                         2u,                                                                                     // uint32_t                                    attachmentCount;
663                         attachmentsViews,                                                       // const VkImageView*                          pAttachments;
664                         mipLevelSize.width,                                                     // uint32_t                                    width;
665                         mipLevelSize.height,                                            // uint32_t                                    height;
666                         imageSparseInfo.arrayLayers,                            // uint32_t                                    layers;
667                 };
668
669                 framebuffers[mipLevelNdx] = makeVkSharedPtr(createFramebuffer(deviceInterface, *m_logicalDevice, &framebufferInfo));
670
671                 // Create descriptor set
672                 descriptorSets[mipLevelNdx] = makeVkSharedPtr(makeDescriptorSet(deviceInterface, *m_logicalDevice, *descriptorPool, *descriptorSetLayout));
673                 const VkDescriptorSet descriptorSet = **descriptorSets[mipLevelNdx];
674
675                 // Update descriptor set
676                 const VkImageSubresourceRange sparseImageSubresourceRange = sampledImageRangeToBind(imageSparseInfo, mipLevelNdx);
677
678                 imageSparseViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, *m_logicalDevice, imageSparse, mapImageViewType(m_imageType), imageSparseInfo.format, sparseImageSubresourceRange));
679
680                 const VkDescriptorImageInfo imageSparseDescInfo = makeDescriptorImageInfo(*sampler, **imageSparseViews[mipLevelNdx], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
681
682                 DescriptorSetUpdateBuilder descriptorUpdateBuilder;
683
684                 descriptorUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(BINDING_IMAGE_SPARSE), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSparseDescInfo);
685                 descriptorUpdateBuilder.update(deviceInterface, *m_logicalDevice);
686
687                 // Begin render pass
688                 beginRenderPass(deviceInterface, commandBuffer, *renderPass, **framebuffers[mipLevelNdx], renderArea, clearValues);
689
690                 // Bind graphics pipeline
691                 deviceInterface.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
692
693                 // Bind descriptor set
694                 deviceInterface.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
695
696                 // Bind vertex buffer
697                 deviceInterface.cmdBindVertexBuffers(commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexBufferStartOffset);
698
699                 // Bind Viewport
700                 deviceInterface.cmdSetViewport(commandBuffer, 0u, 1u, &viewport);
701
702                 // Bind Scissor Rectangle
703                 deviceInterface.cmdSetScissor(commandBuffer, 0u, 1u, &renderArea);
704
705                 // Update push constants
706                 deviceInterface.cmdPushConstants(commandBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(deUint32), &mipLevelNdx);
707
708                 // Draw full screen quad
709                 deviceInterface.cmdDraw(commandBuffer, 4u, 1u, 0u, 0u);
710
711                 // End render pass
712                 endRenderPass(deviceInterface, commandBuffer);
713         }
714
715         {
716                 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers);
717
718                 VkImageMemoryBarrier imageOutputTransferSrcBarriers[2];
719
720                 imageOutputTransferSrcBarriers[0] = makeImageMemoryBarrier
721                 (
722                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
723                         VK_ACCESS_TRANSFER_READ_BIT,
724                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
725                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
726                         imageTexels,
727                         fullImageSubresourceRange
728                 );
729
730                 imageOutputTransferSrcBarriers[1] = makeImageMemoryBarrier
731                 (
732                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
733                         VK_ACCESS_TRANSFER_READ_BIT,
734                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
735                         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
736                         imageResidency,
737                         fullImageSubresourceRange
738                 );
739
740                 deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputTransferSrcBarriers);
741         }
742 }
743
744 class SparseShaderIntrinsicsInstanceSampledExplicit : public SparseShaderIntrinsicsInstanceSampledBase
745 {
746 public:
747         SparseShaderIntrinsicsInstanceSampledExplicit   (Context&                                       context,
748                                                                                                          const SpirVFunction            function,
749                                                                                                          const ImageType                        imageType,
750                                                                                                          const tcu::UVec3&                      imageSize,
751                                                                                                          const tcu::TextureFormat&      format)
752         : SparseShaderIntrinsicsInstanceSampledBase(context, function, imageType, imageSize, format) {}
753
754         VkImageSubresourceRange sampledImageRangeToBind(const VkImageCreateInfo& imageSparseInfo, const deUint32 mipLevel) const;
755 };
756
757 VkImageSubresourceRange SparseShaderIntrinsicsInstanceSampledExplicit::sampledImageRangeToBind (const VkImageCreateInfo& imageSparseInfo, const deUint32 mipLevel) const
758 {
759         DE_UNREF(mipLevel);
760
761         return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers);
762 }
763
764 TestInstance* SparseShaderIntrinsicsCaseSampledExplicit::createInstance (Context& context) const
765 {
766         return new SparseShaderIntrinsicsInstanceSampledExplicit(context, m_function, m_imageType, m_imageSize, m_format);
767 }
768
769 class SparseShaderIntrinsicsInstanceSampledImplicit : public SparseShaderIntrinsicsInstanceSampledBase
770 {
771 public:
772         SparseShaderIntrinsicsInstanceSampledImplicit   (Context&                                       context,
773                                                                                                          const SpirVFunction            function,
774                                                                                                          const ImageType                        imageType,
775                                                                                                          const tcu::UVec3&                      imageSize,
776                                                                                                          const tcu::TextureFormat&      format)
777         : SparseShaderIntrinsicsInstanceSampledBase(context, function, imageType, imageSize, format) {}
778
779         VkImageSubresourceRange sampledImageRangeToBind(const VkImageCreateInfo& imageSparseInfo, const deUint32 mipLevel) const;
780 };
781
782 VkImageSubresourceRange SparseShaderIntrinsicsInstanceSampledImplicit::sampledImageRangeToBind (const VkImageCreateInfo& imageSparseInfo, const deUint32 mipLevel) const
783 {
784         return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, 0u, imageSparseInfo.arrayLayers);
785 }
786
787 TestInstance* SparseShaderIntrinsicsCaseSampledImplicit::createInstance (Context& context) const
788 {
789         return new SparseShaderIntrinsicsInstanceSampledImplicit(context, m_function, m_imageType, m_imageSize, m_format);
790 }
791
792 } // sparse
793 } // vkt