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