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