1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 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
21 * \brief Vulkan Decriptor Indexing Tests
22 *//*--------------------------------------------------------------------*/
23 
24 #include <algorithm>
25 #include <iostream>
26 #include <iterator>
27 #include <functional>
28 #include <sstream>
29 #include <utility>
30 #include <vector>
31 
32 #include "vktDescriptorSetsIndexingTests.hpp"
33 
34 #include "vkBuilderUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vkDefs.hpp"
37 #include "vkObjUtil.hpp"
38 #include "vkPlatform.hpp"
39 #include "vkPrograms.hpp"
40 #include "vkQueryUtil.hpp"
41 #include "vkTypeUtil.hpp"
42 
43 #include "tcuTestLog.hpp"
44 #include "tcuResource.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuCommandLine.hpp"
47 #include "tcuStringTemplate.hpp"
48 
49 #include "deRandom.hpp"
50 #include "deMath.h"
51 #include "deStringUtil.hpp"
52 
53 namespace vkt
54 {
55 namespace DescriptorIndexing
56 {
57 using namespace vk;
58 namespace ut
59 {
60 
ImageHandleAlloc(Move<VkImage> & image_,AllocMv & alloc_,const VkExtent3D & extent_,VkFormat format_,bool usesMipMaps_)61 ImageHandleAlloc::ImageHandleAlloc(Move<VkImage> &image_, AllocMv &alloc_, const VkExtent3D &extent_, VkFormat format_,
62                                    bool usesMipMaps_)
63     : image(image_)
64     , alloc(alloc_)
65     , extent(extent_)
66     , format(format_)
67     , levels(usesMipMaps_ ? computeMipMapCount(extent_) : 1)
68 {
69 }
70 
buildShaderName(VkShaderStageFlagBits stage,VkDescriptorType descriptorType,bool updateAfterBind,bool calculateInLoop,bool minNonUniform,bool performWritesInVertex)71 std::string buildShaderName(VkShaderStageFlagBits stage, VkDescriptorType descriptorType, bool updateAfterBind,
72                             bool calculateInLoop, bool minNonUniform, bool performWritesInVertex)
73 {
74     const char *stageName = DE_NULL;
75     switch (stage)
76     {
77     case VK_SHADER_STAGE_VERTEX_BIT:
78         stageName = "vert";
79         break;
80     case VK_SHADER_STAGE_FRAGMENT_BIT:
81         stageName = "frag";
82         break;
83     case VK_SHADER_STAGE_COMPUTE_BIT:
84         stageName = "comp";
85         break;
86     case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
87         stageName = "tesc";
88         break;
89     case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
90         stageName = "tese";
91         break;
92     case VK_SHADER_STAGE_GEOMETRY_BIT:
93         stageName = "geom";
94         break;
95     default:
96         stageName = "any";
97         break;
98     }
99     DE_ASSERT(stageName);
100 
101     std::map<std::string, std::string> m;
102     m["STAGE"] = stageName;
103     m["DESC"]  = de::toString(uint32_t(descriptorType));
104     m["ABIND"] = updateAfterBind ? "_afterBind" : "";
105     m["LOOP"]  = calculateInLoop ? "_inLoop" : "";
106     m["MINNU"] = minNonUniform ? "_minNonUniform" : "";
107     m["SHWR"]  = performWritesInVertex ? "_shaderWrites" : "";
108 
109     return tcu::StringTemplate("descriptorIndexing_${STAGE}${DESC}${ABIND}${LOOP}${MINNU}${SHWR}").specialize(m);
110 }
111 
generatePrimes(uint32_t limit)112 std::vector<uint32_t> generatePrimes(uint32_t limit)
113 {
114     uint32_t i, j, *data;
115     std::vector<uint32_t> v(limit);
116 
117     data = v.data();
118 
119     for (i = 0; i < limit; ++i)
120         data[i] = i;
121 
122     for (i = 2; i < limit; ++i)
123     {
124         if (data[i])
125         {
126             for (j = i * 2; j < limit; j += i)
127                 data[j] = 0;
128         }
129     }
130 
131     std::vector<uint32_t>::iterator x =
132         std::stable_partition(v.begin(), v.end(), [](uint32_t value) { return value >= 2; });
133 
134     return std::vector<uint32_t>(v.begin(), x);
135 }
136 
computePrimeCount(uint32_t limit)137 uint32_t computePrimeCount(uint32_t limit)
138 {
139     uint32_t i, j, k, *data;
140     std::vector<uint32_t> v(limit);
141 
142     data = v.data();
143 
144     for (i = 0; i < limit; ++i)
145         data[i] = i;
146 
147     k = 0;
148     for (i = 2; i < limit; ++i)
149     {
150         if (data[i])
151         {
152             ++k;
153             for (j = i * 2; j < limit; j += i)
154                 data[j] = 0;
155         }
156     }
157     return k;
158 }
159 
computeMipMapCount(const VkExtent3D & extent)160 uint32_t computeMipMapCount(const VkExtent3D &extent)
161 {
162     return uint32_t(floor(log2(std::max(extent.width, extent.height)))) + 1;
163 }
164 
computeImageSize(const VkExtent3D & extent,VkFormat format,bool withMipMaps,uint32_t level)165 uint32_t computeImageSize(const VkExtent3D &extent, VkFormat format, bool withMipMaps, uint32_t level)
166 {
167     uint32_t mipSize = extent.width * extent.height * extent.depth * vk::mapVkFormat(format).getPixelSize();
168     if (withMipMaps)
169     {
170         uint32_t mipIdx         = 0u;
171         uint32_t width          = extent.width;
172         uint32_t height         = extent.height;
173         const uint32_t mipCount = computeMipMapCount(extent) - 1;
174         do
175         {
176             width /= 2;
177             height /= 2;
178             uint32_t tmpSize = width * height * extent.depth * vk::mapVkFormat(format).getPixelSize();
179 
180             if (level == mipIdx)
181             {
182                 break;
183             }
184             else if (level == maxDeUint32)
185             {
186                 mipSize += tmpSize;
187             }
188             else
189             {
190                 mipSize = tmpSize;
191             }
192 
193         } while (++mipIdx < mipCount);
194     }
195     return mipSize;
196 }
197 
computeImageSize(const ImageHandleAllocSp & image)198 uint32_t computeImageSize(const ImageHandleAllocSp &image)
199 {
200     return computeImageSize(image->extent, image->format);
201 }
202 
createImageAndBind(ut::ImageHandleAllocSp & output,const vkt::Context & ctx,VkFormat colorFormat,const VkExtent3D & extent,VkImageLayout initialLayout,bool withMipMaps,VkImageType imageType)203 void createImageAndBind(ut::ImageHandleAllocSp &output, const vkt::Context &ctx, VkFormat colorFormat,
204                         const VkExtent3D &extent, VkImageLayout initialLayout, bool withMipMaps, VkImageType imageType)
205 {
206     const bool isDepthStencilFormat = vk::isDepthStencilFormat(colorFormat);
207 
208     const VkImageUsageFlags imageUsageFlagsDependent =
209         isDepthStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
210 
211     const VkImageUsageFlags imageUsageFlags = imageUsageFlagsDependent | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
212                                               VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
213                                               VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
214 
215     const uint32_t mipLevels           = withMipMaps ? computeMipMapCount(extent) : 1;
216     const VkImageCreateInfo createInfo = {
217         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
218         DE_NULL,                             // pNext
219         (VkImageCreateFlags)0,               // flags
220         imageType,                           // imageType
221         colorFormat,                         // format
222         extent,                              // extent
223         mipLevels,                           // mipLevels
224         (uint32_t)1,                         // arrayLayers
225         VK_SAMPLE_COUNT_1_BIT,               // samples
226         VK_IMAGE_TILING_OPTIMAL,             // tiling
227         imageUsageFlags,                     // usage
228         VK_SHARING_MODE_EXCLUSIVE,           // sharingMode
229         (uint32_t)0,                         // queueFamilyCount
230         DE_NULL,                             // pQueueFamilyIndices
231         initialLayout                        // initialLayout
232     };
233 
234     Allocator &allocator              = ctx.getDefaultAllocator();
235     VkDevice device                   = ctx.getDevice();
236     const DeviceInterface &dinterface = ctx.getDeviceInterface();
237 
238     Move<VkImage> image = vk::createImage(dinterface, device, &createInfo);
239 
240     const VkMemoryRequirements memReqs = vk::getImageMemoryRequirements(dinterface, device, *image);
241     de::MovePtr<Allocation> allocation = allocator.allocate(memReqs, MemoryRequirement::Any);
242 
243     VK_CHECK(dinterface.bindImageMemory(device, *image, allocation->getMemory(), allocation->getOffset()));
244 
245     output = ImageHandleAllocSp(new ImageHandleAlloc(image, allocation, extent, colorFormat, withMipMaps));
246 }
247 
recordCopyBufferToImage(VkCommandBuffer cmd,const DeviceInterface & interface,VkPipelineStageFlagBits srcStageMask,VkPipelineStageFlagBits dstStageMask,const VkDescriptorBufferInfo & bufferInfo,VkImage image,const VkExtent3D & imageExtent,VkFormat imageFormat,VkImageLayout oldImageLayout,VkImageLayout newImageLayout,uint32_t mipLevelCount)248 void recordCopyBufferToImage(VkCommandBuffer cmd, const DeviceInterface &interface,
249                              VkPipelineStageFlagBits srcStageMask, VkPipelineStageFlagBits dstStageMask,
250                              const VkDescriptorBufferInfo &bufferInfo, VkImage image, const VkExtent3D &imageExtent,
251                              VkFormat imageFormat, VkImageLayout oldImageLayout, VkImageLayout newImageLayout,
252                              uint32_t mipLevelCount)
253 {
254     const VkImageAspectFlags imageAspect = vk::isDepthStencilFormat(imageFormat) ?
255                                                VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT :
256                                                VK_IMAGE_ASPECT_COLOR_BIT;
257 
258     std::vector<VkBufferImageCopy> copyRegions;
259     {
260         uint32_t width            = imageExtent.width;
261         uint32_t height           = imageExtent.height;
262         VkDeviceSize bufferOffset = bufferInfo.offset;
263 
264         for (uint32_t mipIdx = 0; mipIdx < mipLevelCount; ++mipIdx)
265         {
266             VkDeviceSize imageSize = computeImageSize(imageExtent, imageFormat, true, mipIdx);
267 
268             const VkBufferImageCopy copyRegion = {
269                 bufferOffset, // bufferOffset
270                 width,        // bufferRowLength
271                 height,       // bufferImageHeight
272                 {
273                     imageAspect,   // aspect
274                     mipIdx,        // mipLevel
275                     0u,            // baseArrayLayer
276                     1u,            // layerCount
277                 },                 // VkImageSubresourceLayers imageSubresource
278                 {0, 0, 0},         // VkOffset3D                imageOffset
279                 {width, height, 1} // VkExtent3D                imageExtent
280             };
281 
282             copyRegions.push_back(copyRegion);
283 
284             bufferOffset += imageSize;
285             width /= 2;
286             height /= 2;
287         }
288     }
289 
290     const VkImageSubresourceRange subresourceRange = {
291         imageAspect,   // aspectMask
292         0u,            // baseMipLevel
293         mipLevelCount, // levelCount
294         0u,            // baseArrayLayer
295         1u,            // layerCount
296     };
297 
298     const VkImageMemoryBarrier barrierBefore = {
299         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType;
300         DE_NULL,                                // pNext;
301         0,                                      // srcAccessMask;
302         VK_ACCESS_TRANSFER_WRITE_BIT,           // dstAccessMask;
303         oldImageLayout,                         // oldLayout;
304         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // newLayout;
305         VK_QUEUE_FAMILY_IGNORED,                // srcQueueFamilyIndex;
306         VK_QUEUE_FAMILY_IGNORED,                // dstQueueFamilyIndex;
307         image,                                  // image
308         subresourceRange                        // subresourceRange
309     };
310 
311     const VkBufferMemoryBarrier bufferBarrier = {
312         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,      // sType;
313         DE_NULL,                                      // pNext;
314         pipelineAccessFromStage(srcStageMask, false), // srcAccessMask;
315         VK_ACCESS_TRANSFER_READ_BIT,                  // dstAccessMask;
316         VK_QUEUE_FAMILY_IGNORED,                      // srcQueueFamilyIndex;
317         VK_QUEUE_FAMILY_IGNORED,                      // dstQueueFamilyIndex;
318         bufferInfo.buffer,                            // buffer;
319         bufferInfo.offset,                            // offset;
320         bufferInfo.range                              // size;
321     };
322 
323     const VkImageMemoryBarrier barrierAfter = {
324         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                                     // sType;
325         DE_NULL,                                                                                    // pNext;
326         VK_ACCESS_TRANSFER_WRITE_BIT,                                                               // srcAccessMask;
327         pipelineAccessFromStage(dstStageMask, true) | pipelineAccessFromStage(dstStageMask, false), // dstAccessMask;
328         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,                                                       // oldLayout;
329         newImageLayout,                                                                             // newLayout;
330         VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex;
331         VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex;
332         image,                   // image
333         subresourceRange         // subresourceRange
334     };
335 
336     interface.cmdPipelineBarrier(cmd, srcStageMask, VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask, dstStageMask
337                                  (VkDependencyFlags)0,                              // dependencyFlags
338                                  0u, DE_NULL,         // memoryBarrierCount, pMemoryBarriers
339                                  1u, &bufferBarrier,  // bufferBarrierCount, pBufferBarriers
340                                  1u, &barrierBefore); // imageBarrierCount, pImageBarriers
341 
342     interface.cmdCopyBufferToImage(cmd, bufferInfo.buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
343                                    static_cast<uint32_t>(copyRegions.size()), copyRegions.data());
344 
345     interface.cmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, dstStageMask, // srcStageMask, dstStageMask
346                                  (VkDependencyFlags)0,                              // dependencyFlags
347                                  0u, DE_NULL,        // memoryBarrierCount, pMemoryBarriers
348                                  0u, DE_NULL,        // bufferBarrierCount, pBufferBarriers
349                                  1u, &barrierAfter); // imageBarrierCount, pImageBarriers
350 }
351 
recordCopyImageToBuffer(VkCommandBuffer cmd,const DeviceInterface & interface,VkPipelineStageFlagBits srcStageMask,VkPipelineStageFlagBits dstStageMask,VkImage image,const VkExtent3D & imageExtent,VkFormat imageFormat,VkImageLayout oldImageLayout,VkImageLayout newImageLayout,const VkDescriptorBufferInfo & bufferInfo)352 void recordCopyImageToBuffer(VkCommandBuffer cmd, const DeviceInterface &interface,
353                              VkPipelineStageFlagBits srcStageMask, VkPipelineStageFlagBits dstStageMask, VkImage image,
354                              const VkExtent3D &imageExtent, VkFormat imageFormat, VkImageLayout oldImageLayout,
355                              VkImageLayout newImageLayout, const VkDescriptorBufferInfo &bufferInfo)
356 {
357     const VkImageAspectFlags imageAspect = vk::isDepthStencilFormat(imageFormat) ?
358                                                VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT :
359                                                VK_IMAGE_ASPECT_COLOR_BIT;
360 
361     const VkBufferImageCopy copyRegion = {
362         bufferInfo.offset,  // bufferOffset
363         imageExtent.width,  // bufferRowLength
364         imageExtent.height, // bufferImageHeight
365         {
366             imageAspect, // aspect
367             0u,          // mipLevel
368             0u,          // baseArrayLayer
369             1u,          // layerCount
370         },               // VkImageSubresourceLayers
371         {0, 0, 0},       // imageOffset
372         imageExtent      // imageExtent
373     };
374 
375     VkImageSubresourceRange subresourceRange = {
376         VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
377         0u,                        // baseMipLevel
378         1u,                        // levelCount
379         0u,                        // baseArrayLayer
380         1u,                        // layerCount
381     };
382 
383     const VkImageMemoryBarrier barrierBefore = {
384         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,       // sType;
385         DE_NULL,                                      // pNext;
386         pipelineAccessFromStage(srcStageMask, false), // srcAccessMask;
387         VK_ACCESS_TRANSFER_READ_BIT,                  // dstAccessMask;
388         oldImageLayout,                               // oldLayout
389         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,         // newLayout;
390         VK_QUEUE_FAMILY_IGNORED,                      // srcQueueFamilyIndex;
391         VK_QUEUE_FAMILY_IGNORED,                      // dstQueueFamilyIndex;
392         image,                                        // image;
393         subresourceRange,                             // subresourceRange;
394     };
395 
396     const VkImageMemoryBarrier barrierAfter = {
397         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                                                     // sType;
398         DE_NULL,                                                                                    // pNext;
399         VK_ACCESS_TRANSFER_READ_BIT,                                                                // srcAccessMask;
400         pipelineAccessFromStage(dstStageMask, true) | pipelineAccessFromStage(dstStageMask, false), // dstAccessMask;
401         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,                                                       // oldLayout;
402         newImageLayout,                                                                             // newLayout;
403         VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex;
404         VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex;
405         image,                   // image
406         subresourceRange         // subresourceRange
407     };
408 
409     interface.cmdPipelineBarrier(cmd,                                          // commandBuffer
410                                  srcStageMask, VK_PIPELINE_STAGE_TRANSFER_BIT, // srcStageMask, dstStageMask
411                                  (VkDependencyFlags)0,                         // dependencyFlags
412                                  0u, DE_NULL,                                  // memoryBarrierCount, pMemoryBarriers
413                                  0u, DE_NULL,                                  // bufferBarrierCount, pBufferBarriers
414                                  1u, &barrierBefore);                          // imageBarrierCount, pImageBarriers
415 
416     interface.cmdCopyImageToBuffer(cmd, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferInfo.buffer, 1u,
417                                    &copyRegion);
418 
419     interface.cmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, dstStageMask, (VkDependencyFlags)0, 0u, DE_NULL,
420                                  0u, DE_NULL, 0u, &barrierAfter);
421 }
422 
pipelineAccessFromStage(VkPipelineStageFlagBits stage,bool readORwrite)423 VkAccessFlags pipelineAccessFromStage(VkPipelineStageFlagBits stage, bool readORwrite)
424 {
425     VkAccessFlags access[2];
426     VkAccessFlags &readAccess  = access[1];
427     VkAccessFlags &writeAccess = access[0];
428     readAccess = writeAccess = static_cast<VkAccessFlagBits>(0);
429 
430     switch (stage)
431     {
432     case VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT:
433     case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT:
434         readAccess = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
435         break;
436 
437     case VK_PIPELINE_STAGE_VERTEX_INPUT_BIT:
438         readAccess = static_cast<VkAccessFlagBits>(VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
439         break;
440 
441     case VK_PIPELINE_STAGE_VERTEX_SHADER_BIT:
442     case VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT:
443     case VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT:
444     case VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT:
445     case VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT:
446         readAccess  = VK_ACCESS_SHADER_READ_BIT;
447         writeAccess = VK_ACCESS_SHADER_WRITE_BIT;
448         break;
449 
450     case VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT:
451         readAccess  = static_cast<VkAccessFlagBits>(VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_SHADER_READ_BIT |
452                                                    VK_ACCESS_INPUT_ATTACHMENT_READ_BIT);
453         writeAccess = VK_ACCESS_SHADER_READ_BIT;
454         break;
455 
456     case VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT:
457         readAccess  = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
458         writeAccess = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
459         break;
460 
461     case VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT:
462     case VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT:
463         readAccess  = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
464         writeAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
465         break;
466 
467     case VK_PIPELINE_STAGE_TRANSFER_BIT:
468         readAccess  = VK_ACCESS_TRANSFER_READ_BIT;
469         writeAccess = VK_ACCESS_TRANSFER_WRITE_BIT;
470         break;
471 
472     case VK_PIPELINE_STAGE_HOST_BIT:
473         readAccess  = VK_ACCESS_HOST_READ_BIT;
474         writeAccess = VK_ACCESS_HOST_WRITE_BIT;
475         break;
476 
477     default:
478         if (stage == 0)
479         {
480             readAccess  = VK_ACCESS_MEMORY_READ_BIT;
481             writeAccess = VK_ACCESS_MEMORY_WRITE_BIT;
482             break;
483         }
484 
485         DE_ASSERT(false);
486     }
487     return access[readORwrite ? 1 : 0];
488 }
489 
createFrameBuffer(FrameBufferSp & outputFB,const vkt::Context & context,const VkExtent3D & extent,VkFormat colorFormat,VkRenderPass renderpass,uint32_t additionalAttachmentCount,const VkImageView additionalAttachments[])490 void createFrameBuffer(FrameBufferSp &outputFB, const vkt::Context &context, const VkExtent3D &extent,
491                        VkFormat colorFormat, VkRenderPass renderpass, uint32_t additionalAttachmentCount,
492                        const VkImageView additionalAttachments[])
493 {
494     outputFB                         = FrameBufferSp(new ut::FrameBuffer);
495     VkDevice device                  = context.getDevice();
496     const DeviceInterface &interface = context.getDeviceInterface();
497     createImageAndBind(outputFB->image, context, colorFormat, extent, VK_IMAGE_LAYOUT_UNDEFINED);
498 
499     // create and attachment0
500     {
501         const VkImageViewCreateInfo viewCreateInfo = {
502             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
503             DE_NULL,                                  // pNext
504             (VkImageViewCreateFlags)0,                // flags
505             *outputFB->image->image,                  // image
506             VK_IMAGE_VIEW_TYPE_2D,                    // viewType
507             colorFormat,                              // format
508             vk::makeComponentMappingRGBA(),           // components
509             {
510                 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
511                 (uint32_t)0,               // baseMipLevel
512                 (uint32_t)1,               // mipLevels
513                 (uint32_t)0,               // baseArrayLayer
514                 (uint32_t)1u,              // arraySize
515             },
516         };
517 
518         outputFB->attachment0 = vk::createImageView(interface, device, &viewCreateInfo);
519 
520         std::vector<VkImageView> &attachments(outputFB->attachments);
521         attachments.push_back(*outputFB->attachment0);
522         if (additionalAttachments && additionalAttachmentCount)
523         {
524             attachments.insert(attachments.end(), additionalAttachments,
525                                additionalAttachments + additionalAttachmentCount);
526         }
527     }
528 
529     // create a frame buffer
530     {
531         std::vector<VkImageView> &attachments(outputFB->attachments);
532 
533         const VkFramebufferCreateInfo framebufferCreateInfo = {
534             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
535             DE_NULL,                                   // pNext
536             (VkFramebufferCreateFlags)0,               // flags
537             renderpass,                                // renderPass
538             static_cast<uint32_t>(attachments.size()), // attachmentCount
539             attachments.data(),                        // pAttachments
540             extent.width,                              // width
541             extent.height,                             // height
542             (uint32_t)1                                // layers
543         };
544 
545         outputFB->buffer = vk::createFramebuffer(interface, device, &framebufferCreateInfo);
546     }
547 }
548 
createBufferAndBind(ut::BufferHandleAllocSp & output,const vkt::Context & ctx,VkBufferUsageFlags usage,VkDeviceSize desiredSize)549 VkDeviceSize createBufferAndBind(ut::BufferHandleAllocSp &output, const vkt::Context &ctx, VkBufferUsageFlags usage,
550                                  VkDeviceSize desiredSize)
551 {
552     const size_t nonCoherentAtomSize(static_cast<size_t>(ctx.getDeviceProperties().limits.nonCoherentAtomSize));
553     const VkDeviceSize roundedSize(deAlignSize(static_cast<size_t>(desiredSize), nonCoherentAtomSize));
554     Allocator &allocator(ctx.getDefaultAllocator());
555     VkDevice device(ctx.getDevice());
556     const DeviceInterface &interface(ctx.getDeviceInterface());
557 
558     const VkBufferCreateInfo createInfo = {
559         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
560         DE_NULL,                              // pNext
561         (VkBufferCreateFlags)0,               // flags
562         roundedSize,                          // size
563         usage,                                // usage
564         VK_SHARING_MODE_EXCLUSIVE,            // sharingMode
565         0u,                                   // queueFamilyIndexCount
566         DE_NULL,                              // pQueueFamilyIndices
567     };
568 
569     Move<VkBuffer> buffer = vk::createBuffer(interface, device, &createInfo);
570 
571     const VkMemoryRequirements memRequirements = vk::getBufferMemoryRequirements(interface, device, *buffer);
572     de::MovePtr<Allocation> allocation         = allocator.allocate(memRequirements, MemoryRequirement::HostVisible);
573 
574     VK_CHECK(interface.bindBufferMemory(device, *buffer, allocation->getMemory(), allocation->getOffset()));
575 
576     output = BufferHandleAllocSp(new BufferHandleAlloc(buffer, allocation));
577 
578     return roundedSize;
579 }
580 
createVertices(uint32_t width,uint32_t height,float & xSize,float & ySize)581 std::vector<tcu::Vec4> createVertices(uint32_t width, uint32_t height, float &xSize, float &ySize)
582 {
583     std::vector<tcu::Vec4> result;
584 
585     const float xStep  = 2.0f / static_cast<float>(width);
586     const float yStep  = 2.0f / static_cast<float>(height);
587     const float xStart = -1.0f + xStep / 2.0f;
588     const float yStart = -1.0f + yStep / 2.0f;
589 
590     xSize = xStep;
591     ySize = yStep;
592 
593     float x = xStart;
594     float y = yStart;
595 
596     result.reserve(width * height);
597 
598     for (uint32_t row = 0u; row < height; ++row)
599     {
600         for (uint32_t col = 0u; col < width; ++col)
601         {
602             result.push_back(tcu::Vec4(x, y, 1.0f, 1.0f));
603             x += xStep;
604         }
605 
606         y += yStep;
607         x = xStart;
608     }
609 
610     return result;
611 }
612 
isDynamicDescriptor(VkDescriptorType descriptorType)613 bool isDynamicDescriptor(VkDescriptorType descriptorType)
614 {
615     return descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
616            descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
617 }
618 
DeviceProperties(const DeviceProperties & src)619 DeviceProperties::DeviceProperties(const DeviceProperties &src)
620 {
621     m_descriptorIndexingFeatures = src.m_descriptorIndexingFeatures;
622     m_features2                  = src.m_features2;
623 
624     m_descriptorIndexingProperties = src.m_descriptorIndexingProperties;
625     m_properties2                  = src.m_properties2;
626 }
627 
DeviceProperties(const vkt::Context & testContext)628 DeviceProperties::DeviceProperties(const vkt::Context &testContext)
629 {
630     VkPhysicalDevice device            = testContext.getPhysicalDevice();
631     const InstanceInterface &interface = testContext.getInstanceInterface();
632 
633     deMemset(&m_descriptorIndexingFeatures, 0, sizeof(m_descriptorIndexingFeatures));
634     m_descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES;
635     m_descriptorIndexingFeatures.pNext = DE_NULL;
636 
637     deMemset(&m_features2, 0, sizeof(m_features2));
638     m_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
639     m_features2.pNext = &m_descriptorIndexingFeatures;
640 
641     interface.getPhysicalDeviceFeatures2(device, &m_features2);
642 
643     deMemset(&m_descriptorIndexingProperties, 0, sizeof(m_descriptorIndexingProperties));
644     m_descriptorIndexingProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES;
645     m_descriptorIndexingProperties.pNext = DE_NULL;
646 
647     deMemset(&m_properties2, 0, sizeof(m_properties2));
648     m_properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
649     m_properties2.pNext = &m_descriptorIndexingProperties;
650 
651     interface.getPhysicalDeviceProperties2(device, &m_properties2);
652 }
653 
computeMaxPerStageDescriptorCount(VkDescriptorType descriptorType,bool enableUpdateAfterBind,bool reserveUniformTexelBuffer) const654 uint32_t DeviceProperties::computeMaxPerStageDescriptorCount(VkDescriptorType descriptorType,
655                                                              bool enableUpdateAfterBind,
656                                                              bool reserveUniformTexelBuffer) const
657 {
658     const VkPhysicalDeviceDescriptorIndexingProperties &descriptorProps = descriptorIndexingProperties();
659     const VkPhysicalDeviceProperties &deviceProps                       = physicalDeviceProperties();
660 
661     uint32_t result                = 0;
662     uint32_t samplers              = 0;
663     uint32_t uniformBuffers        = 0;
664     uint32_t uniformBuffersDynamic = 0;
665     uint32_t storageBuffers        = 0;
666     uint32_t storageBuffersDynamic = 0;
667     uint32_t sampledImages         = 0;
668     uint32_t storageImages         = 0;
669     uint32_t inputAttachments      = 0;
670 #ifndef CTS_USES_VULKANSC
671     uint32_t inlineUniforms = 0;
672 #endif
673 
674     // in_loop tests use an additional single texel buffer, which is calculated against the limits below
675     const uint32_t reservedCount = (reserveUniformTexelBuffer ? 1u : 0u);
676 
677     const uint32_t resources = deviceProps.limits.maxPerStageResources - reservedCount;
678 
679     if (enableUpdateAfterBind)
680     {
681         samplers              = deMinu32(descriptorProps.maxPerStageDescriptorUpdateAfterBindSamplers,
682                                          descriptorProps.maxDescriptorSetUpdateAfterBindSamplers); // 1048576
683         uniformBuffers        = deMinu32(descriptorProps.maxPerStageDescriptorUpdateAfterBindUniformBuffers,
684                                          descriptorProps.maxDescriptorSetUpdateAfterBindUniformBuffers); // 15
685         uniformBuffersDynamic = deMinu32(descriptorProps.maxPerStageDescriptorUpdateAfterBindUniformBuffers,
686                                          descriptorProps.maxDescriptorSetUpdateAfterBindUniformBuffersDynamic); // 8
687         storageBuffers        = deMinu32(descriptorProps.maxPerStageDescriptorUpdateAfterBindStorageBuffers,
688                                          descriptorProps.maxDescriptorSetUpdateAfterBindStorageBuffers); // 1048576
689         storageBuffersDynamic = deMinu32(descriptorProps.maxPerStageDescriptorUpdateAfterBindStorageBuffers,
690                                          descriptorProps.maxDescriptorSetUpdateAfterBindStorageBuffersDynamic); // 8
691         sampledImages         = deMinu32(descriptorProps.maxPerStageDescriptorUpdateAfterBindSampledImages,
692                                          descriptorProps.maxDescriptorSetUpdateAfterBindSampledImages); // 1048576
693         storageImages         = deMinu32(descriptorProps.maxPerStageDescriptorUpdateAfterBindStorageImages,
694                                          descriptorProps.maxDescriptorSetUpdateAfterBindStorageImages); // 1048576
695         inputAttachments      = deMinu32(descriptorProps.maxPerStageDescriptorUpdateAfterBindInputAttachments,
696                                          descriptorProps.maxDescriptorSetUpdateAfterBindInputAttachments); // 1048576
697     }
698     else
699     {
700         samplers              = deMinu32(deviceProps.limits.maxPerStageDescriptorSamplers,
701                                          deviceProps.limits.maxDescriptorSetSamplers); // 1048576
702         uniformBuffers        = deMinu32(deviceProps.limits.maxPerStageDescriptorUniformBuffers,
703                                          deviceProps.limits.maxDescriptorSetUniformBuffers); // 15
704         uniformBuffersDynamic = deMinu32(deviceProps.limits.maxPerStageDescriptorUniformBuffers,
705                                          deviceProps.limits.maxDescriptorSetUniformBuffersDynamic); // 8
706         storageBuffers        = deMinu32(deviceProps.limits.maxPerStageDescriptorStorageBuffers,
707                                          deviceProps.limits.maxDescriptorSetStorageBuffers); // 1048576
708         storageBuffersDynamic = deMinu32(deviceProps.limits.maxPerStageDescriptorStorageBuffers,
709                                          deviceProps.limits.maxDescriptorSetStorageBuffersDynamic); // 8
710         sampledImages         = deMinu32(deviceProps.limits.maxPerStageDescriptorSampledImages - reservedCount,
711                                          deviceProps.limits.maxDescriptorSetSampledImages - reservedCount); // 1048576.
712         storageImages         = deMinu32(deviceProps.limits.maxPerStageDescriptorStorageImages,
713                                          deviceProps.limits.maxDescriptorSetStorageImages); // 1048576
714         inputAttachments      = deMinu32(
715             deviceProps.limits.maxPerStageDescriptorInputAttachments - 1,
716             deviceProps.limits.maxDescriptorSetInputAttachments -
717                 1); // 1048576. -1 because tests use a prime number + 1 to reference subpass input attachment in shader
718     }
719 
720     // adding arbitrary upper bound limits to restrain the size of the test ( we are testing big arrays, not the maximum size arrays )
721     samplers              = deMinu32(samplers, 4096);
722     uniformBuffers        = deMinu32(uniformBuffers, 16);
723     uniformBuffersDynamic = deMinu32(uniformBuffersDynamic, 16);
724     storageBuffers        = deMinu32(storageBuffers, 8192);
725     storageBuffersDynamic = deMinu32(storageBuffersDynamic, 8192);
726     sampledImages         = deMinu32(sampledImages, 8192);
727     storageImages         = deMinu32(storageImages, 8192);
728     inputAttachments      = deMinu32(inputAttachments, 16);
729 
730     switch (descriptorType)
731     {
732     case VK_DESCRIPTOR_TYPE_SAMPLER:
733         result = samplers;
734         break;
735     case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
736         result = deMinu32(resources, deMinu32(samplers, sampledImages));
737         break;
738     case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
739         result = deMinu32(resources, sampledImages);
740         break;
741     case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
742         result = deMinu32(resources, storageImages);
743         break;
744     case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
745         result = deMinu32(resources, sampledImages);
746         break;
747     case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
748         result = deMinu32(resources, storageImages);
749         break;
750     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
751         result = deMinu32(resources, uniformBuffers);
752         break;
753     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
754         result = deMinu32(resources, storageBuffers);
755         break;
756     case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
757         result = deMinu32(resources, uniformBuffersDynamic);
758         break;
759     case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
760         result = deMinu32(resources, storageBuffersDynamic);
761         break;
762     case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
763         result = deMinu32(resources, inputAttachments);
764         break;
765 #ifndef CTS_USES_VULKANSC
766     case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
767         result = deMinu32(resources, inlineUniforms);
768         break;
769 #endif
770     default:
771         DE_ASSERT(0);
772     }
773 
774     DE_ASSERT(result);
775 
776     return result;
777 }
778 
779 } // namespace ut
780 } // namespace DescriptorIndexing
781 } // namespace vkt
782