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