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 ©Region);
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