1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file vktSparseResourcesTestsUtil.cpp
21 * \brief Sparse Resources Tests Utility Classes
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSparseResourcesTestsUtil.hpp"
25 #include "vkQueryUtil.hpp"
26 #include "vkTypeUtil.hpp"
27 #include "tcuTextureUtil.hpp"
28
29 #include <deMath.h>
30
31 using namespace vk;
32
33 namespace vkt
34 {
35 namespace sparse
36 {
37
getShaderGridSize(const ImageType imageType,const tcu::UVec3 & imageSize,const deUint32 mipLevel)38 tcu::UVec3 getShaderGridSize (const ImageType imageType, const tcu::UVec3& imageSize, const deUint32 mipLevel)
39 {
40 const deUint32 mipLevelX = std::max(imageSize.x() >> mipLevel, 1u);
41 const deUint32 mipLevelY = std::max(imageSize.y() >> mipLevel, 1u);
42 const deUint32 mipLevelZ = std::max(imageSize.z() >> mipLevel, 1u);
43
44 switch (imageType)
45 {
46 case IMAGE_TYPE_1D:
47 return tcu::UVec3(mipLevelX, 1u, 1u);
48
49 case IMAGE_TYPE_BUFFER:
50 return tcu::UVec3(imageSize.x(), 1u, 1u);
51
52 case IMAGE_TYPE_1D_ARRAY:
53 return tcu::UVec3(mipLevelX, imageSize.z(), 1u);
54
55 case IMAGE_TYPE_2D:
56 return tcu::UVec3(mipLevelX, mipLevelY, 1u);
57
58 case IMAGE_TYPE_2D_ARRAY:
59 return tcu::UVec3(mipLevelX, mipLevelY, imageSize.z());
60
61 case IMAGE_TYPE_3D:
62 return tcu::UVec3(mipLevelX, mipLevelY, mipLevelZ);
63
64 case IMAGE_TYPE_CUBE:
65 return tcu::UVec3(mipLevelX, mipLevelY, 6u);
66
67 case IMAGE_TYPE_CUBE_ARRAY:
68 return tcu::UVec3(mipLevelX, mipLevelY, 6u * imageSize.z());
69
70 default:
71 DE_FATAL("Unknown image type");
72 return tcu::UVec3(1u, 1u, 1u);
73 }
74 }
75
getLayerSize(const ImageType imageType,const tcu::UVec3 & imageSize)76 tcu::UVec3 getLayerSize (const ImageType imageType, const tcu::UVec3& imageSize)
77 {
78 switch (imageType)
79 {
80 case IMAGE_TYPE_1D:
81 case IMAGE_TYPE_1D_ARRAY:
82 case IMAGE_TYPE_BUFFER:
83 return tcu::UVec3(imageSize.x(), 1u, 1u);
84
85 case IMAGE_TYPE_2D:
86 case IMAGE_TYPE_2D_ARRAY:
87 case IMAGE_TYPE_CUBE:
88 case IMAGE_TYPE_CUBE_ARRAY:
89 return tcu::UVec3(imageSize.x(), imageSize.y(), 1u);
90
91 case IMAGE_TYPE_3D:
92 return tcu::UVec3(imageSize.x(), imageSize.y(), imageSize.z());
93
94 default:
95 DE_FATAL("Unknown image type");
96 return tcu::UVec3(1u, 1u, 1u);
97 }
98 }
99
getNumLayers(const ImageType imageType,const tcu::UVec3 & imageSize)100 deUint32 getNumLayers (const ImageType imageType, const tcu::UVec3& imageSize)
101 {
102 switch (imageType)
103 {
104 case IMAGE_TYPE_1D:
105 case IMAGE_TYPE_2D:
106 case IMAGE_TYPE_3D:
107 case IMAGE_TYPE_BUFFER:
108 return 1u;
109
110 case IMAGE_TYPE_1D_ARRAY:
111 case IMAGE_TYPE_2D_ARRAY:
112 return imageSize.z();
113
114 case IMAGE_TYPE_CUBE:
115 return 6u;
116
117 case IMAGE_TYPE_CUBE_ARRAY:
118 return imageSize.z() * 6u;
119
120 default:
121 DE_FATAL("Unknown image type");
122 return 0u;
123 }
124 }
125
getNumPixels(const ImageType imageType,const tcu::UVec3 & imageSize)126 deUint32 getNumPixels (const ImageType imageType, const tcu::UVec3& imageSize)
127 {
128 const tcu::UVec3 gridSize = getShaderGridSize(imageType, imageSize);
129
130 return gridSize.x() * gridSize.y() * gridSize.z();
131 }
132
getDimensions(const ImageType imageType)133 deUint32 getDimensions (const ImageType imageType)
134 {
135 switch (imageType)
136 {
137 case IMAGE_TYPE_1D:
138 case IMAGE_TYPE_BUFFER:
139 return 1u;
140
141 case IMAGE_TYPE_1D_ARRAY:
142 case IMAGE_TYPE_2D:
143 return 2u;
144
145 case IMAGE_TYPE_2D_ARRAY:
146 case IMAGE_TYPE_CUBE:
147 case IMAGE_TYPE_CUBE_ARRAY:
148 case IMAGE_TYPE_3D:
149 return 3u;
150
151 default:
152 DE_FATAL("Unknown image type");
153 return 0u;
154 }
155 }
156
getLayerDimensions(const ImageType imageType)157 deUint32 getLayerDimensions (const ImageType imageType)
158 {
159 switch (imageType)
160 {
161 case IMAGE_TYPE_1D:
162 case IMAGE_TYPE_BUFFER:
163 case IMAGE_TYPE_1D_ARRAY:
164 return 1u;
165
166 case IMAGE_TYPE_2D:
167 case IMAGE_TYPE_2D_ARRAY:
168 case IMAGE_TYPE_CUBE:
169 case IMAGE_TYPE_CUBE_ARRAY:
170 return 2u;
171
172 case IMAGE_TYPE_3D:
173 return 3u;
174
175 default:
176 DE_FATAL("Unknown image type");
177 return 0u;
178 }
179 }
180
isImageSizeSupported(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const ImageType imageType,const tcu::UVec3 & imageSize)181 bool isImageSizeSupported (const InstanceInterface& instance, const VkPhysicalDevice physicalDevice, const ImageType imageType, const tcu::UVec3& imageSize)
182 {
183 const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice);
184
185 switch (imageType)
186 {
187 case IMAGE_TYPE_1D:
188 return imageSize.x() <= deviceProperties.limits.maxImageDimension1D;
189 case IMAGE_TYPE_1D_ARRAY:
190 return imageSize.x() <= deviceProperties.limits.maxImageDimension1D &&
191 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
192 case IMAGE_TYPE_2D:
193 return imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
194 imageSize.y() <= deviceProperties.limits.maxImageDimension2D;
195 case IMAGE_TYPE_2D_ARRAY:
196 return imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
197 imageSize.y() <= deviceProperties.limits.maxImageDimension2D &&
198 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
199 case IMAGE_TYPE_CUBE:
200 return imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
201 imageSize.y() <= deviceProperties.limits.maxImageDimensionCube;
202 case IMAGE_TYPE_CUBE_ARRAY:
203 return imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
204 imageSize.y() <= deviceProperties.limits.maxImageDimensionCube &&
205 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
206 case IMAGE_TYPE_3D:
207 return imageSize.x() <= deviceProperties.limits.maxImageDimension3D &&
208 imageSize.y() <= deviceProperties.limits.maxImageDimension3D &&
209 imageSize.z() <= deviceProperties.limits.maxImageDimension3D;
210 case IMAGE_TYPE_BUFFER:
211 return true;
212 default:
213 DE_FATAL("Unknown image type");
214 return false;
215 }
216 }
217
makeBufferCreateInfo(const VkDeviceSize bufferSize,const VkBufferUsageFlags usage)218 VkBufferCreateInfo makeBufferCreateInfo (const VkDeviceSize bufferSize,
219 const VkBufferUsageFlags usage)
220 {
221 const VkBufferCreateInfo bufferCreateInfo =
222 {
223 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
224 DE_NULL, // const void* pNext;
225 0u, // VkBufferCreateFlags flags;
226 bufferSize, // VkDeviceSize size;
227 usage, // VkBufferUsageFlags usage;
228 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
229 0u, // deUint32 queueFamilyIndexCount;
230 DE_NULL, // const deUint32* pQueueFamilyIndices;
231 };
232 return bufferCreateInfo;
233 }
234
makeBufferImageCopy(const VkExtent3D extent,const deUint32 layerCount,const deUint32 mipmapLevel,const VkDeviceSize bufferOffset)235 VkBufferImageCopy makeBufferImageCopy (const VkExtent3D extent,
236 const deUint32 layerCount,
237 const deUint32 mipmapLevel,
238 const VkDeviceSize bufferOffset)
239 {
240 const VkBufferImageCopy copyParams =
241 {
242 bufferOffset, // VkDeviceSize bufferOffset;
243 0u, // deUint32 bufferRowLength;
244 0u, // deUint32 bufferImageHeight;
245 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, mipmapLevel, 0u, layerCount), // VkImageSubresourceLayers imageSubresource;
246 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
247 extent, // VkExtent3D imageExtent;
248 };
249 return copyParams;
250 }
251
makeCommandPool(const DeviceInterface & vk,const VkDevice device,const deUint32 queueFamilyIndex)252 Move<VkCommandPool> makeCommandPool (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
253 {
254 const VkCommandPoolCreateInfo commandPoolParams =
255 {
256 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType;
257 DE_NULL, // const void* pNext;
258 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags flags;
259 queueFamilyIndex, // deUint32 queueFamilyIndex;
260 };
261 return createCommandPool(vk, device, &commandPoolParams);
262 }
263
makeCommandBuffer(const DeviceInterface & vk,const VkDevice device,const VkCommandPool commandPool)264 Move<VkCommandBuffer> makeCommandBuffer (const DeviceInterface& vk, const VkDevice device, const VkCommandPool commandPool)
265 {
266 const VkCommandBufferAllocateInfo bufferAllocateParams =
267 {
268 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
269 DE_NULL, // const void* pNext;
270 commandPool, // VkCommandPool commandPool;
271 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
272 1u, // deUint32 bufferCount;
273 };
274 return allocateCommandBuffer(vk, device, &bufferAllocateParams);
275 }
276
makePipelineLayout(const DeviceInterface & vk,const VkDevice device,const VkDescriptorSetLayout descriptorSetLayout)277 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface& vk,
278 const VkDevice device,
279 const VkDescriptorSetLayout descriptorSetLayout)
280 {
281 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
282 {
283 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
284 DE_NULL, // const void* pNext;
285 0u, // VkPipelineLayoutCreateFlags flags;
286 (descriptorSetLayout != DE_NULL ? 1u : 0u), // deUint32 setLayoutCount;
287 (descriptorSetLayout != DE_NULL ? &descriptorSetLayout : DE_NULL), // const VkDescriptorSetLayout* pSetLayouts;
288 0u, // deUint32 pushConstantRangeCount;
289 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
290 };
291 return createPipelineLayout(vk, device, &pipelineLayoutParams);
292 }
293
makeComputePipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkShaderModule shaderModule,const VkSpecializationInfo * specializationInfo)294 Move<VkPipeline> makeComputePipeline (const DeviceInterface& vk,
295 const VkDevice device,
296 const VkPipelineLayout pipelineLayout,
297 const VkShaderModule shaderModule,
298 const VkSpecializationInfo* specializationInfo)
299 {
300 const VkPipelineShaderStageCreateInfo pipelineShaderStageParams =
301 {
302 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
303 DE_NULL, // const void* pNext;
304 0u, // VkPipelineShaderStageCreateFlags flags;
305 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
306 shaderModule, // VkShaderModule module;
307 "main", // const char* pName;
308 specializationInfo, // const VkSpecializationInfo* pSpecializationInfo;
309 };
310 const VkComputePipelineCreateInfo pipelineCreateInfo =
311 {
312 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
313 DE_NULL, // const void* pNext;
314 0u, // VkPipelineCreateFlags flags;
315 pipelineShaderStageParams, // VkPipelineShaderStageCreateInfo stage;
316 pipelineLayout, // VkPipelineLayout layout;
317 DE_NULL, // VkPipeline basePipelineHandle;
318 0, // deInt32 basePipelineIndex;
319 };
320 return createComputePipeline(vk, device, DE_NULL , &pipelineCreateInfo);
321 }
322
makeBufferView(const DeviceInterface & vk,const VkDevice vkDevice,const VkBuffer buffer,const VkFormat format,const VkDeviceSize offset,const VkDeviceSize size)323 Move<VkBufferView> makeBufferView (const DeviceInterface& vk,
324 const VkDevice vkDevice,
325 const VkBuffer buffer,
326 const VkFormat format,
327 const VkDeviceSize offset,
328 const VkDeviceSize size)
329 {
330 const VkBufferViewCreateInfo bufferViewParams =
331 {
332 VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, // VkStructureType sType;
333 DE_NULL, // const void* pNext;
334 0u, // VkBufferViewCreateFlags flags;
335 buffer, // VkBuffer buffer;
336 format, // VkFormat format;
337 offset, // VkDeviceSize offset;
338 size, // VkDeviceSize range;
339 };
340 return createBufferView(vk, vkDevice, &bufferViewParams);
341 }
342
makeImageView(const DeviceInterface & vk,const VkDevice vkDevice,const VkImage image,const VkImageViewType imageViewType,const VkFormat format,const VkImageSubresourceRange subresourceRange)343 Move<VkImageView> makeImageView (const DeviceInterface& vk,
344 const VkDevice vkDevice,
345 const VkImage image,
346 const VkImageViewType imageViewType,
347 const VkFormat format,
348 const VkImageSubresourceRange subresourceRange)
349 {
350 const VkImageViewCreateInfo imageViewParams =
351 {
352 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
353 DE_NULL, // const void* pNext;
354 0u, // VkImageViewCreateFlags flags;
355 image, // VkImage image;
356 imageViewType, // VkImageViewType viewType;
357 format, // VkFormat format;
358 makeComponentMappingRGBA(), // VkComponentMapping components;
359 subresourceRange, // VkImageSubresourceRange subresourceRange;
360 };
361 return createImageView(vk, vkDevice, &imageViewParams);
362 }
363
makeDescriptorSet(const DeviceInterface & vk,const VkDevice device,const VkDescriptorPool descriptorPool,const VkDescriptorSetLayout setLayout)364 Move<VkDescriptorSet> makeDescriptorSet (const DeviceInterface& vk,
365 const VkDevice device,
366 const VkDescriptorPool descriptorPool,
367 const VkDescriptorSetLayout setLayout)
368 {
369 const VkDescriptorSetAllocateInfo allocateParams =
370 {
371 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
372 DE_NULL, // const void* pNext;
373 descriptorPool, // VkDescriptorPool descriptorPool;
374 1u, // deUint32 setLayoutCount;
375 &setLayout, // const VkDescriptorSetLayout* pSetLayouts;
376 };
377 return allocateDescriptorSet(vk, device, &allocateParams);
378 }
379
makeSemaphore(const DeviceInterface & vk,const VkDevice device)380 Move<VkSemaphore> makeSemaphore (const DeviceInterface& vk, const VkDevice device)
381 {
382 const VkSemaphoreCreateInfo semaphoreCreateInfo =
383 {
384 VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
385 DE_NULL,
386 0u
387 };
388
389 return createSemaphore(vk, device, &semaphoreCreateInfo);
390 }
391
makeFence(const DeviceInterface & vk,const VkDevice device,const VkFenceCreateFlags flags)392 Move<VkFence> makeFence (const DeviceInterface& vk, const VkDevice device, const VkFenceCreateFlags flags)
393 {
394 const VkFenceCreateInfo fenceCreateInfo =
395 {
396 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
397 DE_NULL, // const void* pNext;
398 flags, // VkFenceCreateFlags flags;
399 };
400 return createFence(vk, device, &fenceCreateInfo);
401 }
402
makeFramebuffer(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass,const deUint32 attachmentCount,const VkImageView * pAttachments,const deUint32 width,const deUint32 height,const deUint32 layers)403 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk,
404 const VkDevice device,
405 const VkRenderPass renderPass,
406 const deUint32 attachmentCount,
407 const VkImageView* pAttachments,
408 const deUint32 width,
409 const deUint32 height,
410 const deUint32 layers)
411 {
412 const VkFramebufferCreateInfo framebufferInfo =
413 {
414 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
415 DE_NULL, // const void* pNext;
416 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
417 renderPass, // VkRenderPass renderPass;
418 attachmentCount, // uint32_t attachmentCount;
419 pAttachments, // const VkImageView* pAttachments;
420 width, // uint32_t width;
421 height, // uint32_t height;
422 layers, // uint32_t layers;
423 };
424
425 return createFramebuffer(vk, device, &framebufferInfo);
426 }
427
makeBufferMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkBuffer buffer,const VkDeviceSize offset,const VkDeviceSize bufferSizeBytes)428 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags srcAccessMask,
429 const VkAccessFlags dstAccessMask,
430 const VkBuffer buffer,
431 const VkDeviceSize offset,
432 const VkDeviceSize bufferSizeBytes)
433 {
434 const VkBufferMemoryBarrier barrier =
435 {
436 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
437 DE_NULL, // const void* pNext;
438 srcAccessMask, // VkAccessFlags srcAccessMask;
439 dstAccessMask, // VkAccessFlags dstAccessMask;
440 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
441 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
442 buffer, // VkBuffer buffer;
443 offset, // VkDeviceSize offset;
444 bufferSizeBytes, // VkDeviceSize size;
445 };
446 return barrier;
447 }
448
makeImageMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkImage image,const VkImageSubresourceRange subresourceRange)449 VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask,
450 const VkAccessFlags dstAccessMask,
451 const VkImageLayout oldLayout,
452 const VkImageLayout newLayout,
453 const VkImage image,
454 const VkImageSubresourceRange subresourceRange)
455 {
456 const VkImageMemoryBarrier barrier =
457 {
458 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
459 DE_NULL, // const void* pNext;
460 srcAccessMask, // VkAccessFlags outputMask;
461 dstAccessMask, // VkAccessFlags inputMask;
462 oldLayout, // VkImageLayout oldLayout;
463 newLayout, // VkImageLayout newLayout;
464 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
465 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
466 image, // VkImage image;
467 subresourceRange, // VkImageSubresourceRange subresourceRange;
468 };
469 return barrier;
470 }
471
makeImageMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const deUint32 srcQueueFamilyIndex,const deUint32 destQueueFamilyIndex,const VkImage image,const VkImageSubresourceRange subresourceRange)472 VkImageMemoryBarrier makeImageMemoryBarrier (const VkAccessFlags srcAccessMask,
473 const VkAccessFlags dstAccessMask,
474 const VkImageLayout oldLayout,
475 const VkImageLayout newLayout,
476 const deUint32 srcQueueFamilyIndex,
477 const deUint32 destQueueFamilyIndex,
478 const VkImage image,
479 const VkImageSubresourceRange subresourceRange)
480 {
481 const VkImageMemoryBarrier barrier =
482 {
483 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
484 DE_NULL, // const void* pNext;
485 srcAccessMask, // VkAccessFlags outputMask;
486 dstAccessMask, // VkAccessFlags inputMask;
487 oldLayout, // VkImageLayout oldLayout;
488 newLayout, // VkImageLayout newLayout;
489 srcQueueFamilyIndex, // deUint32 srcQueueFamilyIndex;
490 destQueueFamilyIndex, // deUint32 destQueueFamilyIndex;
491 image, // VkImage image;
492 subresourceRange, // VkImageSubresourceRange subresourceRange;
493 };
494 return barrier;
495 }
496
makeMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask)497 VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags srcAccessMask,
498 const VkAccessFlags dstAccessMask)
499 {
500 const VkMemoryBarrier barrier =
501 {
502 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
503 DE_NULL, // const void* pNext;
504 srcAccessMask, // VkAccessFlags outputMask;
505 dstAccessMask, // VkAccessFlags inputMask;
506 };
507 return barrier;
508 }
509
bindImage(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkImage image,const MemoryRequirement requirement)510 de::MovePtr<Allocation> bindImage (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkImage image, const MemoryRequirement requirement)
511 {
512 de::MovePtr<Allocation> alloc = allocator.allocate(getImageMemoryRequirements(vk, device, image), requirement);
513 VK_CHECK(vk.bindImageMemory(device, image, alloc->getMemory(), alloc->getOffset()));
514 return alloc;
515 }
516
bindBuffer(const DeviceInterface & vk,const VkDevice device,Allocator & allocator,const VkBuffer buffer,const MemoryRequirement requirement)517 de::MovePtr<Allocation> bindBuffer (const DeviceInterface& vk, const VkDevice device, Allocator& allocator, const VkBuffer buffer, const MemoryRequirement requirement)
518 {
519 de::MovePtr<Allocation> alloc(allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), requirement));
520 VK_CHECK(vk.bindBufferMemory(device, buffer, alloc->getMemory(), alloc->getOffset()));
521 return alloc;
522 }
523
beginCommandBuffer(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)524 void beginCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
525 {
526 const VkCommandBufferBeginInfo commandBufBeginParams =
527 {
528 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
529 DE_NULL, // const void* pNext;
530 0u, // VkCommandBufferUsageFlags flags;
531 (const VkCommandBufferInheritanceInfo*)DE_NULL,
532 };
533 VK_CHECK(vk.beginCommandBuffer(commandBuffer, &commandBufBeginParams));
534 }
535
endCommandBuffer(const DeviceInterface & vk,const VkCommandBuffer commandBuffer)536 void endCommandBuffer (const DeviceInterface& vk, const VkCommandBuffer commandBuffer)
537 {
538 VK_CHECK(vk.endCommandBuffer(commandBuffer));
539 }
540
submitCommands(const DeviceInterface & vk,const VkQueue queue,const VkCommandBuffer commandBuffer,const deUint32 waitSemaphoreCount,const VkSemaphore * pWaitSemaphores,const VkPipelineStageFlags * pWaitDstStageMask,const deUint32 signalSemaphoreCount,const VkSemaphore * pSignalSemaphores)541 void submitCommands (const DeviceInterface& vk,
542 const VkQueue queue,
543 const VkCommandBuffer commandBuffer,
544 const deUint32 waitSemaphoreCount,
545 const VkSemaphore* pWaitSemaphores,
546 const VkPipelineStageFlags* pWaitDstStageMask,
547 const deUint32 signalSemaphoreCount,
548 const VkSemaphore* pSignalSemaphores)
549 {
550 const VkSubmitInfo submitInfo =
551 {
552 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
553 DE_NULL, // const void* pNext;
554 waitSemaphoreCount, // deUint32 waitSemaphoreCount;
555 pWaitSemaphores, // const VkSemaphore* pWaitSemaphores;
556 pWaitDstStageMask, // const VkPipelineStageFlags* pWaitDstStageMask;
557 1u, // deUint32 commandBufferCount;
558 &commandBuffer, // const VkCommandBuffer* pCommandBuffers;
559 signalSemaphoreCount, // deUint32 signalSemaphoreCount;
560 pSignalSemaphores, // const VkSemaphore* pSignalSemaphores;
561 };
562
563 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, DE_NULL));
564 }
565
submitCommandsAndWait(const DeviceInterface & vk,const VkDevice device,const VkQueue queue,const VkCommandBuffer commandBuffer,const deUint32 waitSemaphoreCount,const VkSemaphore * pWaitSemaphores,const VkPipelineStageFlags * pWaitDstStageMask,const deUint32 signalSemaphoreCount,const VkSemaphore * pSignalSemaphores)566 void submitCommandsAndWait (const DeviceInterface& vk,
567 const VkDevice device,
568 const VkQueue queue,
569 const VkCommandBuffer commandBuffer,
570 const deUint32 waitSemaphoreCount,
571 const VkSemaphore* pWaitSemaphores,
572 const VkPipelineStageFlags* pWaitDstStageMask,
573 const deUint32 signalSemaphoreCount,
574 const VkSemaphore* pSignalSemaphores)
575 {
576 const VkFenceCreateInfo fenceParams =
577 {
578 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
579 DE_NULL, // const void* pNext;
580 0u, // VkFenceCreateFlags flags;
581 };
582 const Unique<VkFence> fence(createFence(vk, device, &fenceParams));
583
584 const VkSubmitInfo submitInfo =
585 {
586 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
587 DE_NULL, // const void* pNext;
588 waitSemaphoreCount, // deUint32 waitSemaphoreCount;
589 pWaitSemaphores, // const VkSemaphore* pWaitSemaphores;
590 pWaitDstStageMask, // const VkPipelineStageFlags* pWaitDstStageMask;
591 1u, // deUint32 commandBufferCount;
592 &commandBuffer, // const VkCommandBuffer* pCommandBuffers;
593 signalSemaphoreCount, // deUint32 signalSemaphoreCount;
594 pSignalSemaphores, // const VkSemaphore* pSignalSemaphores;
595 };
596
597 VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
598 VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
599 }
600
mapImageType(const ImageType imageType)601 VkImageType mapImageType (const ImageType imageType)
602 {
603 switch (imageType)
604 {
605 case IMAGE_TYPE_1D:
606 case IMAGE_TYPE_1D_ARRAY:
607 case IMAGE_TYPE_BUFFER:
608 return VK_IMAGE_TYPE_1D;
609
610 case IMAGE_TYPE_2D:
611 case IMAGE_TYPE_2D_ARRAY:
612 case IMAGE_TYPE_CUBE:
613 case IMAGE_TYPE_CUBE_ARRAY:
614 return VK_IMAGE_TYPE_2D;
615
616 case IMAGE_TYPE_3D:
617 return VK_IMAGE_TYPE_3D;
618
619 default:
620 DE_ASSERT(false);
621 return VK_IMAGE_TYPE_LAST;
622 }
623 }
624
mapImageViewType(const ImageType imageType)625 VkImageViewType mapImageViewType (const ImageType imageType)
626 {
627 switch (imageType)
628 {
629 case IMAGE_TYPE_1D: return VK_IMAGE_VIEW_TYPE_1D;
630 case IMAGE_TYPE_1D_ARRAY: return VK_IMAGE_VIEW_TYPE_1D_ARRAY;
631 case IMAGE_TYPE_2D: return VK_IMAGE_VIEW_TYPE_2D;
632 case IMAGE_TYPE_2D_ARRAY: return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
633 case IMAGE_TYPE_3D: return VK_IMAGE_VIEW_TYPE_3D;
634 case IMAGE_TYPE_CUBE: return VK_IMAGE_VIEW_TYPE_CUBE;
635 case IMAGE_TYPE_CUBE_ARRAY: return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
636
637 default:
638 DE_ASSERT(false);
639 return VK_IMAGE_VIEW_TYPE_LAST;
640 }
641 }
642
getImageTypeName(const ImageType imageType)643 std::string getImageTypeName (const ImageType imageType)
644 {
645 switch (imageType)
646 {
647 case IMAGE_TYPE_1D: return "1d";
648 case IMAGE_TYPE_1D_ARRAY: return "1d_array";
649 case IMAGE_TYPE_2D: return "2d";
650 case IMAGE_TYPE_2D_ARRAY: return "2d_array";
651 case IMAGE_TYPE_3D: return "3d";
652 case IMAGE_TYPE_CUBE: return "cube";
653 case IMAGE_TYPE_CUBE_ARRAY: return "cube_array";
654 case IMAGE_TYPE_BUFFER: return "buffer";
655
656 default:
657 DE_ASSERT(false);
658 return "";
659 }
660 }
661
getShaderImageType(const tcu::TextureFormat & format,const ImageType imageType)662 std::string getShaderImageType (const tcu::TextureFormat& format, const ImageType imageType)
663 {
664 std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
665 tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? "i" : "";
666
667 std::string imageTypePart;
668 switch (imageType)
669 {
670 case IMAGE_TYPE_1D: imageTypePart = "1D"; break;
671 case IMAGE_TYPE_1D_ARRAY: imageTypePart = "1DArray"; break;
672 case IMAGE_TYPE_2D: imageTypePart = "2D"; break;
673 case IMAGE_TYPE_2D_ARRAY: imageTypePart = "2DArray"; break;
674 case IMAGE_TYPE_3D: imageTypePart = "3D"; break;
675 case IMAGE_TYPE_CUBE: imageTypePart = "Cube"; break;
676 case IMAGE_TYPE_CUBE_ARRAY: imageTypePart = "CubeArray"; break;
677 case IMAGE_TYPE_BUFFER: imageTypePart = "Buffer"; break;
678
679 default:
680 DE_ASSERT(false);
681 }
682
683 return formatPart + "image" + imageTypePart;
684 }
685
686
getShaderImageDataType(const tcu::TextureFormat & format)687 std::string getShaderImageDataType(const tcu::TextureFormat& format)
688 {
689 switch (tcu::getTextureChannelClass(format.type))
690 {
691 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
692 return "uvec4";
693 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
694 return "ivec4";
695 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
696 return "vec4";
697 default:
698 DE_ASSERT(false);
699 return "";
700 }
701 }
702
703
getShaderImageFormatQualifier(const tcu::TextureFormat & format)704 std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
705 {
706 const char* orderPart;
707 const char* typePart;
708
709 switch (format.order)
710 {
711 case tcu::TextureFormat::R: orderPart = "r"; break;
712 case tcu::TextureFormat::RG: orderPart = "rg"; break;
713 case tcu::TextureFormat::RGB: orderPart = "rgb"; break;
714 case tcu::TextureFormat::RGBA: orderPart = "rgba"; break;
715
716 default:
717 DE_ASSERT(false);
718 orderPart = DE_NULL;
719 }
720
721 switch (format.type)
722 {
723 case tcu::TextureFormat::FLOAT: typePart = "32f"; break;
724 case tcu::TextureFormat::HALF_FLOAT: typePart = "16f"; break;
725
726 case tcu::TextureFormat::UNSIGNED_INT32: typePart = "32ui"; break;
727 case tcu::TextureFormat::UNSIGNED_INT16: typePart = "16ui"; break;
728 case tcu::TextureFormat::UNSIGNED_INT8: typePart = "8ui"; break;
729
730 case tcu::TextureFormat::SIGNED_INT32: typePart = "32i"; break;
731 case tcu::TextureFormat::SIGNED_INT16: typePart = "16i"; break;
732 case tcu::TextureFormat::SIGNED_INT8: typePart = "8i"; break;
733
734 case tcu::TextureFormat::UNORM_INT16: typePart = "16"; break;
735 case tcu::TextureFormat::UNORM_INT8: typePart = "8"; break;
736
737 case tcu::TextureFormat::SNORM_INT16: typePart = "16_snorm"; break;
738 case tcu::TextureFormat::SNORM_INT8: typePart = "8_snorm"; break;
739
740 default:
741 DE_ASSERT(false);
742 typePart = DE_NULL;
743 }
744
745 return std::string() + orderPart + typePart;
746 }
747
getShaderImageCoordinates(const ImageType imageType,const std::string & x,const std::string & xy,const std::string & xyz)748 std::string getShaderImageCoordinates (const ImageType imageType,
749 const std::string& x,
750 const std::string& xy,
751 const std::string& xyz)
752 {
753 switch (imageType)
754 {
755 case IMAGE_TYPE_1D:
756 case IMAGE_TYPE_BUFFER:
757 return x;
758
759 case IMAGE_TYPE_1D_ARRAY:
760 case IMAGE_TYPE_2D:
761 return xy;
762
763 case IMAGE_TYPE_2D_ARRAY:
764 case IMAGE_TYPE_3D:
765 case IMAGE_TYPE_CUBE:
766 case IMAGE_TYPE_CUBE_ARRAY:
767 return xyz;
768
769 default:
770 DE_ASSERT(0);
771 return "";
772 }
773 }
774
mipLevelExtents(const VkExtent3D & baseExtents,const deUint32 mipLevel)775 VkExtent3D mipLevelExtents (const VkExtent3D& baseExtents, const deUint32 mipLevel)
776 {
777 VkExtent3D result;
778
779 result.width = std::max(baseExtents.width >> mipLevel, 1u);
780 result.height = std::max(baseExtents.height >> mipLevel, 1u);
781 result.depth = std::max(baseExtents.depth >> mipLevel, 1u);
782
783 return result;
784 }
785
getImageMaxMipLevels(const VkImageFormatProperties & imageFormatProperties,const VkExtent3D & extent)786 deUint32 getImageMaxMipLevels (const VkImageFormatProperties& imageFormatProperties, const VkExtent3D& extent)
787 {
788 const deUint32 widestEdge = std::max(std::max(extent.width, extent.height), extent.depth);
789
790 return std::min(static_cast<deUint32>(deFloatLog2(static_cast<float>(widestEdge))) + 1u, imageFormatProperties.maxMipLevels);
791 }
792
getImageMipLevelSizeInBytes(const VkExtent3D & baseExtents,const deUint32 layersCount,const tcu::TextureFormat & format,const deUint32 mipmapLevel,const deUint32 mipmapMemoryAlignment)793 deUint32 getImageMipLevelSizeInBytes(const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevel, const deUint32 mipmapMemoryAlignment)
794 {
795 const VkExtent3D extents = mipLevelExtents(baseExtents, mipmapLevel);
796
797 return deAlign32(extents.width * extents.height * extents.depth * layersCount * tcu::getPixelSize(format), mipmapMemoryAlignment);
798 }
799
getImageSizeInBytes(const VkExtent3D & baseExtents,const deUint32 layersCount,const tcu::TextureFormat & format,const deUint32 mipmapLevelsCount,const deUint32 mipmapMemoryAlignment)800 deUint32 getImageSizeInBytes(const VkExtent3D& baseExtents, const deUint32 layersCount, const tcu::TextureFormat& format, const deUint32 mipmapLevelsCount, const deUint32 mipmapMemoryAlignment)
801 {
802 deUint32 imageSizeInBytes = 0;
803 for (deUint32 mipmapLevel = 0; mipmapLevel < mipmapLevelsCount; ++mipmapLevel)
804 imageSizeInBytes += getImageMipLevelSizeInBytes(baseExtents, layersCount, format, mipmapLevel, mipmapMemoryAlignment);
805
806 return imageSizeInBytes;
807 }
808
makeSparseImageMemoryBind(const DeviceInterface & vk,const VkDevice device,const VkDeviceSize allocationSize,const deUint32 memoryType,const VkImageSubresource & subresource,const VkOffset3D & offset,const VkExtent3D & extent)809 VkSparseImageMemoryBind makeSparseImageMemoryBind (const DeviceInterface& vk,
810 const VkDevice device,
811 const VkDeviceSize allocationSize,
812 const deUint32 memoryType,
813 const VkImageSubresource& subresource,
814 const VkOffset3D& offset,
815 const VkExtent3D& extent)
816 {
817 const VkMemoryAllocateInfo allocInfo =
818 {
819 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
820 DE_NULL, // const void* pNext;
821 allocationSize, // VkDeviceSize allocationSize;
822 memoryType, // deUint32 memoryTypeIndex;
823 };
824
825 VkDeviceMemory deviceMemory = 0;
826 VK_CHECK(vk.allocateMemory(device, &allocInfo, DE_NULL, &deviceMemory));
827
828 VkSparseImageMemoryBind imageMemoryBind;
829
830 imageMemoryBind.subresource = subresource;
831 imageMemoryBind.memory = deviceMemory;
832 imageMemoryBind.memoryOffset = 0u;
833 imageMemoryBind.flags = 0u;
834 imageMemoryBind.offset = offset;
835 imageMemoryBind.extent = extent;
836
837 return imageMemoryBind;
838 }
839
makeSparseMemoryBind(const DeviceInterface & vk,const VkDevice device,const VkDeviceSize allocationSize,const deUint32 memoryType,const VkDeviceSize resourceOffset)840 VkSparseMemoryBind makeSparseMemoryBind (const DeviceInterface& vk,
841 const VkDevice device,
842 const VkDeviceSize allocationSize,
843 const deUint32 memoryType,
844 const VkDeviceSize resourceOffset)
845 {
846 const VkMemoryAllocateInfo allocInfo =
847 {
848 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
849 DE_NULL, // const void* pNext;
850 allocationSize, // VkDeviceSize allocationSize;
851 memoryType, // deUint32 memoryTypeIndex;
852 };
853
854 VkDeviceMemory deviceMemory = 0;
855 VK_CHECK(vk.allocateMemory(device, &allocInfo, DE_NULL, &deviceMemory));
856
857 VkSparseMemoryBind memoryBind;
858
859 memoryBind.resourceOffset = resourceOffset;
860 memoryBind.size = allocationSize;
861 memoryBind.memory = deviceMemory;
862 memoryBind.memoryOffset = 0u;
863 memoryBind.flags = 0u;
864
865 return memoryBind;
866 }
867
requireFeatures(const InstanceInterface & vki,const VkPhysicalDevice physDevice,const FeatureFlags flags)868 void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
869 {
870 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
871
872 if (((flags & FEATURE_TESSELLATION_SHADER) != 0) && !features.tessellationShader)
873 throw tcu::NotSupportedError("Tessellation shader not supported");
874
875 if (((flags & FEATURE_GEOMETRY_SHADER) != 0) && !features.geometryShader)
876 throw tcu::NotSupportedError("Geometry shader not supported");
877
878 if (((flags & FEATURE_SHADER_FLOAT_64) != 0) && !features.shaderFloat64)
879 throw tcu::NotSupportedError("Double-precision floats not supported");
880
881 if (((flags & FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS) != 0) && !features.vertexPipelineStoresAndAtomics)
882 throw tcu::NotSupportedError("SSBO and image writes not supported in vertex pipeline");
883
884 if (((flags & FEATURE_FRAGMENT_STORES_AND_ATOMICS) != 0) && !features.fragmentStoresAndAtomics)
885 throw tcu::NotSupportedError("SSBO and image writes not supported in fragment shader");
886
887 if (((flags & FEATURE_SHADER_TESSELLATION_AND_GEOMETRY_POINT_SIZE) != 0) && !features.shaderTessellationAndGeometryPointSize)
888 throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
889 }
890
findMatchingMemoryType(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const VkMemoryRequirements & objectMemoryRequirements,const MemoryRequirement & memoryRequirement)891 deUint32 findMatchingMemoryType (const InstanceInterface& instance,
892 const VkPhysicalDevice physicalDevice,
893 const VkMemoryRequirements& objectMemoryRequirements,
894 const MemoryRequirement& memoryRequirement)
895 {
896 const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice);
897
898 for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemoryProperties.memoryTypeCount; ++memoryTypeNdx)
899 {
900 if ((objectMemoryRequirements.memoryTypeBits & (1u << memoryTypeNdx)) != 0 &&
901 memoryRequirement.matchesHeap(deviceMemoryProperties.memoryTypes[memoryTypeNdx].propertyFlags))
902 {
903 return memoryTypeNdx;
904 }
905 }
906
907 return NO_MATCH_FOUND;
908 }
909
checkSparseSupportForImageType(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const ImageType imageType)910 bool checkSparseSupportForImageType (const InstanceInterface& instance,
911 const VkPhysicalDevice physicalDevice,
912 const ImageType imageType)
913 {
914 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instance, physicalDevice);
915
916 if (!deviceFeatures.sparseBinding)
917 return false;
918
919 switch (mapImageType(imageType))
920 {
921 case VK_IMAGE_TYPE_2D:
922 return deviceFeatures.sparseResidencyImage2D == VK_TRUE;
923 case VK_IMAGE_TYPE_3D:
924 return deviceFeatures.sparseResidencyImage3D == VK_TRUE;
925 default:
926 DE_ASSERT(0);
927 return false;
928 };
929 }
930
checkSparseSupportForImageFormat(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const VkImageCreateInfo & imageInfo)931 bool checkSparseSupportForImageFormat (const InstanceInterface& instance,
932 const VkPhysicalDevice physicalDevice,
933 const VkImageCreateInfo& imageInfo)
934 {
935 const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec = getPhysicalDeviceSparseImageFormatProperties(
936 instance, physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.samples, imageInfo.usage, imageInfo.tiling);
937
938 return sparseImageFormatPropVec.size() > 0u;
939 }
940
checkImageFormatFeatureSupport(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const VkFormat format,const VkFormatFeatureFlags featureFlags)941 bool checkImageFormatFeatureSupport (const InstanceInterface& instance,
942 const VkPhysicalDevice physicalDevice,
943 const VkFormat format,
944 const VkFormatFeatureFlags featureFlags)
945 {
946 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format);
947
948 return (formatProperties.optimalTilingFeatures & featureFlags) == featureFlags;
949 }
950
getSparseAspectRequirementsIndex(const std::vector<VkSparseImageMemoryRequirements> & requirements,const VkImageAspectFlags aspectFlags)951 deUint32 getSparseAspectRequirementsIndex (const std::vector<VkSparseImageMemoryRequirements>& requirements,
952 const VkImageAspectFlags aspectFlags)
953 {
954 for (deUint32 memoryReqNdx = 0; memoryReqNdx < requirements.size(); ++memoryReqNdx)
955 {
956 if (requirements[memoryReqNdx].formatProperties.aspectMask & aspectFlags)
957 return memoryReqNdx;
958 }
959
960 return NO_MATCH_FOUND;
961 }
962
963 } // sparse
964 } // vkt
965