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