1 // Copyright 2018 The Amber Authors.
2 // Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 #include "src/vulkan/device.h"
17
18 #include <algorithm>
19 #include <cstring>
20 #include <iomanip> // Vulkan wrappers: std::setw(), std::left/right
21 #include <iostream>
22 #include <memory>
23 #include <set>
24 #include <sstream>
25 #include <string>
26 #include <vector>
27
28 #include "src/make_unique.h"
29
30 namespace amber {
31 namespace vulkan {
32 namespace {
33
34 const char kVariablePointers[] = "VariablePointerFeatures.variablePointers";
35 const char kVariablePointersStorageBuffer[] =
36 "VariablePointerFeatures.variablePointersStorageBuffer";
37 const char kFloat16Int8_Float16[] = "Float16Int8Features.shaderFloat16";
38 const char kFloat16Int8_Int8[] = "Float16Int8Features.shaderInt8";
39 const char k8BitStorage_Storage[] =
40 "Storage8BitFeatures.storageBuffer8BitAccess";
41 const char k8BitStorage_UniformAndStorage[] =
42 "Storage8BitFeatures.uniformAndStorageBuffer8BitAccess";
43 const char k8BitStorage_PushConstant[] =
44 "Storage8BitFeatures.storagePushConstant8";
45 const char k16BitStorage_Storage[] =
46 "Storage16BitFeatures.storageBuffer16BitAccess";
47 const char k16BitStorage_UniformAndStorage[] =
48 "Storage16BitFeatures.uniformAndStorageBuffer16BitAccess";
49 const char k16BitStorage_PushConstant[] =
50 "Storage16BitFeatures.storagePushConstant16";
51 const char k16BitStorage_InputOutput[] =
52 "Storage16BitFeatures.storageInputOutput16";
53
54 const char kSubgroupSizeControl[] = "SubgroupSizeControl.subgroupSizeControl";
55 const char kComputeFullSubgroups[] = "SubgroupSizeControl.computeFullSubgroups";
56
57 const char kSubgroupSupportedOperations[] = "SubgroupSupportedOperations";
58 const char kSubgroupSupportedOperationsBasic[] =
59 "SubgroupSupportedOperations.basic";
60 const char kSubgroupSupportedOperationsVote[] =
61 "SubgroupSupportedOperations.vote";
62 const char kSubgroupSupportedOperationsArithmetic[] =
63 "SubgroupSupportedOperations.arithmetic";
64 const char kSubgroupSupportedOperationsBallot[] =
65 "SubgroupSupportedOperations.ballot";
66 const char kSubgroupSupportedOperationsShuffle[] =
67 "SubgroupSupportedOperations.shuffle";
68 const char kSubgroupSupportedOperationsShuffleRelative[] =
69 "SubgroupSupportedOperations.shuffleRelative";
70 const char kSubgroupSupportedOperationsClustered[] =
71 "SubgroupSupportedOperations.clustered";
72 const char kSubgroupSupportedOperationsQuad[] =
73 "SubgroupSupportedOperations.quad";
74 const char kSubgroupSupportedStages[] = "SubgroupSupportedStages";
75 const char kSubgroupSupportedStagesVertex[] = "SubgroupSupportedStages.vertex";
76 const char kSubgroupSupportedStagesTessellationControl[] =
77 "SubgroupSupportedStages.tessellationControl";
78 const char kSubgroupSupportedStagesTessellationEvaluation[] =
79 "SubgroupSupportedStages.tessellationEvaluation";
80 const char kSubgroupSupportedStagesGeometry[] =
81 "SubgroupSupportedStages.geometry";
82 const char kSubgroupSupportedStagesFragment[] =
83 "SubgroupSupportedStages.fragment";
84 const char kSubgroupSupportedStagesCompute[] =
85 "SubgroupSupportedStages.compute";
86
87 const char kShaderSubgroupExtendedTypes[] =
88 "ShaderSubgroupExtendedTypesFeatures.shaderSubgroupExtendedTypes";
89
90 const char kIndexTypeUint8[] = "IndexTypeUint8Features.indexTypeUint8";
91
92 const char kAccelerationStructure[] =
93 "AccelerationStructureFeaturesKHR.accelerationStructure";
94 const char kBufferDeviceAddress[] =
95 "BufferDeviceAddressFeatures.bufferDeviceAddress";
96 const char kRayTracingPipeline[] =
97 "RayTracingPipelineFeaturesKHR.rayTracingPipeline";
98
99 struct BaseOutStructure {
100 VkStructureType sType;
101 void* pNext;
102 };
103
AreAllRequiredFeaturesSupported(const VkPhysicalDeviceFeatures & available_features,const std::vector<std::string> & required_features)104 bool AreAllRequiredFeaturesSupported(
105 const VkPhysicalDeviceFeatures& available_features,
106 const std::vector<std::string>& required_features) {
107 if (required_features.empty())
108 return true;
109
110 for (const auto& feature : required_features) {
111 if (feature == "robustBufferAccess") {
112 if (available_features.robustBufferAccess == VK_FALSE)
113 return false;
114 continue;
115 }
116 if (feature == "fullDrawIndexUint32") {
117 if (available_features.fullDrawIndexUint32 == VK_FALSE)
118 return false;
119 continue;
120 }
121 if (feature == "imageCubeArray") {
122 if (available_features.imageCubeArray == VK_FALSE)
123 return false;
124 continue;
125 }
126 if (feature == "independentBlend") {
127 if (available_features.independentBlend == VK_FALSE)
128 return false;
129 continue;
130 }
131 if (feature == "geometryShader") {
132 if (available_features.geometryShader == VK_FALSE)
133 return false;
134 continue;
135 }
136 if (feature == "tessellationShader") {
137 if (available_features.tessellationShader == VK_FALSE)
138 return false;
139 continue;
140 }
141 if (feature == "sampleRateShading") {
142 if (available_features.sampleRateShading == VK_FALSE)
143 return false;
144 continue;
145 }
146 if (feature == "dualSrcBlend") {
147 if (available_features.dualSrcBlend == VK_FALSE)
148 return false;
149 continue;
150 }
151 if (feature == "logicOp") {
152 if (available_features.logicOp == VK_FALSE)
153 return false;
154 continue;
155 }
156 if (feature == "multiDrawIndirect") {
157 if (available_features.multiDrawIndirect == VK_FALSE)
158 return false;
159 continue;
160 }
161 if (feature == "drawIndirectFirstInstance") {
162 if (available_features.drawIndirectFirstInstance == VK_FALSE)
163 return false;
164 continue;
165 }
166 if (feature == "depthClamp") {
167 if (available_features.depthClamp == VK_FALSE)
168 return false;
169 continue;
170 }
171 if (feature == "depthBiasClamp") {
172 if (available_features.depthBiasClamp == VK_FALSE)
173 return false;
174 continue;
175 }
176 if (feature == "fillModeNonSolid") {
177 if (available_features.fillModeNonSolid == VK_FALSE)
178 return false;
179 continue;
180 }
181 if (feature == "depthBounds") {
182 if (available_features.depthBounds == VK_FALSE)
183 return false;
184 continue;
185 }
186 if (feature == "wideLines") {
187 if (available_features.wideLines == VK_FALSE)
188 return false;
189 continue;
190 }
191 if (feature == "largePoints") {
192 if (available_features.largePoints == VK_FALSE)
193 return false;
194 continue;
195 }
196 if (feature == "alphaToOne") {
197 if (available_features.alphaToOne == VK_FALSE)
198 return false;
199 continue;
200 }
201 if (feature == "multiViewport") {
202 if (available_features.multiViewport == VK_FALSE)
203 return false;
204 continue;
205 }
206 if (feature == "samplerAnisotropy") {
207 if (available_features.samplerAnisotropy == VK_FALSE)
208 return false;
209 continue;
210 }
211 if (feature == "textureCompressionETC2") {
212 if (available_features.textureCompressionETC2 == VK_FALSE)
213 return false;
214 continue;
215 }
216 if (feature == "textureCompressionASTC_LDR") {
217 if (available_features.textureCompressionASTC_LDR == VK_FALSE)
218 return false;
219 continue;
220 }
221 if (feature == "textureCompressionBC") {
222 if (available_features.textureCompressionBC == VK_FALSE)
223 return false;
224 continue;
225 }
226 if (feature == "occlusionQueryPrecise") {
227 if (available_features.occlusionQueryPrecise == VK_FALSE)
228 return false;
229 continue;
230 }
231 if (feature == "pipelineStatisticsQuery") {
232 if (available_features.pipelineStatisticsQuery == VK_FALSE)
233 return false;
234 continue;
235 }
236 if (feature == "vertexPipelineStoresAndAtomics") {
237 if (available_features.vertexPipelineStoresAndAtomics == VK_FALSE)
238 return false;
239 continue;
240 }
241 if (feature == "fragmentStoresAndAtomics") {
242 if (available_features.fragmentStoresAndAtomics == VK_FALSE)
243 return false;
244 continue;
245 }
246 if (feature == "shaderTessellationAndGeometryPointSize") {
247 if (available_features.shaderTessellationAndGeometryPointSize == VK_FALSE)
248 return false;
249 continue;
250 }
251 if (feature == "shaderImageGatherExtended") {
252 if (available_features.shaderImageGatherExtended == VK_FALSE)
253 return false;
254 continue;
255 }
256 if (feature == "shaderStorageImageExtendedFormats") {
257 if (available_features.shaderStorageImageExtendedFormats == VK_FALSE)
258 return false;
259 continue;
260 }
261 if (feature == "shaderStorageImageMultisample") {
262 if (available_features.shaderStorageImageMultisample == VK_FALSE)
263 return false;
264 continue;
265 }
266 if (feature == "shaderStorageImageReadWithoutFormat") {
267 if (available_features.shaderStorageImageReadWithoutFormat == VK_FALSE)
268 return false;
269 continue;
270 }
271 if (feature == "shaderStorageImageWriteWithoutFormat") {
272 if (available_features.shaderStorageImageWriteWithoutFormat == VK_FALSE)
273 return false;
274 continue;
275 }
276 if (feature == "shaderUniformBufferArrayDynamicIndexing") {
277 if (available_features.shaderUniformBufferArrayDynamicIndexing ==
278 VK_FALSE)
279 return false;
280 continue;
281 }
282 if (feature == "shaderSampledImageArrayDynamicIndexing") {
283 if (available_features.shaderSampledImageArrayDynamicIndexing == VK_FALSE)
284 return false;
285 continue;
286 }
287 if (feature == "shaderStorageBufferArrayDynamicIndexing") {
288 if (available_features.shaderStorageBufferArrayDynamicIndexing ==
289 VK_FALSE)
290 return false;
291 continue;
292 }
293 if (feature == "shaderStorageImageArrayDynamicIndexing") {
294 if (available_features.shaderStorageImageArrayDynamicIndexing == VK_FALSE)
295 return false;
296 continue;
297 }
298 if (feature == "shaderClipDistance") {
299 if (available_features.shaderClipDistance == VK_FALSE)
300 return false;
301 continue;
302 }
303 if (feature == "shaderCullDistance") {
304 if (available_features.shaderCullDistance == VK_FALSE)
305 return false;
306 continue;
307 }
308 if (feature == "shaderFloat64") {
309 if (available_features.shaderFloat64 == VK_FALSE)
310 return false;
311 continue;
312 }
313 if (feature == "shaderInt64") {
314 if (available_features.shaderInt64 == VK_FALSE)
315 return false;
316 continue;
317 }
318 if (feature == "shaderInt16") {
319 if (available_features.shaderInt16 == VK_FALSE)
320 return false;
321 continue;
322 }
323 if (feature == "shaderResourceResidency") {
324 if (available_features.shaderResourceResidency == VK_FALSE)
325 return false;
326 continue;
327 }
328 if (feature == "shaderResourceMinLod") {
329 if (available_features.shaderResourceMinLod == VK_FALSE)
330 return false;
331 continue;
332 }
333 if (feature == "sparseBinding") {
334 if (available_features.sparseBinding == VK_FALSE)
335 return false;
336 continue;
337 }
338 if (feature == "sparseResidencyBuffer") {
339 if (available_features.sparseResidencyBuffer == VK_FALSE)
340 return false;
341 continue;
342 }
343 if (feature == "sparseResidencyImage2D") {
344 if (available_features.sparseResidencyImage2D == VK_FALSE)
345 return false;
346 continue;
347 }
348 if (feature == "sparseResidencyImage3D") {
349 if (available_features.sparseResidencyImage3D == VK_FALSE)
350 return false;
351 continue;
352 }
353 if (feature == "sparseResidency2Samples") {
354 if (available_features.sparseResidency2Samples == VK_FALSE)
355 return false;
356 continue;
357 }
358 if (feature == "sparseResidency4Samples") {
359 if (available_features.sparseResidency4Samples == VK_FALSE)
360 return false;
361 continue;
362 }
363 if (feature == "sparseResidency8Samples") {
364 if (available_features.sparseResidency8Samples == VK_FALSE)
365 return false;
366 continue;
367 }
368 if (feature == "sparseResidency16Samples") {
369 if (available_features.sparseResidency16Samples == VK_FALSE)
370 return false;
371 continue;
372 }
373 if (feature == "sparseResidencyAliased") {
374 if (available_features.sparseResidencyAliased == VK_FALSE)
375 return false;
376 continue;
377 }
378 if (feature == "variableMultisampleRate") {
379 if (available_features.variableMultisampleRate == VK_FALSE)
380 return false;
381 continue;
382 }
383 if (feature == "inheritedQueries") {
384 if (available_features.inheritedQueries == VK_FALSE)
385 return false;
386 continue;
387 }
388 }
389
390 return true;
391 }
392
AreAllExtensionsSupported(const std::vector<std::string> & available_extensions,const std::vector<std::string> & required_extensions)393 bool AreAllExtensionsSupported(
394 const std::vector<std::string>& available_extensions,
395 const std::vector<std::string>& required_extensions) {
396 if (required_extensions.empty())
397 return true;
398
399 std::set<std::string> required_extension_set(required_extensions.begin(),
400 required_extensions.end());
401 for (const auto& extension : available_extensions) {
402 required_extension_set.erase(extension);
403 }
404
405 return required_extension_set.empty();
406 }
407
408 } // namespace
409
Device(VkInstance instance,VkPhysicalDevice physical_device,uint32_t queue_family_index,VkDevice device,VkQueue queue,Delegate * delegate)410 Device::Device(VkInstance instance,
411 VkPhysicalDevice physical_device,
412 uint32_t queue_family_index,
413 VkDevice device,
414 VkQueue queue,
415 Delegate* delegate)
416 : instance_(instance),
417 physical_device_(physical_device),
418 device_(device),
419 queue_(queue),
420 queue_family_index_(queue_family_index),
421 delegate_(delegate) {}
422
423 Device::~Device() = default;
424
LoadVulkanPointers(PFN_vkGetInstanceProcAddr getInstanceProcAddr,Delegate * delegate)425 Result Device::LoadVulkanPointers(PFN_vkGetInstanceProcAddr getInstanceProcAddr,
426 Delegate* delegate) {
427 // Note: logging Vulkan calls is done via the delegate rather than a Vulkan
428 // layer because we want such logging even when Amber is built as a native
429 // executable on Android, where Vulkan layers are usable only with APKs.
430 if (delegate && delegate->LogGraphicsCalls())
431 delegate->Log("Loading Vulkan Pointers");
432
433 #include "vk-wrappers-1-0.inc"
434
435 ptrs_.vkGetPhysicalDeviceProperties(physical_device_,
436 &physical_device_properties_);
437
438 if (SupportsApiVersion(1, 1, 0)) {
439 #include "vk-wrappers-1-1.inc"
440 }
441
442 return {};
443 }
444
SupportsApiVersion(uint32_t major,uint32_t minor,uint32_t patch)445 bool Device::SupportsApiVersion(uint32_t major,
446 uint32_t minor,
447 uint32_t patch) {
448 #pragma clang diagnostic push
449 #pragma clang diagnostic ignored "-Wold-style-cast"
450 return physical_device_properties_.apiVersion >=
451 VK_MAKE_VERSION(major, minor, patch);
452 #pragma clang diagnostic pop
453 }
454
ReportExecutionTiming(double time_in_ms)455 void Device::ReportExecutionTiming(double time_in_ms) {
456 if (delegate_) {
457 delegate_->ReportExecutionTiming(time_in_ms);
458 }
459 }
460
Initialize(PFN_vkGetInstanceProcAddr getInstanceProcAddr,const std::vector<std::string> & required_features,const std::vector<std::string> & required_properties,const std::vector<std::string> & required_device_extensions,const VkPhysicalDeviceFeatures & available_features,const VkPhysicalDeviceFeatures2KHR & available_features2,const VkPhysicalDeviceProperties2KHR & available_properties2,const std::vector<std::string> & available_extensions)461 Result Device::Initialize(
462 PFN_vkGetInstanceProcAddr getInstanceProcAddr,
463 const std::vector<std::string>& required_features,
464 const std::vector<std::string>& required_properties,
465 const std::vector<std::string>& required_device_extensions,
466 const VkPhysicalDeviceFeatures& available_features,
467 const VkPhysicalDeviceFeatures2KHR& available_features2,
468 const VkPhysicalDeviceProperties2KHR& available_properties2,
469 const std::vector<std::string>& available_extensions) {
470 Result r = LoadVulkanPointers(getInstanceProcAddr, delegate_);
471 if (!r.IsSuccess())
472 return r;
473
474 // Check for the core features. We don't know if available_features or
475 // available_features2 is provided, so check both.
476 if (!AreAllRequiredFeaturesSupported(available_features, required_features) &&
477 !AreAllRequiredFeaturesSupported(available_features2.features,
478 required_features)) {
479 return Result(
480 "Vulkan: Device::Initialize given physical device does not support "
481 "required features");
482 }
483
484 // Search for additional features in case they are found in pNext field of
485 // available_features2.
486 VkPhysicalDeviceVariablePointerFeaturesKHR* var_ptrs = nullptr;
487 VkPhysicalDeviceFloat16Int8FeaturesKHR* float16_ptrs = nullptr;
488 VkPhysicalDevice8BitStorageFeaturesKHR* storage8_ptrs = nullptr;
489 VkPhysicalDevice16BitStorageFeaturesKHR* storage16_ptrs = nullptr;
490 VkPhysicalDeviceVulkan11Features* vulkan11_ptrs = nullptr;
491 VkPhysicalDeviceVulkan12Features* vulkan12_ptrs = nullptr;
492 VkPhysicalDeviceVulkan13Features* vulkan13_ptrs = nullptr;
493 VkPhysicalDeviceVulkan14Features* vulkan14_ptrs = nullptr;
494 VkPhysicalDeviceSubgroupSizeControlFeaturesEXT*
495 subgroup_size_control_features = nullptr;
496 VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures*
497 shader_subgroup_extended_types_ptrs = nullptr;
498 VkPhysicalDeviceIndexTypeUint8FeaturesEXT* index_type_uint8_ptrs = nullptr;
499 VkPhysicalDeviceAccelerationStructureFeaturesKHR*
500 acceleration_structure_ptrs = nullptr;
501 VkPhysicalDeviceBufferDeviceAddressFeatures* bda_ptrs = nullptr;
502 VkPhysicalDeviceRayTracingPipelineFeaturesKHR* ray_tracing_pipeline_ptrs =
503 nullptr;
504
505 void* ptr = available_features2.pNext;
506 while (ptr != nullptr) {
507 BaseOutStructure* s = static_cast<BaseOutStructure*>(ptr);
508 switch (s->sType) {
509 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR:
510 var_ptrs =
511 static_cast<VkPhysicalDeviceVariablePointerFeaturesKHR*>(ptr);
512 break;
513 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR:
514 float16_ptrs =
515 static_cast<VkPhysicalDeviceFloat16Int8FeaturesKHR*>(ptr);
516 break;
517 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR:
518 storage8_ptrs =
519 static_cast<VkPhysicalDevice8BitStorageFeaturesKHR*>(ptr);
520 break;
521 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR:
522 storage16_ptrs =
523 static_cast<VkPhysicalDevice16BitStorageFeaturesKHR*>(ptr);
524 break;
525 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT:
526 subgroup_size_control_features =
527 static_cast<VkPhysicalDeviceSubgroupSizeControlFeaturesEXT*>(ptr);
528 break;
529 // NOLINTNEXTLINE(whitespace/line_length)
530 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES:
531 shader_subgroup_extended_types_ptrs =
532 static_cast<VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures*>(
533 ptr);
534 break;
535 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT:
536 index_type_uint8_ptrs =
537 static_cast<VkPhysicalDeviceIndexTypeUint8FeaturesEXT*>(ptr);
538 break;
539 // NOLINTNEXTLINE(whitespace/line_length)
540 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR:
541 acceleration_structure_ptrs =
542 static_cast<VkPhysicalDeviceAccelerationStructureFeaturesKHR*>(ptr);
543 break;
544 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES:
545 bda_ptrs =
546 static_cast<VkPhysicalDeviceBufferDeviceAddressFeatures*>(ptr);
547 break;
548 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR:
549 ray_tracing_pipeline_ptrs =
550 static_cast<VkPhysicalDeviceRayTracingPipelineFeaturesKHR*>(ptr);
551 break;
552 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES:
553 vulkan11_ptrs = static_cast<VkPhysicalDeviceVulkan11Features*>(ptr);
554 break;
555 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES:
556 vulkan12_ptrs = static_cast<VkPhysicalDeviceVulkan12Features*>(ptr);
557 break;
558 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES:
559 vulkan13_ptrs = static_cast<VkPhysicalDeviceVulkan13Features*>(ptr);
560 break;
561 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES:
562 vulkan14_ptrs = static_cast<VkPhysicalDeviceVulkan14Features*>(ptr);
563 break;
564 default:
565 break;
566 }
567 ptr = s->pNext;
568 }
569
570 // Compare the available additional (non-core) features against the
571 // requirements.
572 //
573 // Vulkan 1.2 added support for defining non-core physical device features
574 // using VkPhysicalDeviceVulkan11Features and VkPhysicalDeviceVulkan12Features
575 // structures. If |vulkan11_ptrs| and/or |vulkan12_ptrs| are null, we must
576 // check for features using the old approach (by checking across various
577 // feature structs); otherwise, we can check features via the new structs.
578 for (const auto& feature : required_features) {
579 // First check the feature structures are provided for the required
580 // features.
581 if ((feature == kVariablePointers ||
582 feature == kVariablePointersStorageBuffer) &&
583 var_ptrs == nullptr && vulkan11_ptrs == nullptr) {
584 return amber::Result(
585 "Variable pointers requested but feature not returned");
586 }
587 if ((feature == k16BitStorage_Storage ||
588 feature == k16BitStorage_UniformAndStorage ||
589 feature == k16BitStorage_PushConstant ||
590 feature == k16BitStorage_InputOutput) &&
591 storage16_ptrs == nullptr && vulkan11_ptrs == nullptr) {
592 return amber::Result(
593 "Shader 16-bit storage requested but feature not returned");
594 }
595 if ((feature == kFloat16Int8_Float16 || feature == kFloat16Int8_Int8) &&
596 float16_ptrs == nullptr && vulkan12_ptrs == nullptr) {
597 return amber::Result(
598 "Shader float16/int8 requested but feature not returned");
599 }
600 if ((feature == k8BitStorage_UniformAndStorage ||
601 feature == k8BitStorage_Storage ||
602 feature == k8BitStorage_PushConstant) &&
603 storage8_ptrs == nullptr && vulkan12_ptrs == nullptr) {
604 return amber::Result(
605 "Shader 8-bit storage requested but feature not returned");
606 }
607 if ((feature == kSubgroupSizeControl || feature == kComputeFullSubgroups) &&
608 subgroup_size_control_features == nullptr && vulkan13_ptrs == nullptr) {
609 return amber::Result("Missing subgroup size control features");
610 }
611 if (feature == kShaderSubgroupExtendedTypes &&
612 shader_subgroup_extended_types_ptrs == nullptr &&
613 vulkan12_ptrs == nullptr) {
614 return amber::Result(
615 "Subgroup extended types requested but feature not returned");
616 }
617 if (feature == kAccelerationStructure) {
618 if (acceleration_structure_ptrs == nullptr)
619 return amber::Result(
620 "Acceleration structure requested but feature not returned");
621 if (ptrs_.vkCreateAccelerationStructureKHR == nullptr)
622 return amber::Result(
623 "vkCreateAccelerationStructureKHR is required, but not provided");
624 if (ptrs_.vkDestroyAccelerationStructureKHR == nullptr)
625 return amber::Result(
626 "vkDestroyAccelerationStructureKHR is required, but not provided");
627 if (ptrs_.vkGetAccelerationStructureBuildSizesKHR == nullptr)
628 return amber::Result(
629 "vkGetAccelerationStructureBuildSizesKHR is required, but not "
630 "provided");
631 if (ptrs_.vkBuildAccelerationStructuresKHR == nullptr)
632 return amber::Result(
633 "vkBuildAccelerationStructuresKHR is required, but not "
634 "provided");
635 if (ptrs_.vkCmdBuildAccelerationStructuresKHR == nullptr)
636 return amber::Result(
637 "vkCmdBuildAccelerationStructuresKHR is required, but not "
638 "provided");
639 if (ptrs_.vkGetAccelerationStructureDeviceAddressKHR == nullptr)
640 return amber::Result(
641 "vkGetAccelerationStructureDeviceAddressKHR is required, but not "
642 "provided");
643 }
644 if (feature == kBufferDeviceAddress && bda_ptrs == nullptr &&
645 vulkan12_ptrs == nullptr) {
646 return amber::Result(
647 "Buffer device address requested but feature not returned");
648 }
649 if (feature == kRayTracingPipeline) {
650 if (ray_tracing_pipeline_ptrs == nullptr)
651 return amber::Result(
652 "Ray tracing pipeline requested but feature not returned");
653 if (ptrs_.vkCreateRayTracingPipelinesKHR == nullptr)
654 return amber::Result(
655 "vkCreateRayTracingPipelinesKHR is required, but not provided");
656 if (ptrs_.vkCmdTraceRaysKHR == nullptr)
657 return amber::Result(
658 "vkCmdTraceRaysKHR is required, but not provided");
659 if (ptrs_.vkGetRayTracingShaderGroupHandlesKHR == nullptr)
660 return amber::Result(
661 "vkGetRayTracingShaderGroupHandlesKHR is required, but not "
662 "provided");
663 }
664
665 // Next check the fields of the feature structures.
666
667 // If Vulkan 1.1 structure exists the features are set there.
668 if (vulkan11_ptrs) {
669 if (feature == kVariablePointers &&
670 vulkan11_ptrs->variablePointers != VK_TRUE) {
671 return amber::Result("Missing variable pointers feature");
672 }
673 if (feature == kVariablePointersStorageBuffer &&
674 vulkan11_ptrs->variablePointersStorageBuffer != VK_TRUE) {
675 return amber::Result(
676 "Missing variable pointers storage buffer feature");
677 }
678 if (feature == k16BitStorage_Storage &&
679 vulkan11_ptrs->storageBuffer16BitAccess != VK_TRUE) {
680 return amber::Result("Missing 16-bit storage access");
681 }
682 if (feature == k16BitStorage_UniformAndStorage &&
683 vulkan11_ptrs->uniformAndStorageBuffer16BitAccess != VK_TRUE) {
684 return amber::Result("Missing 16-bit uniform and storage access");
685 }
686 if (feature == k16BitStorage_PushConstant &&
687 vulkan11_ptrs->storagePushConstant16 != VK_TRUE) {
688 return amber::Result("Missing 16-bit push constant access");
689 }
690 if (feature == k16BitStorage_InputOutput &&
691 vulkan11_ptrs->storageInputOutput16 != VK_TRUE) {
692 return amber::Result("Missing 16-bit input/output access");
693 }
694 } else {
695 // Vulkan 1.1 structure was not found. Use separate structures per each
696 // feature.
697 if (feature == kVariablePointers &&
698 var_ptrs->variablePointers != VK_TRUE) {
699 return amber::Result("Missing variable pointers feature");
700 }
701 if (feature == kVariablePointersStorageBuffer &&
702 var_ptrs->variablePointersStorageBuffer != VK_TRUE) {
703 return amber::Result(
704 "Missing variable pointers storage buffer feature");
705 }
706 if (feature == k16BitStorage_Storage &&
707 storage16_ptrs->storageBuffer16BitAccess != VK_TRUE) {
708 return amber::Result("Missing 16-bit storage access");
709 }
710 if (feature == k16BitStorage_UniformAndStorage &&
711 storage16_ptrs->uniformAndStorageBuffer16BitAccess != VK_TRUE) {
712 return amber::Result("Missing 16-bit uniform and storage access");
713 }
714 if (feature == k16BitStorage_PushConstant &&
715 storage16_ptrs->storagePushConstant16 != VK_TRUE) {
716 return amber::Result("Missing 16-bit push constant access");
717 }
718 if (feature == k16BitStorage_InputOutput &&
719 storage16_ptrs->storageInputOutput16 != VK_TRUE) {
720 return amber::Result("Missing 16-bit input/output access");
721 }
722 }
723
724 // If Vulkan 1.2 structure exists the features are set there.
725 if (vulkan12_ptrs) {
726 if (feature == kFloat16Int8_Float16 &&
727 vulkan12_ptrs->shaderFloat16 != VK_TRUE) {
728 return amber::Result("Missing float16 feature");
729 }
730 if (feature == kFloat16Int8_Int8 &&
731 vulkan12_ptrs->shaderInt8 != VK_TRUE) {
732 return amber::Result("Missing int8 feature");
733 }
734 if (feature == k8BitStorage_Storage &&
735 vulkan12_ptrs->storageBuffer8BitAccess != VK_TRUE) {
736 return amber::Result("Missing 8-bit storage access");
737 }
738 if (feature == k8BitStorage_UniformAndStorage &&
739 vulkan12_ptrs->uniformAndStorageBuffer8BitAccess != VK_TRUE) {
740 return amber::Result("Missing 8-bit uniform and storage access");
741 }
742 if (feature == k8BitStorage_PushConstant &&
743 vulkan12_ptrs->storagePushConstant8 != VK_TRUE) {
744 return amber::Result("Missing 8-bit push constant access");
745 }
746 if (feature == kShaderSubgroupExtendedTypes &&
747 vulkan12_ptrs->shaderSubgroupExtendedTypes != VK_TRUE) {
748 return amber::Result("Missing subgroup extended types");
749 }
750 if (feature == kBufferDeviceAddress &&
751 vulkan12_ptrs->bufferDeviceAddress != VK_TRUE) {
752 return amber::Result("Missing buffer device address");
753 }
754 } else {
755 // Vulkan 1.2 structure was not found. Use separate structures per each
756 // feature.
757 if (feature == kFloat16Int8_Float16 &&
758 float16_ptrs->shaderFloat16 != VK_TRUE) {
759 return amber::Result("Missing float16 feature");
760 }
761 if (feature == kFloat16Int8_Int8 && float16_ptrs->shaderInt8 != VK_TRUE) {
762 return amber::Result("Missing int8 feature");
763 }
764 if (feature == k8BitStorage_Storage &&
765 storage8_ptrs->storageBuffer8BitAccess != VK_TRUE) {
766 return amber::Result("Missing 8-bit storage access");
767 }
768 if (feature == k8BitStorage_UniformAndStorage &&
769 storage8_ptrs->uniformAndStorageBuffer8BitAccess != VK_TRUE) {
770 return amber::Result("Missing 8-bit uniform and storage access");
771 }
772 if (feature == k8BitStorage_PushConstant &&
773 storage8_ptrs->storagePushConstant8 != VK_TRUE) {
774 return amber::Result("Missing 8-bit push constant access");
775 }
776 if (feature == kShaderSubgroupExtendedTypes &&
777 shader_subgroup_extended_types_ptrs->shaderSubgroupExtendedTypes !=
778 VK_TRUE) {
779 return amber::Result("Missing subgroup extended types");
780 }
781 if (feature == kBufferDeviceAddress &&
782 bda_ptrs->bufferDeviceAddress != VK_TRUE) {
783 return amber::Result("Missing buffer device address");
784 }
785 }
786
787 // If Vulkan 1.3 structure exists the features are set there.
788 if (vulkan13_ptrs) {
789 if (feature == kSubgroupSizeControl &&
790 vulkan13_ptrs->subgroupSizeControl != VK_TRUE) {
791 return amber::Result("Missing subgroup size control feature");
792 }
793 if (feature == kComputeFullSubgroups &&
794 vulkan13_ptrs->computeFullSubgroups != VK_TRUE) {
795 return amber::Result("Missing compute full subgroups feature");
796 }
797 } else {
798 if (feature == kSubgroupSizeControl &&
799 subgroup_size_control_features->subgroupSizeControl != VK_TRUE) {
800 return amber::Result("Missing subgroup size control feature");
801 }
802 if (feature == kComputeFullSubgroups &&
803 subgroup_size_control_features->computeFullSubgroups != VK_TRUE) {
804 return amber::Result("Missing compute full subgroups feature");
805 }
806 }
807
808 // If Vulkan 1.4 structure exists the features are set there.
809 if (vulkan14_ptrs) {
810 if (feature == kIndexTypeUint8 &&
811 vulkan14_ptrs->indexTypeUint8 != VK_TRUE) {
812 return amber::Result(
813 "Index type uint8_t requested but feature not returned");
814 }
815 } else {
816 if (feature == kIndexTypeUint8 &&
817 (index_type_uint8_ptrs == nullptr ||
818 index_type_uint8_ptrs->indexTypeUint8 != VK_TRUE)) {
819 return amber::Result(
820 "Index type uint8_t requested but feature not returned");
821 }
822 }
823 }
824
825 if (!AreAllExtensionsSupported(available_extensions,
826 required_device_extensions)) {
827 return Result(
828 "Vulkan: Device::Initialize given physical device does not support "
829 "required extensions");
830 }
831
832 const bool needs_shader_group_handle_size =
833 std::find(required_features.begin(), required_features.end(),
834 kAccelerationStructure) != required_features.end();
835
836 if (needs_shader_group_handle_size) {
837 VkPhysicalDeviceRayTracingPipelinePropertiesKHR rt_pipeline_properties = {};
838 rt_pipeline_properties.sType =
839 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR;
840
841 VkPhysicalDeviceProperties2KHR properties2 = {};
842 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
843 properties2.pNext = &rt_pipeline_properties;
844
845 ptrs_.vkGetPhysicalDeviceProperties2(physical_device_, &properties2);
846
847 shader_group_handle_size_ = rt_pipeline_properties.shaderGroupHandleSize;
848 }
849
850 VkPhysicalDeviceVulkan12Properties* pv12 = nullptr;
851 VkPhysicalDeviceFloatControlsProperties* pfc = nullptr;
852
853 ptr = available_properties2.pNext;
854 while (ptr != nullptr) {
855 BaseOutStructure* s = static_cast<BaseOutStructure*>(ptr);
856 switch (s->sType) {
857 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES:
858 pv12 = static_cast<VkPhysicalDeviceVulkan12Properties*>(ptr);
859 break;
860 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR:
861 pfc = static_cast<VkPhysicalDeviceFloatControlsPropertiesKHR*>(ptr);
862 break;
863 default:
864 break;
865 }
866 ptr = s->pNext;
867 }
868
869 #define CHK_P(R, P, NAME, S1, S2) \
870 do { \
871 if (R == -1 && P == #NAME) \
872 R = ((S1 && S1->NAME) || (S2 && S2->NAME)) ? 1 : 0; \
873 } while (false)
874
875 for (const std::string& prop : required_properties) {
876 const size_t dot_pos = prop.find('.');
877 const size_t dot_found = dot_pos != std::string::npos;
878 const std::string prefix = dot_found ? prop.substr(0, dot_pos) : "";
879 const std::string name = dot_found ? prop.substr(dot_pos + 1) : prop;
880 int supported = -1;
881
882 if (supported == -1 && prefix == "FloatControlsProperties") {
883 if (pfc == nullptr && pv12 == nullptr)
884 return Result(
885 "Vulkan: Device::Initialize given physical device does not support "
886 "required float control properties");
887
888 CHK_P(supported, name, shaderSignedZeroInfNanPreserveFloat16, pfc, pv12);
889 CHK_P(supported, name, shaderSignedZeroInfNanPreserveFloat32, pfc, pv12);
890 CHK_P(supported, name, shaderSignedZeroInfNanPreserveFloat64, pfc, pv12);
891 CHK_P(supported, name, shaderDenormPreserveFloat16, pfc, pv12);
892 CHK_P(supported, name, shaderDenormPreserveFloat32, pfc, pv12);
893 CHK_P(supported, name, shaderDenormPreserveFloat64, pfc, pv12);
894 CHK_P(supported, name, shaderDenormFlushToZeroFloat16, pfc, pv12);
895 CHK_P(supported, name, shaderDenormFlushToZeroFloat32, pfc, pv12);
896 CHK_P(supported, name, shaderDenormFlushToZeroFloat64, pfc, pv12);
897 CHK_P(supported, name, shaderRoundingModeRTEFloat16, pfc, pv12);
898 CHK_P(supported, name, shaderRoundingModeRTEFloat32, pfc, pv12);
899 CHK_P(supported, name, shaderRoundingModeRTEFloat64, pfc, pv12);
900 CHK_P(supported, name, shaderRoundingModeRTZFloat16, pfc, pv12);
901 CHK_P(supported, name, shaderRoundingModeRTZFloat32, pfc, pv12);
902 CHK_P(supported, name, shaderRoundingModeRTZFloat64, pfc, pv12);
903 }
904
905 if (supported == 0)
906 return Result("Vulkan: Device::Initialize missing " + prop + " property");
907
908 if (supported == -1)
909 return Result("Vulkan: Device::Initialize property not handled " + prop);
910 }
911
912 ptrs_.vkGetPhysicalDeviceMemoryProperties(physical_device_,
913 &physical_memory_properties_);
914
915 subgroup_size_control_properties_ = {};
916 const bool needs_subgroup_size_control =
917 std::find(required_features.begin(), required_features.end(),
918 kSubgroupSizeControl) != required_features.end();
919
920 bool needs_subgroup_supported_operations = false;
921 bool needs_subgroup_supported_stages = false;
922
923 // Search for subgroup supported operations requirements.
924 for (const auto& feature : required_features)
925 if (feature.find(kSubgroupSupportedOperations) != std::string::npos)
926 needs_subgroup_supported_operations = true;
927
928 // Search for subgroup supported stages requirements.
929 for (const auto& feature : required_features)
930 if (feature.find(kSubgroupSupportedStages) != std::string::npos)
931 needs_subgroup_supported_stages = true;
932
933 const bool needs_subgroup_properties =
934 needs_subgroup_supported_operations || needs_subgroup_supported_stages;
935
936 if (needs_subgroup_size_control || needs_subgroup_properties) {
937 // Always chain all physical device properties structs in case at least one
938 // of them is needed.
939 VkPhysicalDeviceProperties2 properties2 = {};
940 VkPhysicalDeviceSubgroupProperties subgroup_properties = {};
941 VkPhysicalDeviceVulkan11Properties vulkan11_properties = {};
942 VkSubgroupFeatureFlags subgroup_supported_operations;
943 VkShaderStageFlags subgroup_supported_stages;
944 properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
945 properties2.pNext = &subgroup_size_control_properties_;
946 subgroup_size_control_properties_.sType =
947 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT;
948 if (SupportsApiVersion(1, 2, 0)) {
949 subgroup_size_control_properties_.pNext = &vulkan11_properties;
950 vulkan11_properties.sType =
951 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES;
952 } else {
953 subgroup_size_control_properties_.pNext = &subgroup_properties;
954 subgroup_properties.sType =
955 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
956 }
957
958 if (needs_subgroup_size_control && !SupportsApiVersion(1, 1, 0)) {
959 return Result(
960 "Vulkan: Device::Initialize subgroup size control feature also "
961 "requires an API version of 1.1 or higher");
962 }
963 if (needs_subgroup_properties && !SupportsApiVersion(1, 1, 0)) {
964 return Result(
965 "Vulkan: Device::Initialize subgroup properties also "
966 "requires an API version of 1.1 or higher");
967 }
968 ptrs_.vkGetPhysicalDeviceProperties2(physical_device_, &properties2);
969
970 if (needs_subgroup_supported_operations) {
971 // Read supported subgroup operations from the correct struct depending on
972 // the device API
973 if (SupportsApiVersion(1, 2, 0)) {
974 subgroup_supported_operations =
975 vulkan11_properties.subgroupSupportedOperations;
976 } else {
977 subgroup_supported_operations = subgroup_properties.supportedOperations;
978 }
979
980 for (const auto& feature : required_features) {
981 if (feature == kSubgroupSupportedOperationsBasic &&
982 !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_BASIC_BIT)) {
983 return amber::Result("Missing subgroup operation basic feature");
984 }
985 if (feature == kSubgroupSupportedOperationsVote &&
986 !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_VOTE_BIT)) {
987 return amber::Result("Missing subgroup operation vote feature");
988 }
989 if (feature == kSubgroupSupportedOperationsArithmetic &&
990 !(subgroup_supported_operations &
991 VK_SUBGROUP_FEATURE_ARITHMETIC_BIT)) {
992 return amber::Result("Missing subgroup operation arithmetic feature");
993 }
994 if (feature == kSubgroupSupportedOperationsBallot &&
995 !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_BALLOT_BIT)) {
996 return amber::Result("Missing subgroup operation ballot feature");
997 }
998 if (feature == kSubgroupSupportedOperationsShuffle &&
999 !(subgroup_supported_operations &
1000 VK_SUBGROUP_FEATURE_SHUFFLE_BIT)) {
1001 return amber::Result("Missing subgroup operation shuffle feature");
1002 }
1003 if (feature == kSubgroupSupportedOperationsShuffleRelative &&
1004 !(subgroup_supported_operations &
1005 VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT)) {
1006 return amber::Result(
1007 "Missing subgroup operation shuffle relative feature");
1008 }
1009 if (feature == kSubgroupSupportedOperationsClustered &&
1010 !(subgroup_supported_operations &
1011 VK_SUBGROUP_FEATURE_CLUSTERED_BIT)) {
1012 return amber::Result("Missing subgroup operation clustered feature");
1013 }
1014 if (feature == kSubgroupSupportedOperationsQuad &&
1015 !(subgroup_supported_operations & VK_SUBGROUP_FEATURE_QUAD_BIT)) {
1016 return amber::Result("Missing subgroup operation quad feature");
1017 }
1018 }
1019 }
1020
1021 if (needs_subgroup_supported_stages) {
1022 // Read supported subgroup stages from the correct struct depending on the
1023 // device API
1024 if (SupportsApiVersion(1, 2, 0)) {
1025 subgroup_supported_stages = vulkan11_properties.subgroupSupportedStages;
1026 } else {
1027 subgroup_supported_stages = subgroup_properties.supportedStages;
1028 }
1029
1030 for (const auto& feature : required_features) {
1031 if (feature == kSubgroupSupportedStagesVertex &&
1032 !(subgroup_supported_stages & VK_SHADER_STAGE_VERTEX_BIT)) {
1033 return amber::Result(
1034 "Subgroup operations not supported for vertex shader stage");
1035 }
1036 if (feature == kSubgroupSupportedStagesTessellationControl &&
1037 !(subgroup_supported_stages &
1038 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)) {
1039 return amber::Result(
1040 "Subgroup operations not supported for tessellation control "
1041 "shader stage");
1042 }
1043 if (feature == kSubgroupSupportedStagesTessellationEvaluation &&
1044 !(subgroup_supported_stages &
1045 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) {
1046 return amber::Result(
1047 "Subgroup operations not supported for tessellation evaluation "
1048 "shader stage");
1049 }
1050 if (feature == kSubgroupSupportedStagesGeometry &&
1051 !(subgroup_supported_stages & VK_SHADER_STAGE_GEOMETRY_BIT)) {
1052 return amber::Result(
1053 "Subgroup operations not supported for geometry shader stage");
1054 }
1055 if (feature == kSubgroupSupportedStagesFragment &&
1056 !(subgroup_supported_stages & VK_SHADER_STAGE_FRAGMENT_BIT)) {
1057 return amber::Result(
1058 "Subgroup operations not supported for fragment shader stage");
1059 }
1060 if (feature == kSubgroupSupportedStagesCompute &&
1061 !(subgroup_supported_stages & VK_SHADER_STAGE_COMPUTE_BIT)) {
1062 return amber::Result(
1063 "Subgroup operations not supported for compute shader stage");
1064 }
1065 }
1066 }
1067 }
1068
1069 return {};
1070 }
1071
IsFormatSupportedByPhysicalDevice(const Format & format,BufferType type)1072 bool Device::IsFormatSupportedByPhysicalDevice(const Format& format,
1073 BufferType type) {
1074 VkFormat vk_format = GetVkFormat(format);
1075 VkFormatProperties properties = VkFormatProperties();
1076 GetPtrs()->vkGetPhysicalDeviceFormatProperties(physical_device_, vk_format,
1077 &properties);
1078
1079 VkFormatFeatureFlagBits flag = VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
1080 bool is_buffer_type_image = false;
1081 switch (type) {
1082 case BufferType::kColor:
1083 case BufferType::kResolve:
1084 case BufferType::kStorageImage:
1085 flag = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
1086 is_buffer_type_image = true;
1087 break;
1088 case BufferType::kDepthStencil:
1089 flag = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
1090 is_buffer_type_image = true;
1091 break;
1092 case BufferType::kSampledImage:
1093 case BufferType::kCombinedImageSampler:
1094 flag = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
1095 is_buffer_type_image = true;
1096 break;
1097 case BufferType::kVertex:
1098 flag = VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT;
1099 is_buffer_type_image = false;
1100 break;
1101 default:
1102 return false;
1103 }
1104
1105 return ((is_buffer_type_image ? properties.optimalTilingFeatures
1106 : properties.bufferFeatures) &
1107 flag) == flag;
1108 }
1109
HasMemoryFlags(uint32_t memory_type_index,const VkMemoryPropertyFlags flags) const1110 bool Device::HasMemoryFlags(uint32_t memory_type_index,
1111 const VkMemoryPropertyFlags flags) const {
1112 return (physical_memory_properties_.memoryTypes[memory_type_index]
1113 .propertyFlags &
1114 flags) == flags;
1115 }
1116
IsMemoryHostAccessible(uint32_t memory_type_index) const1117 bool Device::IsMemoryHostAccessible(uint32_t memory_type_index) const {
1118 return HasMemoryFlags(memory_type_index, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
1119 }
1120
IsMemoryHostCoherent(uint32_t memory_type_index) const1121 bool Device::IsMemoryHostCoherent(uint32_t memory_type_index) const {
1122 return HasMemoryFlags(memory_type_index,
1123 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
1124 }
1125
GetMaxPushConstants() const1126 uint32_t Device::GetMaxPushConstants() const {
1127 return physical_device_properties_.limits.maxPushConstantsSize;
1128 }
1129
IsTimestampComputeAndGraphicsSupported() const1130 bool Device::IsTimestampComputeAndGraphicsSupported() const {
1131 return physical_device_properties_.limits.timestampComputeAndGraphics;
1132 }
1133
GetTimestampPeriod() const1134 float Device::GetTimestampPeriod() const {
1135 return physical_device_properties_.limits.timestampPeriod;
1136 }
1137
IsDescriptorSetInBounds(uint32_t descriptor_set) const1138 bool Device::IsDescriptorSetInBounds(uint32_t descriptor_set) const {
1139 VkPhysicalDeviceProperties properties = VkPhysicalDeviceProperties();
1140 GetPtrs()->vkGetPhysicalDeviceProperties(physical_device_, &properties);
1141 return properties.limits.maxBoundDescriptorSets > descriptor_set;
1142 }
1143
GetVkFormat(const Format & format) const1144 VkFormat Device::GetVkFormat(const Format& format) const {
1145 VkFormat ret = VK_FORMAT_UNDEFINED;
1146 switch (format.GetFormatType()) {
1147 case FormatType::kUnknown:
1148 ret = VK_FORMAT_UNDEFINED;
1149 break;
1150 case FormatType::kA1R5G5B5_UNORM_PACK16:
1151 ret = VK_FORMAT_A1R5G5B5_UNORM_PACK16;
1152 break;
1153 case FormatType::kA2B10G10R10_SINT_PACK32:
1154 ret = VK_FORMAT_A2B10G10R10_SINT_PACK32;
1155 break;
1156 case FormatType::kA2B10G10R10_SNORM_PACK32:
1157 ret = VK_FORMAT_A2B10G10R10_SNORM_PACK32;
1158 break;
1159 case FormatType::kA2B10G10R10_SSCALED_PACK32:
1160 ret = VK_FORMAT_A2B10G10R10_SSCALED_PACK32;
1161 break;
1162 case FormatType::kA2B10G10R10_UINT_PACK32:
1163 ret = VK_FORMAT_A2B10G10R10_UINT_PACK32;
1164 break;
1165 case FormatType::kA2B10G10R10_UNORM_PACK32:
1166 ret = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
1167 break;
1168 case FormatType::kA2B10G10R10_USCALED_PACK32:
1169 ret = VK_FORMAT_A2B10G10R10_USCALED_PACK32;
1170 break;
1171 case FormatType::kA2R10G10B10_SINT_PACK32:
1172 ret = VK_FORMAT_A2R10G10B10_SINT_PACK32;
1173 break;
1174 case FormatType::kA2R10G10B10_SNORM_PACK32:
1175 ret = VK_FORMAT_A2R10G10B10_SNORM_PACK32;
1176 break;
1177 case FormatType::kA2R10G10B10_SSCALED_PACK32:
1178 ret = VK_FORMAT_A2R10G10B10_SSCALED_PACK32;
1179 break;
1180 case FormatType::kA2R10G10B10_UINT_PACK32:
1181 ret = VK_FORMAT_A2R10G10B10_UINT_PACK32;
1182 break;
1183 case FormatType::kA2R10G10B10_UNORM_PACK32:
1184 ret = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
1185 break;
1186 case FormatType::kA2R10G10B10_USCALED_PACK32:
1187 ret = VK_FORMAT_A2R10G10B10_USCALED_PACK32;
1188 break;
1189 case FormatType::kA8B8G8R8_SINT_PACK32:
1190 ret = VK_FORMAT_A8B8G8R8_SINT_PACK32;
1191 break;
1192 case FormatType::kA8B8G8R8_SNORM_PACK32:
1193 ret = VK_FORMAT_A8B8G8R8_SNORM_PACK32;
1194 break;
1195 case FormatType::kA8B8G8R8_SRGB_PACK32:
1196 ret = VK_FORMAT_A8B8G8R8_SRGB_PACK32;
1197 break;
1198 case FormatType::kA8B8G8R8_SSCALED_PACK32:
1199 ret = VK_FORMAT_A8B8G8R8_SSCALED_PACK32;
1200 break;
1201 case FormatType::kA8B8G8R8_UINT_PACK32:
1202 ret = VK_FORMAT_A8B8G8R8_UINT_PACK32;
1203 break;
1204 case FormatType::kA8B8G8R8_UNORM_PACK32:
1205 ret = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
1206 break;
1207 case FormatType::kA8B8G8R8_USCALED_PACK32:
1208 ret = VK_FORMAT_A8B8G8R8_USCALED_PACK32;
1209 break;
1210 case FormatType::kB10G11R11_UFLOAT_PACK32:
1211 ret = VK_FORMAT_B10G11R11_UFLOAT_PACK32;
1212 break;
1213 case FormatType::kB4G4R4A4_UNORM_PACK16:
1214 ret = VK_FORMAT_B4G4R4A4_UNORM_PACK16;
1215 break;
1216 case FormatType::kB5G5R5A1_UNORM_PACK16:
1217 ret = VK_FORMAT_B5G5R5A1_UNORM_PACK16;
1218 break;
1219 case FormatType::kB5G6R5_UNORM_PACK16:
1220 ret = VK_FORMAT_B5G6R5_UNORM_PACK16;
1221 break;
1222 case FormatType::kB8G8R8A8_SINT:
1223 ret = VK_FORMAT_B8G8R8A8_SINT;
1224 break;
1225 case FormatType::kB8G8R8A8_SNORM:
1226 ret = VK_FORMAT_B8G8R8A8_SNORM;
1227 break;
1228 case FormatType::kB8G8R8A8_SRGB:
1229 ret = VK_FORMAT_B8G8R8A8_SRGB;
1230 break;
1231 case FormatType::kB8G8R8A8_SSCALED:
1232 ret = VK_FORMAT_B8G8R8A8_SSCALED;
1233 break;
1234 case FormatType::kB8G8R8A8_UINT:
1235 ret = VK_FORMAT_B8G8R8A8_UINT;
1236 break;
1237 case FormatType::kB8G8R8A8_UNORM:
1238 ret = VK_FORMAT_B8G8R8A8_UNORM;
1239 break;
1240 case FormatType::kB8G8R8A8_USCALED:
1241 ret = VK_FORMAT_B8G8R8A8_USCALED;
1242 break;
1243 case FormatType::kB8G8R8_SINT:
1244 ret = VK_FORMAT_B8G8R8_SINT;
1245 break;
1246 case FormatType::kB8G8R8_SNORM:
1247 ret = VK_FORMAT_B8G8R8_SNORM;
1248 break;
1249 case FormatType::kB8G8R8_SRGB:
1250 ret = VK_FORMAT_B8G8R8_SRGB;
1251 break;
1252 case FormatType::kB8G8R8_SSCALED:
1253 ret = VK_FORMAT_B8G8R8_SSCALED;
1254 break;
1255 case FormatType::kB8G8R8_UINT:
1256 ret = VK_FORMAT_B8G8R8_UINT;
1257 break;
1258 case FormatType::kB8G8R8_UNORM:
1259 ret = VK_FORMAT_B8G8R8_UNORM;
1260 break;
1261 case FormatType::kB8G8R8_USCALED:
1262 ret = VK_FORMAT_B8G8R8_USCALED;
1263 break;
1264 case FormatType::kD16_UNORM:
1265 ret = VK_FORMAT_D16_UNORM;
1266 break;
1267 case FormatType::kD16_UNORM_S8_UINT:
1268 ret = VK_FORMAT_D16_UNORM_S8_UINT;
1269 break;
1270 case FormatType::kD24_UNORM_S8_UINT:
1271 ret = VK_FORMAT_D24_UNORM_S8_UINT;
1272 break;
1273 case FormatType::kD32_SFLOAT:
1274 ret = VK_FORMAT_D32_SFLOAT;
1275 break;
1276 case FormatType::kD32_SFLOAT_S8_UINT:
1277 ret = VK_FORMAT_D32_SFLOAT_S8_UINT;
1278 break;
1279 case FormatType::kR16G16B16A16_SFLOAT:
1280 ret = VK_FORMAT_R16G16B16A16_SFLOAT;
1281 break;
1282 case FormatType::kR16G16B16A16_SINT:
1283 ret = VK_FORMAT_R16G16B16A16_SINT;
1284 break;
1285 case FormatType::kR16G16B16A16_SNORM:
1286 ret = VK_FORMAT_R16G16B16A16_SNORM;
1287 break;
1288 case FormatType::kR16G16B16A16_SSCALED:
1289 ret = VK_FORMAT_R16G16B16A16_SSCALED;
1290 break;
1291 case FormatType::kR16G16B16A16_UINT:
1292 ret = VK_FORMAT_R16G16B16A16_UINT;
1293 break;
1294 case FormatType::kR16G16B16A16_UNORM:
1295 ret = VK_FORMAT_R16G16B16A16_UNORM;
1296 break;
1297 case FormatType::kR16G16B16A16_USCALED:
1298 ret = VK_FORMAT_R16G16B16A16_USCALED;
1299 break;
1300 case FormatType::kR16G16B16_SFLOAT:
1301 ret = VK_FORMAT_R16G16B16_SFLOAT;
1302 break;
1303 case FormatType::kR16G16B16_SINT:
1304 ret = VK_FORMAT_R16G16B16_SINT;
1305 break;
1306 case FormatType::kR16G16B16_SNORM:
1307 ret = VK_FORMAT_R16G16B16_SNORM;
1308 break;
1309 case FormatType::kR16G16B16_SSCALED:
1310 ret = VK_FORMAT_R16G16B16_SSCALED;
1311 break;
1312 case FormatType::kR16G16B16_UINT:
1313 ret = VK_FORMAT_R16G16B16_UINT;
1314 break;
1315 case FormatType::kR16G16B16_UNORM:
1316 ret = VK_FORMAT_R16G16B16_UNORM;
1317 break;
1318 case FormatType::kR16G16B16_USCALED:
1319 ret = VK_FORMAT_R16G16B16_USCALED;
1320 break;
1321 case FormatType::kR16G16_SFLOAT:
1322 ret = VK_FORMAT_R16G16_SFLOAT;
1323 break;
1324 case FormatType::kR16G16_SINT:
1325 ret = VK_FORMAT_R16G16_SINT;
1326 break;
1327 case FormatType::kR16G16_SNORM:
1328 ret = VK_FORMAT_R16G16_SNORM;
1329 break;
1330 case FormatType::kR16G16_SSCALED:
1331 ret = VK_FORMAT_R16G16_SSCALED;
1332 break;
1333 case FormatType::kR16G16_UINT:
1334 ret = VK_FORMAT_R16G16_UINT;
1335 break;
1336 case FormatType::kR16G16_UNORM:
1337 ret = VK_FORMAT_R16G16_UNORM;
1338 break;
1339 case FormatType::kR16G16_USCALED:
1340 ret = VK_FORMAT_R16G16_USCALED;
1341 break;
1342 case FormatType::kR16_SFLOAT:
1343 ret = VK_FORMAT_R16_SFLOAT;
1344 break;
1345 case FormatType::kR16_SINT:
1346 ret = VK_FORMAT_R16_SINT;
1347 break;
1348 case FormatType::kR16_SNORM:
1349 ret = VK_FORMAT_R16_SNORM;
1350 break;
1351 case FormatType::kR16_SSCALED:
1352 ret = VK_FORMAT_R16_SSCALED;
1353 break;
1354 case FormatType::kR16_UINT:
1355 ret = VK_FORMAT_R16_UINT;
1356 break;
1357 case FormatType::kR16_UNORM:
1358 ret = VK_FORMAT_R16_UNORM;
1359 break;
1360 case FormatType::kR16_USCALED:
1361 ret = VK_FORMAT_R16_USCALED;
1362 break;
1363 case FormatType::kR32G32B32A32_SFLOAT:
1364 ret = VK_FORMAT_R32G32B32A32_SFLOAT;
1365 break;
1366 case FormatType::kR32G32B32A32_SINT:
1367 ret = VK_FORMAT_R32G32B32A32_SINT;
1368 break;
1369 case FormatType::kR32G32B32A32_UINT:
1370 ret = VK_FORMAT_R32G32B32A32_UINT;
1371 break;
1372 case FormatType::kR32G32B32_SFLOAT:
1373 ret = VK_FORMAT_R32G32B32_SFLOAT;
1374 break;
1375 case FormatType::kR32G32B32_SINT:
1376 ret = VK_FORMAT_R32G32B32_SINT;
1377 break;
1378 case FormatType::kR32G32B32_UINT:
1379 ret = VK_FORMAT_R32G32B32_UINT;
1380 break;
1381 case FormatType::kR32G32_SFLOAT:
1382 ret = VK_FORMAT_R32G32_SFLOAT;
1383 break;
1384 case FormatType::kR32G32_SINT:
1385 ret = VK_FORMAT_R32G32_SINT;
1386 break;
1387 case FormatType::kR32G32_UINT:
1388 ret = VK_FORMAT_R32G32_UINT;
1389 break;
1390 case FormatType::kR32_SFLOAT:
1391 ret = VK_FORMAT_R32_SFLOAT;
1392 break;
1393 case FormatType::kR32_SINT:
1394 ret = VK_FORMAT_R32_SINT;
1395 break;
1396 case FormatType::kR32_UINT:
1397 ret = VK_FORMAT_R32_UINT;
1398 break;
1399 case FormatType::kR4G4B4A4_UNORM_PACK16:
1400 ret = VK_FORMAT_R4G4B4A4_UNORM_PACK16;
1401 break;
1402 case FormatType::kR4G4_UNORM_PACK8:
1403 ret = VK_FORMAT_R4G4_UNORM_PACK8;
1404 break;
1405 case FormatType::kR5G5B5A1_UNORM_PACK16:
1406 ret = VK_FORMAT_R5G5B5A1_UNORM_PACK16;
1407 break;
1408 case FormatType::kR5G6B5_UNORM_PACK16:
1409 ret = VK_FORMAT_R5G6B5_UNORM_PACK16;
1410 break;
1411 case FormatType::kR64G64B64A64_SFLOAT:
1412 ret = VK_FORMAT_R64G64B64A64_SFLOAT;
1413 break;
1414 case FormatType::kR64G64B64A64_SINT:
1415 ret = VK_FORMAT_R64G64B64A64_SINT;
1416 break;
1417 case FormatType::kR64G64B64A64_UINT:
1418 ret = VK_FORMAT_R64G64B64A64_UINT;
1419 break;
1420 case FormatType::kR64G64B64_SFLOAT:
1421 ret = VK_FORMAT_R64G64B64_SFLOAT;
1422 break;
1423 case FormatType::kR64G64B64_SINT:
1424 ret = VK_FORMAT_R64G64B64_SINT;
1425 break;
1426 case FormatType::kR64G64B64_UINT:
1427 ret = VK_FORMAT_R64G64B64_UINT;
1428 break;
1429 case FormatType::kR64G64_SFLOAT:
1430 ret = VK_FORMAT_R64G64_SFLOAT;
1431 break;
1432 case FormatType::kR64G64_SINT:
1433 ret = VK_FORMAT_R64G64_SINT;
1434 break;
1435 case FormatType::kR64G64_UINT:
1436 ret = VK_FORMAT_R64G64_UINT;
1437 break;
1438 case FormatType::kR64_SFLOAT:
1439 ret = VK_FORMAT_R64_SFLOAT;
1440 break;
1441 case FormatType::kR64_SINT:
1442 ret = VK_FORMAT_R64_SINT;
1443 break;
1444 case FormatType::kR64_UINT:
1445 ret = VK_FORMAT_R64_UINT;
1446 break;
1447 case FormatType::kR8G8B8A8_SINT:
1448 ret = VK_FORMAT_R8G8B8A8_SINT;
1449 break;
1450 case FormatType::kR8G8B8A8_SNORM:
1451 ret = VK_FORMAT_R8G8B8A8_SNORM;
1452 break;
1453 case FormatType::kR8G8B8A8_SRGB:
1454 ret = VK_FORMAT_R8G8B8A8_SRGB;
1455 break;
1456 case FormatType::kR8G8B8A8_SSCALED:
1457 ret = VK_FORMAT_R8G8B8A8_SSCALED;
1458 break;
1459 case FormatType::kR8G8B8A8_UINT:
1460 ret = VK_FORMAT_R8G8B8A8_UINT;
1461 break;
1462 case FormatType::kR8G8B8A8_UNORM:
1463 ret = VK_FORMAT_R8G8B8A8_UNORM;
1464 break;
1465 case FormatType::kR8G8B8A8_USCALED:
1466 ret = VK_FORMAT_R8G8B8A8_USCALED;
1467 break;
1468 case FormatType::kR8G8B8_SINT:
1469 ret = VK_FORMAT_R8G8B8_SINT;
1470 break;
1471 case FormatType::kR8G8B8_SNORM:
1472 ret = VK_FORMAT_R8G8B8_SNORM;
1473 break;
1474 case FormatType::kR8G8B8_SRGB:
1475 ret = VK_FORMAT_R8G8B8_SRGB;
1476 break;
1477 case FormatType::kR8G8B8_SSCALED:
1478 ret = VK_FORMAT_R8G8B8_SSCALED;
1479 break;
1480 case FormatType::kR8G8B8_UINT:
1481 ret = VK_FORMAT_R8G8B8_UINT;
1482 break;
1483 case FormatType::kR8G8B8_UNORM:
1484 ret = VK_FORMAT_R8G8B8_UNORM;
1485 break;
1486 case FormatType::kR8G8B8_USCALED:
1487 ret = VK_FORMAT_R8G8B8_USCALED;
1488 break;
1489 case FormatType::kR8G8_SINT:
1490 ret = VK_FORMAT_R8G8_SINT;
1491 break;
1492 case FormatType::kR8G8_SNORM:
1493 ret = VK_FORMAT_R8G8_SNORM;
1494 break;
1495 case FormatType::kR8G8_SRGB:
1496 ret = VK_FORMAT_R8G8_SRGB;
1497 break;
1498 case FormatType::kR8G8_SSCALED:
1499 ret = VK_FORMAT_R8G8_SSCALED;
1500 break;
1501 case FormatType::kR8G8_UINT:
1502 ret = VK_FORMAT_R8G8_UINT;
1503 break;
1504 case FormatType::kR8G8_UNORM:
1505 ret = VK_FORMAT_R8G8_UNORM;
1506 break;
1507 case FormatType::kR8G8_USCALED:
1508 ret = VK_FORMAT_R8G8_USCALED;
1509 break;
1510 case FormatType::kR8_SINT:
1511 ret = VK_FORMAT_R8_SINT;
1512 break;
1513 case FormatType::kR8_SNORM:
1514 ret = VK_FORMAT_R8_SNORM;
1515 break;
1516 case FormatType::kR8_SRGB:
1517 ret = VK_FORMAT_R8_SRGB;
1518 break;
1519 case FormatType::kR8_SSCALED:
1520 ret = VK_FORMAT_R8_SSCALED;
1521 break;
1522 case FormatType::kR8_UINT:
1523 ret = VK_FORMAT_R8_UINT;
1524 break;
1525 case FormatType::kR8_UNORM:
1526 ret = VK_FORMAT_R8_UNORM;
1527 break;
1528 case FormatType::kR8_USCALED:
1529 ret = VK_FORMAT_R8_USCALED;
1530 break;
1531 case FormatType::kS8_UINT:
1532 ret = VK_FORMAT_S8_UINT;
1533 break;
1534 case FormatType::kX8_D24_UNORM_PACK32:
1535 ret = VK_FORMAT_X8_D24_UNORM_PACK32;
1536 break;
1537 }
1538 return ret;
1539 }
1540
IsRequiredSubgroupSizeSupported(const ShaderType type,const uint32_t required_subgroup_size) const1541 bool Device::IsRequiredSubgroupSizeSupported(
1542 const ShaderType type,
1543 const uint32_t required_subgroup_size) const {
1544 VkShaderStageFlagBits stage = {};
1545 switch (type) {
1546 case kShaderTypeGeometry:
1547 stage = VK_SHADER_STAGE_GEOMETRY_BIT;
1548 break;
1549 case kShaderTypeFragment:
1550 stage = VK_SHADER_STAGE_FRAGMENT_BIT;
1551 break;
1552 case kShaderTypeVertex:
1553 stage = VK_SHADER_STAGE_VERTEX_BIT;
1554 break;
1555 case kShaderTypeTessellationControl:
1556 stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1557 break;
1558 case kShaderTypeTessellationEvaluation:
1559 stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
1560 break;
1561 case kShaderTypeCompute:
1562 stage = VK_SHADER_STAGE_COMPUTE_BIT;
1563 break;
1564 default:
1565 return false;
1566 }
1567 if ((stage & subgroup_size_control_properties_.requiredSubgroupSizeStages) ==
1568 0) {
1569 return false;
1570 }
1571 if (required_subgroup_size == 0 ||
1572 required_subgroup_size <
1573 subgroup_size_control_properties_.minSubgroupSize ||
1574 required_subgroup_size >
1575 subgroup_size_control_properties_.maxSubgroupSize) {
1576 return false;
1577 }
1578
1579 return true;
1580 }
1581
GetMinSubgroupSize() const1582 uint32_t Device::GetMinSubgroupSize() const {
1583 return subgroup_size_control_properties_.minSubgroupSize;
1584 }
1585
GetMaxSubgroupSize() const1586 uint32_t Device::GetMaxSubgroupSize() const {
1587 return subgroup_size_control_properties_.maxSubgroupSize;
1588 }
1589
GetRayTracingShaderGroupHandleSize() const1590 uint32_t Device::GetRayTracingShaderGroupHandleSize() const {
1591 return shader_group_handle_size_;
1592 }
1593
1594 } // namespace vulkan
1595 } // namespace amber
1596