1e5c31af7Sopenharmony_ci// Copyright 2019 The Amber Authors.
2e5c31af7Sopenharmony_ci//
3e5c31af7Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4e5c31af7Sopenharmony_ci// you may not use this file except in compliance with the License.
5e5c31af7Sopenharmony_ci// You may obtain a copy of the License at
6e5c31af7Sopenharmony_ci//
7e5c31af7Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8e5c31af7Sopenharmony_ci//
9e5c31af7Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10e5c31af7Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11e5c31af7Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e5c31af7Sopenharmony_ci// See the License for the specific language governing permissions and
13e5c31af7Sopenharmony_ci// limitations under the License.
14e5c31af7Sopenharmony_ci
15e5c31af7Sopenharmony_ci#include "samples/config_helper_vulkan.h"
16e5c31af7Sopenharmony_ci
17e5c31af7Sopenharmony_ci#include <vulkan/vulkan.h>
18e5c31af7Sopenharmony_ci
19e5c31af7Sopenharmony_ci#include <algorithm>
20e5c31af7Sopenharmony_ci#include <cstring>
21e5c31af7Sopenharmony_ci#include <iostream>
22e5c31af7Sopenharmony_ci#include <iterator>
23e5c31af7Sopenharmony_ci#include <set>
24e5c31af7Sopenharmony_ci#include <sstream>
25e5c31af7Sopenharmony_ci#include <utility>
26e5c31af7Sopenharmony_ci
27e5c31af7Sopenharmony_ci#include "samples/log.h"
28e5c31af7Sopenharmony_ci
29e5c31af7Sopenharmony_cinamespace sample {
30e5c31af7Sopenharmony_cinamespace {
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ciconst char* const kRequiredValidationLayers[] = {
33e5c31af7Sopenharmony_ci#ifdef __ANDROID__
34e5c31af7Sopenharmony_ci    // Note that the order of enabled layers is important. It is
35e5c31af7Sopenharmony_ci    // based on Android NDK Vulkan document.
36e5c31af7Sopenharmony_ci    "VK_LAYER_GOOGLE_threading",      "VK_LAYER_LUNARG_parameter_validation",
37e5c31af7Sopenharmony_ci    "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation",
38e5c31af7Sopenharmony_ci    "VK_LAYER_GOOGLE_unique_objects",
39e5c31af7Sopenharmony_ci#else   // __ANDROID__
40e5c31af7Sopenharmony_ci    "VK_LAYER_KHRONOS_validation",
41e5c31af7Sopenharmony_ci#endif  // __ANDROID__
42e5c31af7Sopenharmony_ci};
43e5c31af7Sopenharmony_ci
44e5c31af7Sopenharmony_ciconst size_t kNumberOfRequiredValidationLayers =
45e5c31af7Sopenharmony_ci    sizeof(kRequiredValidationLayers) / sizeof(const char*);
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_ciconst char kVariablePointers[] = "VariablePointerFeatures.variablePointers";
48e5c31af7Sopenharmony_ciconst char kVariablePointersStorageBuffer[] =
49e5c31af7Sopenharmony_ci    "VariablePointerFeatures.variablePointersStorageBuffer";
50e5c31af7Sopenharmony_ciconst char kFloat16Int8_Float16[] = "Float16Int8Features.shaderFloat16";
51e5c31af7Sopenharmony_ciconst char kFloat16Int8_Int8[] = "Float16Int8Features.shaderInt8";
52e5c31af7Sopenharmony_ciconst char k8BitStorage_Storage[] =
53e5c31af7Sopenharmony_ci    "Storage8BitFeatures.storageBuffer8BitAccess";
54e5c31af7Sopenharmony_ciconst char k8BitStorage_UniformAndStorage[] =
55e5c31af7Sopenharmony_ci    "Storage8BitFeatures.uniformAndStorageBuffer8BitAccess";
56e5c31af7Sopenharmony_ciconst char k8BitStorage_PushConstant[] =
57e5c31af7Sopenharmony_ci    "Storage8BitFeatures.storagePushConstant8";
58e5c31af7Sopenharmony_ciconst char k16BitStorage_Storage[] =
59e5c31af7Sopenharmony_ci    "Storage16BitFeatures.storageBuffer16BitAccess";
60e5c31af7Sopenharmony_ciconst char k16BitStorage_UniformAndStorage[] =
61e5c31af7Sopenharmony_ci    "Storage16BitFeatures.uniformAndStorageBuffer16BitAccess";
62e5c31af7Sopenharmony_ciconst char k16BitStorage_PushConstant[] =
63e5c31af7Sopenharmony_ci    "Storage16BitFeatures.storagePushConstant16";
64e5c31af7Sopenharmony_ciconst char k16BitStorage_InputOutput[] =
65e5c31af7Sopenharmony_ci    "Storage16BitFeatures.storageInputOutput16";
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ciconst char kSubgroupSizeControl[] = "SubgroupSizeControl.subgroupSizeControl";
68e5c31af7Sopenharmony_ciconst char kComputeFullSubgroups[] = "SubgroupSizeControl.computeFullSubgroups";
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_ciconst char kShaderSubgroupExtendedTypes[] =
71e5c31af7Sopenharmony_ci    "ShaderSubgroupExtendedTypesFeatures.shaderSubgroupExtendedTypes";
72e5c31af7Sopenharmony_ci
73e5c31af7Sopenharmony_ciconst char kExtensionForValidationLayer[] = "VK_EXT_debug_report";
74e5c31af7Sopenharmony_ci
75e5c31af7Sopenharmony_ciVKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugReportFlagsEXT flag,
76e5c31af7Sopenharmony_ci                                             VkDebugReportObjectTypeEXT,
77e5c31af7Sopenharmony_ci                                             uint64_t,
78e5c31af7Sopenharmony_ci                                             size_t,
79e5c31af7Sopenharmony_ci                                             int32_t,
80e5c31af7Sopenharmony_ci                                             const char* layerPrefix,
81e5c31af7Sopenharmony_ci                                             const char* msg,
82e5c31af7Sopenharmony_ci                                             void*) {
83e5c31af7Sopenharmony_ci  std::string flag_message;
84e5c31af7Sopenharmony_ci  switch (flag) {
85e5c31af7Sopenharmony_ci    case VK_DEBUG_REPORT_ERROR_BIT_EXT:
86e5c31af7Sopenharmony_ci      flag_message = "[ERROR]";
87e5c31af7Sopenharmony_ci      break;
88e5c31af7Sopenharmony_ci    case VK_DEBUG_REPORT_WARNING_BIT_EXT:
89e5c31af7Sopenharmony_ci      flag_message = "[WARNING]";
90e5c31af7Sopenharmony_ci      break;
91e5c31af7Sopenharmony_ci    default:
92e5c31af7Sopenharmony_ci      flag_message = "[UNKNOWN]";
93e5c31af7Sopenharmony_ci      break;
94e5c31af7Sopenharmony_ci  }
95e5c31af7Sopenharmony_ci
96e5c31af7Sopenharmony_ci  LogError(flag_message + " validation layer (" + layerPrefix + "):\n" + msg);
97e5c31af7Sopenharmony_ci  return VK_FALSE;
98e5c31af7Sopenharmony_ci}
99e5c31af7Sopenharmony_ci
100e5c31af7Sopenharmony_ci// Convert required features given as a string array to
101e5c31af7Sopenharmony_ci// VkPhysicalDeviceFeatures.
102e5c31af7Sopenharmony_ciamber::Result NamesToVulkanFeatures(
103e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_feature_names,
104e5c31af7Sopenharmony_ci    VkPhysicalDeviceFeatures* features) {
105e5c31af7Sopenharmony_ci  for (const auto& name : required_feature_names) {
106e5c31af7Sopenharmony_ci    if (name == "robustBufferAccess") {
107e5c31af7Sopenharmony_ci      features->robustBufferAccess = VK_TRUE;
108e5c31af7Sopenharmony_ci    } else if (name == "fullDrawIndexUint32") {
109e5c31af7Sopenharmony_ci      features->fullDrawIndexUint32 = VK_TRUE;
110e5c31af7Sopenharmony_ci    } else if (name == "imageCubeArray") {
111e5c31af7Sopenharmony_ci      features->imageCubeArray = VK_TRUE;
112e5c31af7Sopenharmony_ci    } else if (name == "independentBlend") {
113e5c31af7Sopenharmony_ci      features->independentBlend = VK_TRUE;
114e5c31af7Sopenharmony_ci    } else if (name == "geometryShader") {
115e5c31af7Sopenharmony_ci      features->geometryShader = VK_TRUE;
116e5c31af7Sopenharmony_ci    } else if (name == "tessellationShader") {
117e5c31af7Sopenharmony_ci      features->tessellationShader = VK_TRUE;
118e5c31af7Sopenharmony_ci    } else if (name == "sampleRateShading") {
119e5c31af7Sopenharmony_ci      features->sampleRateShading = VK_TRUE;
120e5c31af7Sopenharmony_ci    } else if (name == "dualSrcBlend") {
121e5c31af7Sopenharmony_ci      features->dualSrcBlend = VK_TRUE;
122e5c31af7Sopenharmony_ci    } else if (name == "logicOp") {
123e5c31af7Sopenharmony_ci      features->logicOp = VK_TRUE;
124e5c31af7Sopenharmony_ci    } else if (name == "multiDrawIndirect") {
125e5c31af7Sopenharmony_ci      features->multiDrawIndirect = VK_TRUE;
126e5c31af7Sopenharmony_ci    } else if (name == "drawIndirectFirstInstance") {
127e5c31af7Sopenharmony_ci      features->drawIndirectFirstInstance = VK_TRUE;
128e5c31af7Sopenharmony_ci    } else if (name == "depthClamp") {
129e5c31af7Sopenharmony_ci      features->depthClamp = VK_TRUE;
130e5c31af7Sopenharmony_ci    } else if (name == "depthBiasClamp") {
131e5c31af7Sopenharmony_ci      features->depthBiasClamp = VK_TRUE;
132e5c31af7Sopenharmony_ci    } else if (name == "fillModeNonSolid") {
133e5c31af7Sopenharmony_ci      features->fillModeNonSolid = VK_TRUE;
134e5c31af7Sopenharmony_ci    } else if (name == "depthBounds") {
135e5c31af7Sopenharmony_ci      features->depthBounds = VK_TRUE;
136e5c31af7Sopenharmony_ci    } else if (name == "wideLines") {
137e5c31af7Sopenharmony_ci      features->wideLines = VK_TRUE;
138e5c31af7Sopenharmony_ci    } else if (name == "largePoints") {
139e5c31af7Sopenharmony_ci      features->largePoints = VK_TRUE;
140e5c31af7Sopenharmony_ci    } else if (name == "alphaToOne") {
141e5c31af7Sopenharmony_ci      features->alphaToOne = VK_TRUE;
142e5c31af7Sopenharmony_ci    } else if (name == "multiViewport") {
143e5c31af7Sopenharmony_ci      features->multiViewport = VK_TRUE;
144e5c31af7Sopenharmony_ci    } else if (name == "samplerAnisotropy") {
145e5c31af7Sopenharmony_ci      features->samplerAnisotropy = VK_TRUE;
146e5c31af7Sopenharmony_ci    } else if (name == "textureCompressionETC2") {
147e5c31af7Sopenharmony_ci      features->textureCompressionETC2 = VK_TRUE;
148e5c31af7Sopenharmony_ci    } else if (name == "textureCompressionASTC_LDR") {
149e5c31af7Sopenharmony_ci      features->textureCompressionASTC_LDR = VK_TRUE;
150e5c31af7Sopenharmony_ci    } else if (name == "textureCompressionBC") {
151e5c31af7Sopenharmony_ci      features->textureCompressionBC = VK_TRUE;
152e5c31af7Sopenharmony_ci    } else if (name == "occlusionQueryPrecise") {
153e5c31af7Sopenharmony_ci      features->occlusionQueryPrecise = VK_TRUE;
154e5c31af7Sopenharmony_ci    } else if (name == "pipelineStatisticsQuery") {
155e5c31af7Sopenharmony_ci      features->pipelineStatisticsQuery = VK_TRUE;
156e5c31af7Sopenharmony_ci    } else if (name == "vertexPipelineStoresAndAtomics") {
157e5c31af7Sopenharmony_ci      features->vertexPipelineStoresAndAtomics = VK_TRUE;
158e5c31af7Sopenharmony_ci    } else if (name == "fragmentStoresAndAtomics") {
159e5c31af7Sopenharmony_ci      features->fragmentStoresAndAtomics = VK_TRUE;
160e5c31af7Sopenharmony_ci    } else if (name == "shaderTessellationAndGeometryPointSize") {
161e5c31af7Sopenharmony_ci      features->shaderTessellationAndGeometryPointSize = VK_TRUE;
162e5c31af7Sopenharmony_ci    } else if (name == "shaderImageGatherExtended") {
163e5c31af7Sopenharmony_ci      features->shaderImageGatherExtended = VK_TRUE;
164e5c31af7Sopenharmony_ci    } else if (name == "shaderStorageImageExtendedFormats") {
165e5c31af7Sopenharmony_ci      features->shaderStorageImageExtendedFormats = VK_TRUE;
166e5c31af7Sopenharmony_ci    } else if (name == "shaderStorageImageMultisample") {
167e5c31af7Sopenharmony_ci      features->shaderStorageImageMultisample = VK_TRUE;
168e5c31af7Sopenharmony_ci    } else if (name == "shaderStorageImageReadWithoutFormat") {
169e5c31af7Sopenharmony_ci      features->shaderStorageImageReadWithoutFormat = VK_TRUE;
170e5c31af7Sopenharmony_ci    } else if (name == "shaderStorageImageWriteWithoutFormat") {
171e5c31af7Sopenharmony_ci      features->shaderStorageImageWriteWithoutFormat = VK_TRUE;
172e5c31af7Sopenharmony_ci    } else if (name == "shaderUniformBufferArrayDynamicIndexing") {
173e5c31af7Sopenharmony_ci      features->shaderUniformBufferArrayDynamicIndexing = VK_TRUE;
174e5c31af7Sopenharmony_ci    } else if (name == "shaderSampledImageArrayDynamicIndexing") {
175e5c31af7Sopenharmony_ci      features->shaderSampledImageArrayDynamicIndexing = VK_TRUE;
176e5c31af7Sopenharmony_ci    } else if (name == "shaderStorageBufferArrayDynamicIndexing") {
177e5c31af7Sopenharmony_ci      features->shaderStorageBufferArrayDynamicIndexing = VK_TRUE;
178e5c31af7Sopenharmony_ci    } else if (name == "shaderStorageImageArrayDynamicIndexing") {
179e5c31af7Sopenharmony_ci      features->shaderStorageImageArrayDynamicIndexing = VK_TRUE;
180e5c31af7Sopenharmony_ci    } else if (name == "shaderClipDistance") {
181e5c31af7Sopenharmony_ci      features->shaderClipDistance = VK_TRUE;
182e5c31af7Sopenharmony_ci    } else if (name == "shaderCullDistance") {
183e5c31af7Sopenharmony_ci      features->shaderCullDistance = VK_TRUE;
184e5c31af7Sopenharmony_ci    } else if (name == "shaderFloat64") {
185e5c31af7Sopenharmony_ci      features->shaderFloat64 = VK_TRUE;
186e5c31af7Sopenharmony_ci    } else if (name == "shaderInt64") {
187e5c31af7Sopenharmony_ci      features->shaderInt64 = VK_TRUE;
188e5c31af7Sopenharmony_ci    } else if (name == "shaderInt16") {
189e5c31af7Sopenharmony_ci      features->shaderInt16 = VK_TRUE;
190e5c31af7Sopenharmony_ci    } else if (name == "shaderResourceResidency") {
191e5c31af7Sopenharmony_ci      features->shaderResourceResidency = VK_TRUE;
192e5c31af7Sopenharmony_ci    } else if (name == "shaderResourceMinLod") {
193e5c31af7Sopenharmony_ci      features->shaderResourceMinLod = VK_TRUE;
194e5c31af7Sopenharmony_ci    } else if (name == "sparseBinding") {
195e5c31af7Sopenharmony_ci      features->sparseBinding = VK_TRUE;
196e5c31af7Sopenharmony_ci    } else if (name == "sparseResidencyBuffer") {
197e5c31af7Sopenharmony_ci      features->sparseResidencyBuffer = VK_TRUE;
198e5c31af7Sopenharmony_ci    } else if (name == "sparseResidencyImage2D") {
199e5c31af7Sopenharmony_ci      features->sparseResidencyImage2D = VK_TRUE;
200e5c31af7Sopenharmony_ci    } else if (name == "sparseResidencyImage3D") {
201e5c31af7Sopenharmony_ci      features->sparseResidencyImage3D = VK_TRUE;
202e5c31af7Sopenharmony_ci    } else if (name == "sparseResidency2Samples") {
203e5c31af7Sopenharmony_ci      features->sparseResidency2Samples = VK_TRUE;
204e5c31af7Sopenharmony_ci    } else if (name == "sparseResidency4Samples") {
205e5c31af7Sopenharmony_ci      features->sparseResidency4Samples = VK_TRUE;
206e5c31af7Sopenharmony_ci    } else if (name == "sparseResidency8Samples") {
207e5c31af7Sopenharmony_ci      features->sparseResidency8Samples = VK_TRUE;
208e5c31af7Sopenharmony_ci    } else if (name == "sparseResidency16Samples") {
209e5c31af7Sopenharmony_ci      features->sparseResidency16Samples = VK_TRUE;
210e5c31af7Sopenharmony_ci    } else if (name == "sparseResidencyAliased") {
211e5c31af7Sopenharmony_ci      features->sparseResidencyAliased = VK_TRUE;
212e5c31af7Sopenharmony_ci    } else if (name == "variableMultisampleRate") {
213e5c31af7Sopenharmony_ci      features->variableMultisampleRate = VK_TRUE;
214e5c31af7Sopenharmony_ci    } else if (name == "inheritedQueries") {
215e5c31af7Sopenharmony_ci      features->inheritedQueries = VK_TRUE;
216e5c31af7Sopenharmony_ci    } else {
217e5c31af7Sopenharmony_ci      return amber::Result("Sample: Unknown Vulkan feature: " + name);
218e5c31af7Sopenharmony_ci    }
219e5c31af7Sopenharmony_ci  }
220e5c31af7Sopenharmony_ci  return {};
221e5c31af7Sopenharmony_ci}
222e5c31af7Sopenharmony_ci
223e5c31af7Sopenharmony_cibool AreAllValidationLayersSupported() {
224e5c31af7Sopenharmony_ci  std::vector<VkLayerProperties> available_layer_properties;
225e5c31af7Sopenharmony_ci  uint32_t available_layer_count = 0;
226e5c31af7Sopenharmony_ci  if (vkEnumerateInstanceLayerProperties(&available_layer_count, nullptr) !=
227e5c31af7Sopenharmony_ci      VK_SUCCESS) {
228e5c31af7Sopenharmony_ci    return false;
229e5c31af7Sopenharmony_ci  }
230e5c31af7Sopenharmony_ci  available_layer_properties.resize(available_layer_count);
231e5c31af7Sopenharmony_ci  if (vkEnumerateInstanceLayerProperties(&available_layer_count,
232e5c31af7Sopenharmony_ci                                         available_layer_properties.data()) !=
233e5c31af7Sopenharmony_ci      VK_SUCCESS) {
234e5c31af7Sopenharmony_ci    return false;
235e5c31af7Sopenharmony_ci  }
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ci  std::set<std::string> required_layer_set(
238e5c31af7Sopenharmony_ci      kRequiredValidationLayers,
239e5c31af7Sopenharmony_ci      &kRequiredValidationLayers[kNumberOfRequiredValidationLayers]);
240e5c31af7Sopenharmony_ci  for (const auto& property : available_layer_properties) {
241e5c31af7Sopenharmony_ci    required_layer_set.erase(property.layerName);
242e5c31af7Sopenharmony_ci  }
243e5c31af7Sopenharmony_ci
244e5c31af7Sopenharmony_ci  if (required_layer_set.empty())
245e5c31af7Sopenharmony_ci    return true;
246e5c31af7Sopenharmony_ci
247e5c31af7Sopenharmony_ci  std::string missing_layers;
248e5c31af7Sopenharmony_ci  for (const auto& missing_layer : required_layer_set)
249e5c31af7Sopenharmony_ci    missing_layers = missing_layers + missing_layer + ",\n\t\t";
250e5c31af7Sopenharmony_ci  LogError("Vulkan: missing validation layers:\n\t\t" + missing_layers);
251e5c31af7Sopenharmony_ci  return true;
252e5c31af7Sopenharmony_ci}
253e5c31af7Sopenharmony_ci
254e5c31af7Sopenharmony_cibool AreAllValidationExtensionsSupported() {
255e5c31af7Sopenharmony_ci  for (const auto& layer : kRequiredValidationLayers) {
256e5c31af7Sopenharmony_ci    uint32_t available_extension_count = 0;
257e5c31af7Sopenharmony_ci    std::vector<VkExtensionProperties> extension_properties;
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_ci    if (vkEnumerateInstanceExtensionProperties(
260e5c31af7Sopenharmony_ci            layer, &available_extension_count, nullptr) != VK_SUCCESS) {
261e5c31af7Sopenharmony_ci      return false;
262e5c31af7Sopenharmony_ci    }
263e5c31af7Sopenharmony_ci    extension_properties.resize(available_extension_count);
264e5c31af7Sopenharmony_ci    if (vkEnumerateInstanceExtensionProperties(
265e5c31af7Sopenharmony_ci            layer, &available_extension_count, extension_properties.data()) !=
266e5c31af7Sopenharmony_ci        VK_SUCCESS) {
267e5c31af7Sopenharmony_ci      return false;
268e5c31af7Sopenharmony_ci    }
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_ci    for (const auto& ext : extension_properties) {
271e5c31af7Sopenharmony_ci      if (!strcmp(kExtensionForValidationLayer, ext.extensionName))
272e5c31af7Sopenharmony_ci        return true;
273e5c31af7Sopenharmony_ci    }
274e5c31af7Sopenharmony_ci  }
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_ci  return false;
277e5c31af7Sopenharmony_ci}
278e5c31af7Sopenharmony_ci
279e5c31af7Sopenharmony_ci// Check if |physical_device| supports all required features given
280e5c31af7Sopenharmony_ci// in |required_features|.
281e5c31af7Sopenharmony_cibool AreAllRequiredFeaturesSupported(
282e5c31af7Sopenharmony_ci    const VkPhysicalDeviceFeatures& available_features,
283e5c31af7Sopenharmony_ci    const VkPhysicalDeviceFeatures& required_features) {
284e5c31af7Sopenharmony_ci  if (available_features.robustBufferAccess == VK_FALSE &&
285e5c31af7Sopenharmony_ci      required_features.robustBufferAccess == VK_TRUE) {
286e5c31af7Sopenharmony_ci    return false;
287e5c31af7Sopenharmony_ci  }
288e5c31af7Sopenharmony_ci  if (available_features.fullDrawIndexUint32 == VK_FALSE &&
289e5c31af7Sopenharmony_ci      required_features.fullDrawIndexUint32 == VK_TRUE) {
290e5c31af7Sopenharmony_ci    return false;
291e5c31af7Sopenharmony_ci  }
292e5c31af7Sopenharmony_ci  if (available_features.imageCubeArray == VK_FALSE &&
293e5c31af7Sopenharmony_ci      required_features.imageCubeArray == VK_TRUE) {
294e5c31af7Sopenharmony_ci    return false;
295e5c31af7Sopenharmony_ci  }
296e5c31af7Sopenharmony_ci  if (available_features.independentBlend == VK_FALSE &&
297e5c31af7Sopenharmony_ci      required_features.independentBlend == VK_TRUE) {
298e5c31af7Sopenharmony_ci    return false;
299e5c31af7Sopenharmony_ci  }
300e5c31af7Sopenharmony_ci  if (available_features.geometryShader == VK_FALSE &&
301e5c31af7Sopenharmony_ci      required_features.geometryShader == VK_TRUE) {
302e5c31af7Sopenharmony_ci    return false;
303e5c31af7Sopenharmony_ci  }
304e5c31af7Sopenharmony_ci  if (available_features.tessellationShader == VK_FALSE &&
305e5c31af7Sopenharmony_ci      required_features.tessellationShader == VK_TRUE) {
306e5c31af7Sopenharmony_ci    return false;
307e5c31af7Sopenharmony_ci  }
308e5c31af7Sopenharmony_ci  if (available_features.sampleRateShading == VK_FALSE &&
309e5c31af7Sopenharmony_ci      required_features.sampleRateShading == VK_TRUE) {
310e5c31af7Sopenharmony_ci    return false;
311e5c31af7Sopenharmony_ci  }
312e5c31af7Sopenharmony_ci  if (available_features.dualSrcBlend == VK_FALSE &&
313e5c31af7Sopenharmony_ci      required_features.dualSrcBlend == VK_TRUE) {
314e5c31af7Sopenharmony_ci    return false;
315e5c31af7Sopenharmony_ci  }
316e5c31af7Sopenharmony_ci  if (available_features.logicOp == VK_FALSE &&
317e5c31af7Sopenharmony_ci      required_features.logicOp == VK_TRUE) {
318e5c31af7Sopenharmony_ci    return false;
319e5c31af7Sopenharmony_ci  }
320e5c31af7Sopenharmony_ci  if (available_features.multiDrawIndirect == VK_FALSE &&
321e5c31af7Sopenharmony_ci      required_features.multiDrawIndirect == VK_TRUE) {
322e5c31af7Sopenharmony_ci    return false;
323e5c31af7Sopenharmony_ci  }
324e5c31af7Sopenharmony_ci  if (available_features.drawIndirectFirstInstance == VK_FALSE &&
325e5c31af7Sopenharmony_ci      required_features.drawIndirectFirstInstance == VK_TRUE) {
326e5c31af7Sopenharmony_ci    return false;
327e5c31af7Sopenharmony_ci  }
328e5c31af7Sopenharmony_ci  if (available_features.depthClamp == VK_FALSE &&
329e5c31af7Sopenharmony_ci      required_features.depthClamp == VK_TRUE) {
330e5c31af7Sopenharmony_ci    return false;
331e5c31af7Sopenharmony_ci  }
332e5c31af7Sopenharmony_ci  if (available_features.depthBiasClamp == VK_FALSE &&
333e5c31af7Sopenharmony_ci      required_features.depthBiasClamp == VK_TRUE) {
334e5c31af7Sopenharmony_ci    return false;
335e5c31af7Sopenharmony_ci  }
336e5c31af7Sopenharmony_ci  if (available_features.fillModeNonSolid == VK_FALSE &&
337e5c31af7Sopenharmony_ci      required_features.fillModeNonSolid == VK_TRUE) {
338e5c31af7Sopenharmony_ci    return false;
339e5c31af7Sopenharmony_ci  }
340e5c31af7Sopenharmony_ci  if (available_features.depthBounds == VK_FALSE &&
341e5c31af7Sopenharmony_ci      required_features.depthBounds == VK_TRUE) {
342e5c31af7Sopenharmony_ci    return false;
343e5c31af7Sopenharmony_ci  }
344e5c31af7Sopenharmony_ci  if (available_features.wideLines == VK_FALSE &&
345e5c31af7Sopenharmony_ci      required_features.wideLines == VK_TRUE) {
346e5c31af7Sopenharmony_ci    return false;
347e5c31af7Sopenharmony_ci  }
348e5c31af7Sopenharmony_ci  if (available_features.largePoints == VK_FALSE &&
349e5c31af7Sopenharmony_ci      required_features.largePoints == VK_TRUE) {
350e5c31af7Sopenharmony_ci    return false;
351e5c31af7Sopenharmony_ci  }
352e5c31af7Sopenharmony_ci  if (available_features.alphaToOne == VK_FALSE &&
353e5c31af7Sopenharmony_ci      required_features.alphaToOne == VK_TRUE) {
354e5c31af7Sopenharmony_ci    return false;
355e5c31af7Sopenharmony_ci  }
356e5c31af7Sopenharmony_ci  if (available_features.multiViewport == VK_FALSE &&
357e5c31af7Sopenharmony_ci      required_features.multiViewport == VK_TRUE) {
358e5c31af7Sopenharmony_ci    return false;
359e5c31af7Sopenharmony_ci  }
360e5c31af7Sopenharmony_ci  if (available_features.samplerAnisotropy == VK_FALSE &&
361e5c31af7Sopenharmony_ci      required_features.samplerAnisotropy == VK_TRUE) {
362e5c31af7Sopenharmony_ci    return false;
363e5c31af7Sopenharmony_ci  }
364e5c31af7Sopenharmony_ci  if (available_features.textureCompressionETC2 == VK_FALSE &&
365e5c31af7Sopenharmony_ci      required_features.textureCompressionETC2 == VK_TRUE) {
366e5c31af7Sopenharmony_ci    return false;
367e5c31af7Sopenharmony_ci  }
368e5c31af7Sopenharmony_ci  if (available_features.textureCompressionASTC_LDR == VK_FALSE &&
369e5c31af7Sopenharmony_ci      required_features.textureCompressionASTC_LDR == VK_TRUE) {
370e5c31af7Sopenharmony_ci    return false;
371e5c31af7Sopenharmony_ci  }
372e5c31af7Sopenharmony_ci  if (available_features.textureCompressionBC == VK_FALSE &&
373e5c31af7Sopenharmony_ci      required_features.textureCompressionBC == VK_TRUE) {
374e5c31af7Sopenharmony_ci    return false;
375e5c31af7Sopenharmony_ci  }
376e5c31af7Sopenharmony_ci  if (available_features.occlusionQueryPrecise == VK_FALSE &&
377e5c31af7Sopenharmony_ci      required_features.occlusionQueryPrecise == VK_TRUE) {
378e5c31af7Sopenharmony_ci    return false;
379e5c31af7Sopenharmony_ci  }
380e5c31af7Sopenharmony_ci  if (available_features.pipelineStatisticsQuery == VK_FALSE &&
381e5c31af7Sopenharmony_ci      required_features.pipelineStatisticsQuery == VK_TRUE) {
382e5c31af7Sopenharmony_ci    return false;
383e5c31af7Sopenharmony_ci  }
384e5c31af7Sopenharmony_ci  if (available_features.vertexPipelineStoresAndAtomics == VK_FALSE &&
385e5c31af7Sopenharmony_ci      required_features.vertexPipelineStoresAndAtomics == VK_TRUE) {
386e5c31af7Sopenharmony_ci    return false;
387e5c31af7Sopenharmony_ci  }
388e5c31af7Sopenharmony_ci  if (available_features.fragmentStoresAndAtomics == VK_FALSE &&
389e5c31af7Sopenharmony_ci      required_features.fragmentStoresAndAtomics == VK_TRUE) {
390e5c31af7Sopenharmony_ci    return false;
391e5c31af7Sopenharmony_ci  }
392e5c31af7Sopenharmony_ci  if (available_features.shaderTessellationAndGeometryPointSize == VK_FALSE &&
393e5c31af7Sopenharmony_ci      required_features.shaderTessellationAndGeometryPointSize == VK_TRUE) {
394e5c31af7Sopenharmony_ci    return false;
395e5c31af7Sopenharmony_ci  }
396e5c31af7Sopenharmony_ci  if (available_features.shaderImageGatherExtended == VK_FALSE &&
397e5c31af7Sopenharmony_ci      required_features.shaderImageGatherExtended == VK_TRUE) {
398e5c31af7Sopenharmony_ci    return false;
399e5c31af7Sopenharmony_ci  }
400e5c31af7Sopenharmony_ci  if (available_features.shaderStorageImageExtendedFormats == VK_FALSE &&
401e5c31af7Sopenharmony_ci      required_features.shaderStorageImageExtendedFormats == VK_TRUE) {
402e5c31af7Sopenharmony_ci    return false;
403e5c31af7Sopenharmony_ci  }
404e5c31af7Sopenharmony_ci  if (available_features.shaderStorageImageMultisample == VK_FALSE &&
405e5c31af7Sopenharmony_ci      required_features.shaderStorageImageMultisample == VK_TRUE) {
406e5c31af7Sopenharmony_ci    return false;
407e5c31af7Sopenharmony_ci  }
408e5c31af7Sopenharmony_ci  if (available_features.shaderStorageImageReadWithoutFormat == VK_FALSE &&
409e5c31af7Sopenharmony_ci      required_features.shaderStorageImageReadWithoutFormat == VK_TRUE) {
410e5c31af7Sopenharmony_ci    return false;
411e5c31af7Sopenharmony_ci  }
412e5c31af7Sopenharmony_ci  if (available_features.shaderStorageImageWriteWithoutFormat == VK_FALSE &&
413e5c31af7Sopenharmony_ci      required_features.shaderStorageImageWriteWithoutFormat == VK_TRUE) {
414e5c31af7Sopenharmony_ci    return false;
415e5c31af7Sopenharmony_ci  }
416e5c31af7Sopenharmony_ci  if (available_features.shaderUniformBufferArrayDynamicIndexing == VK_FALSE &&
417e5c31af7Sopenharmony_ci      required_features.shaderUniformBufferArrayDynamicIndexing == VK_TRUE) {
418e5c31af7Sopenharmony_ci    return false;
419e5c31af7Sopenharmony_ci  }
420e5c31af7Sopenharmony_ci  if (available_features.shaderSampledImageArrayDynamicIndexing == VK_FALSE &&
421e5c31af7Sopenharmony_ci      required_features.shaderSampledImageArrayDynamicIndexing == VK_TRUE) {
422e5c31af7Sopenharmony_ci    return false;
423e5c31af7Sopenharmony_ci  }
424e5c31af7Sopenharmony_ci  if (available_features.shaderStorageBufferArrayDynamicIndexing == VK_FALSE &&
425e5c31af7Sopenharmony_ci      required_features.shaderStorageBufferArrayDynamicIndexing == VK_TRUE) {
426e5c31af7Sopenharmony_ci    return false;
427e5c31af7Sopenharmony_ci  }
428e5c31af7Sopenharmony_ci  if (available_features.shaderStorageImageArrayDynamicIndexing == VK_FALSE &&
429e5c31af7Sopenharmony_ci      required_features.shaderStorageImageArrayDynamicIndexing == VK_TRUE) {
430e5c31af7Sopenharmony_ci    return false;
431e5c31af7Sopenharmony_ci  }
432e5c31af7Sopenharmony_ci  if (available_features.shaderClipDistance == VK_FALSE &&
433e5c31af7Sopenharmony_ci      required_features.shaderClipDistance == VK_TRUE) {
434e5c31af7Sopenharmony_ci    return false;
435e5c31af7Sopenharmony_ci  }
436e5c31af7Sopenharmony_ci  if (available_features.shaderCullDistance == VK_FALSE &&
437e5c31af7Sopenharmony_ci      required_features.shaderCullDistance == VK_TRUE) {
438e5c31af7Sopenharmony_ci    return false;
439e5c31af7Sopenharmony_ci  }
440e5c31af7Sopenharmony_ci  if (available_features.shaderFloat64 == VK_FALSE &&
441e5c31af7Sopenharmony_ci      required_features.shaderFloat64 == VK_TRUE) {
442e5c31af7Sopenharmony_ci    return false;
443e5c31af7Sopenharmony_ci  }
444e5c31af7Sopenharmony_ci  if (available_features.shaderInt64 == VK_FALSE &&
445e5c31af7Sopenharmony_ci      required_features.shaderInt64 == VK_TRUE) {
446e5c31af7Sopenharmony_ci    return false;
447e5c31af7Sopenharmony_ci  }
448e5c31af7Sopenharmony_ci  if (available_features.shaderInt16 == VK_FALSE &&
449e5c31af7Sopenharmony_ci      required_features.shaderInt16 == VK_TRUE) {
450e5c31af7Sopenharmony_ci    return false;
451e5c31af7Sopenharmony_ci  }
452e5c31af7Sopenharmony_ci  if (available_features.shaderResourceResidency == VK_FALSE &&
453e5c31af7Sopenharmony_ci      required_features.shaderResourceResidency == VK_TRUE) {
454e5c31af7Sopenharmony_ci    return false;
455e5c31af7Sopenharmony_ci  }
456e5c31af7Sopenharmony_ci  if (available_features.shaderResourceMinLod == VK_FALSE &&
457e5c31af7Sopenharmony_ci      required_features.shaderResourceMinLod == VK_TRUE) {
458e5c31af7Sopenharmony_ci    return false;
459e5c31af7Sopenharmony_ci  }
460e5c31af7Sopenharmony_ci  if (available_features.sparseBinding == VK_FALSE &&
461e5c31af7Sopenharmony_ci      required_features.sparseBinding == VK_TRUE) {
462e5c31af7Sopenharmony_ci    return false;
463e5c31af7Sopenharmony_ci  }
464e5c31af7Sopenharmony_ci  if (available_features.sparseResidencyBuffer == VK_FALSE &&
465e5c31af7Sopenharmony_ci      required_features.sparseResidencyBuffer == VK_TRUE) {
466e5c31af7Sopenharmony_ci    return false;
467e5c31af7Sopenharmony_ci  }
468e5c31af7Sopenharmony_ci  if (available_features.sparseResidencyImage2D == VK_FALSE &&
469e5c31af7Sopenharmony_ci      required_features.sparseResidencyImage2D == VK_TRUE) {
470e5c31af7Sopenharmony_ci    return false;
471e5c31af7Sopenharmony_ci  }
472e5c31af7Sopenharmony_ci  if (available_features.sparseResidencyImage3D == VK_FALSE &&
473e5c31af7Sopenharmony_ci      required_features.sparseResidencyImage3D == VK_TRUE) {
474e5c31af7Sopenharmony_ci    return false;
475e5c31af7Sopenharmony_ci  }
476e5c31af7Sopenharmony_ci  if (available_features.sparseResidency2Samples == VK_FALSE &&
477e5c31af7Sopenharmony_ci      required_features.sparseResidency2Samples == VK_TRUE) {
478e5c31af7Sopenharmony_ci    return false;
479e5c31af7Sopenharmony_ci  }
480e5c31af7Sopenharmony_ci  if (available_features.sparseResidency4Samples == VK_FALSE &&
481e5c31af7Sopenharmony_ci      required_features.sparseResidency4Samples == VK_TRUE) {
482e5c31af7Sopenharmony_ci    return false;
483e5c31af7Sopenharmony_ci  }
484e5c31af7Sopenharmony_ci  if (available_features.sparseResidency8Samples == VK_FALSE &&
485e5c31af7Sopenharmony_ci      required_features.sparseResidency8Samples == VK_TRUE) {
486e5c31af7Sopenharmony_ci    return false;
487e5c31af7Sopenharmony_ci  }
488e5c31af7Sopenharmony_ci  if (available_features.sparseResidency16Samples == VK_FALSE &&
489e5c31af7Sopenharmony_ci      required_features.sparseResidency16Samples == VK_TRUE) {
490e5c31af7Sopenharmony_ci    return false;
491e5c31af7Sopenharmony_ci  }
492e5c31af7Sopenharmony_ci  if (available_features.sparseResidencyAliased == VK_FALSE &&
493e5c31af7Sopenharmony_ci      required_features.sparseResidencyAliased == VK_TRUE) {
494e5c31af7Sopenharmony_ci    return false;
495e5c31af7Sopenharmony_ci  }
496e5c31af7Sopenharmony_ci  if (available_features.variableMultisampleRate == VK_FALSE &&
497e5c31af7Sopenharmony_ci      required_features.variableMultisampleRate == VK_TRUE) {
498e5c31af7Sopenharmony_ci    return false;
499e5c31af7Sopenharmony_ci  }
500e5c31af7Sopenharmony_ci  if (available_features.inheritedQueries == VK_FALSE &&
501e5c31af7Sopenharmony_ci      required_features.inheritedQueries == VK_TRUE) {
502e5c31af7Sopenharmony_ci    return false;
503e5c31af7Sopenharmony_ci  }
504e5c31af7Sopenharmony_ci  return true;
505e5c31af7Sopenharmony_ci}
506e5c31af7Sopenharmony_ci
507e5c31af7Sopenharmony_ci// Get all available instance extensions.
508e5c31af7Sopenharmony_cistd::vector<std::string> GetAvailableInstanceExtensions() {
509e5c31af7Sopenharmony_ci  std::vector<std::string> available_extensions;
510e5c31af7Sopenharmony_ci  uint32_t available_extension_count = 0;
511e5c31af7Sopenharmony_ci  std::vector<VkExtensionProperties> available_extension_properties;
512e5c31af7Sopenharmony_ci
513e5c31af7Sopenharmony_ci  if (vkEnumerateInstanceExtensionProperties(
514e5c31af7Sopenharmony_ci          nullptr, &available_extension_count, nullptr) != VK_SUCCESS) {
515e5c31af7Sopenharmony_ci    return available_extensions;
516e5c31af7Sopenharmony_ci  }
517e5c31af7Sopenharmony_ci
518e5c31af7Sopenharmony_ci  if (available_extension_count == 0)
519e5c31af7Sopenharmony_ci    return available_extensions;
520e5c31af7Sopenharmony_ci
521e5c31af7Sopenharmony_ci  available_extension_properties.resize(available_extension_count);
522e5c31af7Sopenharmony_ci  if (vkEnumerateInstanceExtensionProperties(
523e5c31af7Sopenharmony_ci          nullptr, &available_extension_count,
524e5c31af7Sopenharmony_ci          available_extension_properties.data()) != VK_SUCCESS) {
525e5c31af7Sopenharmony_ci    return available_extensions;
526e5c31af7Sopenharmony_ci  }
527e5c31af7Sopenharmony_ci
528e5c31af7Sopenharmony_ci  for (const auto& property : available_extension_properties)
529e5c31af7Sopenharmony_ci    available_extensions.push_back(property.extensionName);
530e5c31af7Sopenharmony_ci
531e5c31af7Sopenharmony_ci  return available_extensions;
532e5c31af7Sopenharmony_ci}
533e5c31af7Sopenharmony_ci
534e5c31af7Sopenharmony_ci// Get all available extensions of |physical_device|.
535e5c31af7Sopenharmony_cistd::vector<std::string> GetAvailableDeviceExtensions(
536e5c31af7Sopenharmony_ci    const VkPhysicalDevice& physical_device) {
537e5c31af7Sopenharmony_ci  std::vector<std::string> available_extensions;
538e5c31af7Sopenharmony_ci  uint32_t available_extension_count = 0;
539e5c31af7Sopenharmony_ci  std::vector<VkExtensionProperties> available_extension_properties;
540e5c31af7Sopenharmony_ci
541e5c31af7Sopenharmony_ci  if (vkEnumerateDeviceExtensionProperties(physical_device, nullptr,
542e5c31af7Sopenharmony_ci                                           &available_extension_count,
543e5c31af7Sopenharmony_ci                                           nullptr) != VK_SUCCESS) {
544e5c31af7Sopenharmony_ci    return available_extensions;
545e5c31af7Sopenharmony_ci  }
546e5c31af7Sopenharmony_ci
547e5c31af7Sopenharmony_ci  if (available_extension_count == 0)
548e5c31af7Sopenharmony_ci    return available_extensions;
549e5c31af7Sopenharmony_ci
550e5c31af7Sopenharmony_ci  available_extension_properties.resize(available_extension_count);
551e5c31af7Sopenharmony_ci  if (vkEnumerateDeviceExtensionProperties(
552e5c31af7Sopenharmony_ci          physical_device, nullptr, &available_extension_count,
553e5c31af7Sopenharmony_ci          available_extension_properties.data()) != VK_SUCCESS) {
554e5c31af7Sopenharmony_ci    return available_extensions;
555e5c31af7Sopenharmony_ci  }
556e5c31af7Sopenharmony_ci
557e5c31af7Sopenharmony_ci  for (const auto& property : available_extension_properties)
558e5c31af7Sopenharmony_ci    available_extensions.push_back(property.extensionName);
559e5c31af7Sopenharmony_ci
560e5c31af7Sopenharmony_ci  return available_extensions;
561e5c31af7Sopenharmony_ci}
562e5c31af7Sopenharmony_ci
563e5c31af7Sopenharmony_ci// Check if |physical_device| supports all required extensions given
564e5c31af7Sopenharmony_ci// in |required_extensions|.
565e5c31af7Sopenharmony_cibool AreAllExtensionsSupported(
566e5c31af7Sopenharmony_ci    const std::vector<std::string>& available_extensions,
567e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_extensions) {
568e5c31af7Sopenharmony_ci  if (required_extensions.empty())
569e5c31af7Sopenharmony_ci    return true;
570e5c31af7Sopenharmony_ci
571e5c31af7Sopenharmony_ci  std::set<std::string> required_extension_set(required_extensions.begin(),
572e5c31af7Sopenharmony_ci                                               required_extensions.end());
573e5c31af7Sopenharmony_ci  for (const auto& extension : available_extensions) {
574e5c31af7Sopenharmony_ci    required_extension_set.erase(extension);
575e5c31af7Sopenharmony_ci  }
576e5c31af7Sopenharmony_ci
577e5c31af7Sopenharmony_ci  return required_extension_set.empty();
578e5c31af7Sopenharmony_ci}
579e5c31af7Sopenharmony_ci
580e5c31af7Sopenharmony_ci// Check if |physical_device| supports both compute and graphics
581e5c31af7Sopenharmony_ci// pipelines.
582e5c31af7Sopenharmony_ciuint32_t ChooseQueueFamilyIndex(const VkPhysicalDevice& physical_device) {
583e5c31af7Sopenharmony_ci  uint32_t count = 0;
584e5c31af7Sopenharmony_ci  std::vector<VkQueueFamilyProperties> properties;
585e5c31af7Sopenharmony_ci
586e5c31af7Sopenharmony_ci  vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count, nullptr);
587e5c31af7Sopenharmony_ci  properties.resize(count);
588e5c31af7Sopenharmony_ci  vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &count,
589e5c31af7Sopenharmony_ci                                           properties.data());
590e5c31af7Sopenharmony_ci
591e5c31af7Sopenharmony_ci  for (uint32_t i = 0; i < count; ++i) {
592e5c31af7Sopenharmony_ci    if (properties[i].queueFlags &
593e5c31af7Sopenharmony_ci        (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)) {
594e5c31af7Sopenharmony_ci      return i;
595e5c31af7Sopenharmony_ci    }
596e5c31af7Sopenharmony_ci  }
597e5c31af7Sopenharmony_ci
598e5c31af7Sopenharmony_ci  return std::numeric_limits<uint32_t>::max();
599e5c31af7Sopenharmony_ci}
600e5c31af7Sopenharmony_ci
601e5c31af7Sopenharmony_cistd::string deviceTypeToName(VkPhysicalDeviceType type) {
602e5c31af7Sopenharmony_ci  switch (type) {
603e5c31af7Sopenharmony_ci    case VK_PHYSICAL_DEVICE_TYPE_OTHER:
604e5c31af7Sopenharmony_ci      return "other";
605e5c31af7Sopenharmony_ci    case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
606e5c31af7Sopenharmony_ci      return "integrated gpu";
607e5c31af7Sopenharmony_ci    case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
608e5c31af7Sopenharmony_ci      return "discrete gpu";
609e5c31af7Sopenharmony_ci    case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
610e5c31af7Sopenharmony_ci      return "virtual gpu";
611e5c31af7Sopenharmony_ci    case VK_PHYSICAL_DEVICE_TYPE_CPU:
612e5c31af7Sopenharmony_ci      return "cpu";
613e5c31af7Sopenharmony_ci    default:
614e5c31af7Sopenharmony_ci      break;
615e5c31af7Sopenharmony_ci  }
616e5c31af7Sopenharmony_ci  return "unknown";
617e5c31af7Sopenharmony_ci}
618e5c31af7Sopenharmony_ci
619e5c31af7Sopenharmony_cistd::string stageFlagBitsToNames(const VkShaderStageFlags bits) {
620e5c31af7Sopenharmony_ci  static const std::pair<VkShaderStageFlagBits, const char*> stages[] = {
621e5c31af7Sopenharmony_ci      std::make_pair(VK_SHADER_STAGE_VERTEX_BIT, "vert"),
622e5c31af7Sopenharmony_ci      std::make_pair(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tessc"),
623e5c31af7Sopenharmony_ci      std::make_pair(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "tesse"),
624e5c31af7Sopenharmony_ci      std::make_pair(VK_SHADER_STAGE_GEOMETRY_BIT, "geom"),
625e5c31af7Sopenharmony_ci      std::make_pair(VK_SHADER_STAGE_FRAGMENT_BIT, "frag"),
626e5c31af7Sopenharmony_ci      std::make_pair(VK_SHADER_STAGE_COMPUTE_BIT, "comp")};
627e5c31af7Sopenharmony_ci  std::ostringstream result;
628e5c31af7Sopenharmony_ci  bool addSeparator = false;
629e5c31af7Sopenharmony_ci  for (const auto& stage : stages) {
630e5c31af7Sopenharmony_ci    if ((bits & stage.first) != 0) {
631e5c31af7Sopenharmony_ci      if (addSeparator)
632e5c31af7Sopenharmony_ci        result << ", ";
633e5c31af7Sopenharmony_ci      result << stage.second;
634e5c31af7Sopenharmony_ci      addSeparator = true;
635e5c31af7Sopenharmony_ci    }
636e5c31af7Sopenharmony_ci  }
637e5c31af7Sopenharmony_ci  return result.str();
638e5c31af7Sopenharmony_ci}
639e5c31af7Sopenharmony_ci
640e5c31af7Sopenharmony_ci}  // namespace
641e5c31af7Sopenharmony_ci
642e5c31af7Sopenharmony_ciConfigHelperVulkan::ConfigHelperVulkan()
643e5c31af7Sopenharmony_ci    : available_features_(VkPhysicalDeviceFeatures()),
644e5c31af7Sopenharmony_ci      available_features2_(VkPhysicalDeviceFeatures2KHR()),
645e5c31af7Sopenharmony_ci      variable_pointers_feature_(VkPhysicalDeviceVariablePointerFeaturesKHR()),
646e5c31af7Sopenharmony_ci      float16_int8_feature_(VkPhysicalDeviceFloat16Int8FeaturesKHR()),
647e5c31af7Sopenharmony_ci      storage_8bit_feature_(VkPhysicalDevice8BitStorageFeaturesKHR()),
648e5c31af7Sopenharmony_ci      storage_16bit_feature_(VkPhysicalDevice16BitStorageFeaturesKHR()),
649e5c31af7Sopenharmony_ci      subgroup_size_control_feature_(
650e5c31af7Sopenharmony_ci          VkPhysicalDeviceSubgroupSizeControlFeaturesEXT()) {}
651e5c31af7Sopenharmony_ci
652e5c31af7Sopenharmony_ciConfigHelperVulkan::~ConfigHelperVulkan() {
653e5c31af7Sopenharmony_ci  if (vulkan_device_)
654e5c31af7Sopenharmony_ci    vkDestroyDevice(vulkan_device_, nullptr);
655e5c31af7Sopenharmony_ci
656e5c31af7Sopenharmony_ci  if (vulkan_callback_) {
657e5c31af7Sopenharmony_ci    auto vkDestroyDebugReportCallbackEXT =
658e5c31af7Sopenharmony_ci        reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
659e5c31af7Sopenharmony_ci            vkGetInstanceProcAddr(vulkan_instance_,
660e5c31af7Sopenharmony_ci                                  "vkDestroyDebugReportCallbackEXT"));
661e5c31af7Sopenharmony_ci    if (vkDestroyDebugReportCallbackEXT) {
662e5c31af7Sopenharmony_ci      vkDestroyDebugReportCallbackEXT(vulkan_instance_, vulkan_callback_,
663e5c31af7Sopenharmony_ci                                      nullptr);
664e5c31af7Sopenharmony_ci    }
665e5c31af7Sopenharmony_ci  }
666e5c31af7Sopenharmony_ci
667e5c31af7Sopenharmony_ci  if (vulkan_instance_)
668e5c31af7Sopenharmony_ci    vkDestroyInstance(vulkan_instance_, nullptr);
669e5c31af7Sopenharmony_ci}
670e5c31af7Sopenharmony_ci
671e5c31af7Sopenharmony_ciamber::Result ConfigHelperVulkan::CreateVulkanInstance(
672e5c31af7Sopenharmony_ci    uint32_t engine_major,
673e5c31af7Sopenharmony_ci    uint32_t engine_minor,
674e5c31af7Sopenharmony_ci    std::vector<std::string> required_extensions,
675e5c31af7Sopenharmony_ci    bool disable_validation_layer) {
676e5c31af7Sopenharmony_ci  VkApplicationInfo app_info = VkApplicationInfo();
677e5c31af7Sopenharmony_ci  app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
678e5c31af7Sopenharmony_ci
679e5c31af7Sopenharmony_ci#pragma clang diagnostic push
680e5c31af7Sopenharmony_ci#pragma clang diagnostic ignored "-Wold-style-cast"
681e5c31af7Sopenharmony_ci  app_info.apiVersion = VK_MAKE_VERSION(engine_major, engine_minor, 0);
682e5c31af7Sopenharmony_ci#pragma clang diagnostic pop
683e5c31af7Sopenharmony_ci
684e5c31af7Sopenharmony_ci  VkInstanceCreateInfo instance_info = VkInstanceCreateInfo();
685e5c31af7Sopenharmony_ci  instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
686e5c31af7Sopenharmony_ci  instance_info.pApplicationInfo = &app_info;
687e5c31af7Sopenharmony_ci
688e5c31af7Sopenharmony_ci  if (!disable_validation_layer) {
689e5c31af7Sopenharmony_ci    if (!AreAllValidationLayersSupported())
690e5c31af7Sopenharmony_ci      return amber::Result("Sample: not all validation layers are supported");
691e5c31af7Sopenharmony_ci    if (!AreAllValidationExtensionsSupported()) {
692e5c31af7Sopenharmony_ci      return amber::Result(
693e5c31af7Sopenharmony_ci          "Sample: extensions of validation layers are not supported");
694e5c31af7Sopenharmony_ci    }
695e5c31af7Sopenharmony_ci    instance_info.enabledLayerCount = kNumberOfRequiredValidationLayers;
696e5c31af7Sopenharmony_ci    instance_info.ppEnabledLayerNames = kRequiredValidationLayers;
697e5c31af7Sopenharmony_ci
698e5c31af7Sopenharmony_ci    required_extensions.push_back(kExtensionForValidationLayer);
699e5c31af7Sopenharmony_ci  }
700e5c31af7Sopenharmony_ci
701e5c31af7Sopenharmony_ci  available_instance_extensions_ = GetAvailableInstanceExtensions();
702e5c31af7Sopenharmony_ci  if (!required_extensions.empty()) {
703e5c31af7Sopenharmony_ci    if (!AreAllExtensionsSupported(available_instance_extensions_,
704e5c31af7Sopenharmony_ci                                   required_extensions)) {
705e5c31af7Sopenharmony_ci      return amber::Result("Missing required instance extensions");
706e5c31af7Sopenharmony_ci    }
707e5c31af7Sopenharmony_ci  }
708e5c31af7Sopenharmony_ci
709e5c31af7Sopenharmony_ci  if (std::find(available_instance_extensions_.begin(),
710e5c31af7Sopenharmony_ci                available_instance_extensions_.end(),
711e5c31af7Sopenharmony_ci                "VK_KHR_get_physical_device_properties2") !=
712e5c31af7Sopenharmony_ci      available_instance_extensions_.end()) {
713e5c31af7Sopenharmony_ci    required_extensions.push_back("VK_KHR_get_physical_device_properties2");
714e5c31af7Sopenharmony_ci  }
715e5c31af7Sopenharmony_ci
716e5c31af7Sopenharmony_ci  // Determine if VkPhysicalDeviceProperties2KHR should be used
717e5c31af7Sopenharmony_ci  for (auto& ext : required_extensions) {
718e5c31af7Sopenharmony_ci    if (ext == "VK_KHR_get_physical_device_properties2")
719e5c31af7Sopenharmony_ci      supports_get_physical_device_properties2_ = true;
720e5c31af7Sopenharmony_ci  }
721e5c31af7Sopenharmony_ci
722e5c31af7Sopenharmony_ci  std::vector<const char*> required_extensions_in_char;
723e5c31af7Sopenharmony_ci  std::transform(
724e5c31af7Sopenharmony_ci      required_extensions.begin(), required_extensions.end(),
725e5c31af7Sopenharmony_ci      std::back_inserter(required_extensions_in_char),
726e5c31af7Sopenharmony_ci      [](const std::string& ext) -> const char* { return ext.c_str(); });
727e5c31af7Sopenharmony_ci
728e5c31af7Sopenharmony_ci  instance_info.enabledExtensionCount =
729e5c31af7Sopenharmony_ci      static_cast<uint32_t>(required_extensions_in_char.size());
730e5c31af7Sopenharmony_ci  instance_info.ppEnabledExtensionNames = required_extensions_in_char.data();
731e5c31af7Sopenharmony_ci
732e5c31af7Sopenharmony_ci  if (vkCreateInstance(&instance_info, nullptr, &vulkan_instance_) !=
733e5c31af7Sopenharmony_ci      VK_SUCCESS) {
734e5c31af7Sopenharmony_ci    return amber::Result("Unable to create vulkan instance");
735e5c31af7Sopenharmony_ci  }
736e5c31af7Sopenharmony_ci  return {};
737e5c31af7Sopenharmony_ci}
738e5c31af7Sopenharmony_ci
739e5c31af7Sopenharmony_ciamber::Result ConfigHelperVulkan::CreateDebugReportCallback() {
740e5c31af7Sopenharmony_ci  VkDebugReportCallbackCreateInfoEXT info =
741e5c31af7Sopenharmony_ci      VkDebugReportCallbackCreateInfoEXT();
742e5c31af7Sopenharmony_ci  info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
743e5c31af7Sopenharmony_ci  info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
744e5c31af7Sopenharmony_ci  info.pfnCallback = debugCallback;
745e5c31af7Sopenharmony_ci
746e5c31af7Sopenharmony_ci  auto vkCreateDebugReportCallbackEXT =
747e5c31af7Sopenharmony_ci      reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
748e5c31af7Sopenharmony_ci          vkGetInstanceProcAddr(vulkan_instance_,
749e5c31af7Sopenharmony_ci                                "vkCreateDebugReportCallbackEXT"));
750e5c31af7Sopenharmony_ci  if (!vkCreateDebugReportCallbackEXT)
751e5c31af7Sopenharmony_ci    return amber::Result("Sample: vkCreateDebugReportCallbackEXT is nullptr");
752e5c31af7Sopenharmony_ci
753e5c31af7Sopenharmony_ci  if (vkCreateDebugReportCallbackEXT(vulkan_instance_, &info, nullptr,
754e5c31af7Sopenharmony_ci                                     &vulkan_callback_) != VK_SUCCESS) {
755e5c31af7Sopenharmony_ci    return amber::Result("Sample: vkCreateDebugReportCallbackEXT fail");
756e5c31af7Sopenharmony_ci  }
757e5c31af7Sopenharmony_ci  return {};
758e5c31af7Sopenharmony_ci}
759e5c31af7Sopenharmony_ci
760e5c31af7Sopenharmony_ciamber::Result ConfigHelperVulkan::CheckVulkanPhysicalDeviceRequirements(
761e5c31af7Sopenharmony_ci    const VkPhysicalDevice physical_device,
762e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_features,
763e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_extensions) {
764e5c31af7Sopenharmony_ci  available_device_extensions_ = GetAvailableDeviceExtensions(physical_device);
765e5c31af7Sopenharmony_ci  if (!AreAllExtensionsSupported(available_device_extensions_,
766e5c31af7Sopenharmony_ci                                 required_extensions)) {
767e5c31af7Sopenharmony_ci    return amber::Result("Device does not support all required extensions");
768e5c31af7Sopenharmony_ci  }
769e5c31af7Sopenharmony_ci  for (const auto& ext : available_device_extensions_) {
770e5c31af7Sopenharmony_ci    if (ext == "VK_KHR_shader_float16_int8")
771e5c31af7Sopenharmony_ci      supports_shader_float16_int8_ = true;
772e5c31af7Sopenharmony_ci    else if (ext == "VK_KHR_8bit_storage")
773e5c31af7Sopenharmony_ci      supports_shader_8bit_storage_ = true;
774e5c31af7Sopenharmony_ci    else if (ext == "VK_KHR_16bit_storage")
775e5c31af7Sopenharmony_ci      supports_shader_16bit_storage_ = true;
776e5c31af7Sopenharmony_ci    else if (ext == "VK_EXT_subgroup_size_control")
777e5c31af7Sopenharmony_ci      supports_subgroup_size_control_ = true;
778e5c31af7Sopenharmony_ci    else if (ext == "VK_KHR_shader_subgroup_extended_types")
779e5c31af7Sopenharmony_ci      supports_shader_subgroup_extended_types_ = true;
780e5c31af7Sopenharmony_ci  }
781e5c31af7Sopenharmony_ci
782e5c31af7Sopenharmony_ci  VkPhysicalDeviceFeatures required_vulkan_features =
783e5c31af7Sopenharmony_ci      VkPhysicalDeviceFeatures();
784e5c31af7Sopenharmony_ci
785e5c31af7Sopenharmony_ci  if (supports_get_physical_device_properties2_) {
786e5c31af7Sopenharmony_ci    VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures
787e5c31af7Sopenharmony_ci        shader_subgroup_extended_types_features = {};
788e5c31af7Sopenharmony_ci    VkPhysicalDeviceSubgroupSizeControlFeaturesEXT
789e5c31af7Sopenharmony_ci        subgroup_size_control_features = {};
790e5c31af7Sopenharmony_ci    VkPhysicalDeviceVariablePointerFeaturesKHR variable_pointers_features = {};
791e5c31af7Sopenharmony_ci    VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8_features = {};
792e5c31af7Sopenharmony_ci    VkPhysicalDevice8BitStorageFeaturesKHR storage_8bit_features = {};
793e5c31af7Sopenharmony_ci    VkPhysicalDevice16BitStorageFeaturesKHR storage_16bit_features = {};
794e5c31af7Sopenharmony_ci
795e5c31af7Sopenharmony_ci    subgroup_size_control_features.sType =
796e5c31af7Sopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT;
797e5c31af7Sopenharmony_ci    subgroup_size_control_features.pNext = nullptr;
798e5c31af7Sopenharmony_ci
799e5c31af7Sopenharmony_ci    // Add subgroup size control struct into the chain only if
800e5c31af7Sopenharmony_ci    // VK_EXT_subgroup_size_control is supported.
801e5c31af7Sopenharmony_ci    variable_pointers_features.sType =
802e5c31af7Sopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR;
803e5c31af7Sopenharmony_ci    variable_pointers_features.pNext = supports_subgroup_size_control_
804e5c31af7Sopenharmony_ci                                           ? &subgroup_size_control_features
805e5c31af7Sopenharmony_ci                                           : nullptr;
806e5c31af7Sopenharmony_ci
807e5c31af7Sopenharmony_ci    shader_subgroup_extended_types_features.sType =
808e5c31af7Sopenharmony_ci    // NOLINTNEXTLINE(whitespace/line_length)
809e5c31af7Sopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES;
810e5c31af7Sopenharmony_ci    shader_subgroup_extended_types_features.pNext = &variable_pointers_features;
811e5c31af7Sopenharmony_ci
812e5c31af7Sopenharmony_ci    float16_int8_features.sType =
813e5c31af7Sopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
814e5c31af7Sopenharmony_ci    float16_int8_features.pNext = &shader_subgroup_extended_types_features;
815e5c31af7Sopenharmony_ci
816e5c31af7Sopenharmony_ci    storage_8bit_features.sType =
817e5c31af7Sopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR;
818e5c31af7Sopenharmony_ci    storage_8bit_features.pNext = &float16_int8_features;
819e5c31af7Sopenharmony_ci
820e5c31af7Sopenharmony_ci    storage_16bit_features.sType =
821e5c31af7Sopenharmony_ci        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;
822e5c31af7Sopenharmony_ci    storage_16bit_features.pNext = &storage_8bit_features;
823e5c31af7Sopenharmony_ci
824e5c31af7Sopenharmony_ci    VkPhysicalDeviceFeatures2KHR features2 = VkPhysicalDeviceFeatures2KHR();
825e5c31af7Sopenharmony_ci    features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
826e5c31af7Sopenharmony_ci    features2.pNext = &storage_16bit_features;
827e5c31af7Sopenharmony_ci
828e5c31af7Sopenharmony_ci    auto vkGetPhysicalDeviceFeatures2KHR =
829e5c31af7Sopenharmony_ci        reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2KHR>(
830e5c31af7Sopenharmony_ci            vkGetInstanceProcAddr(vulkan_instance_,
831e5c31af7Sopenharmony_ci                                  "vkGetPhysicalDeviceFeatures2KHR"));
832e5c31af7Sopenharmony_ci    vkGetPhysicalDeviceFeatures2KHR(physical_device, &features2);
833e5c31af7Sopenharmony_ci    available_features_ = features2.features;
834e5c31af7Sopenharmony_ci
835e5c31af7Sopenharmony_ci    std::vector<std::string> required_features1;
836e5c31af7Sopenharmony_ci    for (const auto& feature : required_features) {
837e5c31af7Sopenharmony_ci      // No dot means this is a features1 feature.
838e5c31af7Sopenharmony_ci      if (feature.find_first_of('.') == std::string::npos) {
839e5c31af7Sopenharmony_ci        required_features1.push_back(feature);
840e5c31af7Sopenharmony_ci        continue;
841e5c31af7Sopenharmony_ci      }
842e5c31af7Sopenharmony_ci
843e5c31af7Sopenharmony_ci      if ((feature == kVariablePointers &&
844e5c31af7Sopenharmony_ci           variable_pointers_features.variablePointers == VK_FALSE) ||
845e5c31af7Sopenharmony_ci          (feature == kVariablePointersStorageBuffer &&
846e5c31af7Sopenharmony_ci           variable_pointers_features.variablePointersStorageBuffer ==
847e5c31af7Sopenharmony_ci               VK_FALSE) ||
848e5c31af7Sopenharmony_ci          (feature == kSubgroupSizeControl &&
849e5c31af7Sopenharmony_ci           subgroup_size_control_features.subgroupSizeControl == VK_FALSE) ||
850e5c31af7Sopenharmony_ci          (feature == kComputeFullSubgroups &&
851e5c31af7Sopenharmony_ci           subgroup_size_control_features.computeFullSubgroups == VK_FALSE) ||
852e5c31af7Sopenharmony_ci          (feature == kFloat16Int8_Float16 &&
853e5c31af7Sopenharmony_ci           float16_int8_features.shaderFloat16 == VK_FALSE) ||
854e5c31af7Sopenharmony_ci          (feature == kFloat16Int8_Int8 &&
855e5c31af7Sopenharmony_ci           float16_int8_features.shaderInt8 == VK_FALSE) ||
856e5c31af7Sopenharmony_ci          (feature == k8BitStorage_Storage &&
857e5c31af7Sopenharmony_ci           storage_8bit_features.storageBuffer8BitAccess == VK_FALSE) ||
858e5c31af7Sopenharmony_ci          (feature == k8BitStorage_UniformAndStorage &&
859e5c31af7Sopenharmony_ci           storage_8bit_features.uniformAndStorageBuffer8BitAccess ==
860e5c31af7Sopenharmony_ci               VK_FALSE) ||
861e5c31af7Sopenharmony_ci          (feature == k8BitStorage_PushConstant &&
862e5c31af7Sopenharmony_ci           storage_8bit_features.storagePushConstant8 == VK_FALSE) ||
863e5c31af7Sopenharmony_ci          (feature == k16BitStorage_Storage &&
864e5c31af7Sopenharmony_ci           storage_16bit_features.storageBuffer16BitAccess == VK_FALSE) ||
865e5c31af7Sopenharmony_ci          (feature == k16BitStorage_InputOutput &&
866e5c31af7Sopenharmony_ci           storage_16bit_features.storageInputOutput16 == VK_FALSE) ||
867e5c31af7Sopenharmony_ci          (feature == k16BitStorage_PushConstant &&
868e5c31af7Sopenharmony_ci           storage_16bit_features.storagePushConstant16 == VK_FALSE) ||
869e5c31af7Sopenharmony_ci          (feature == k16BitStorage_UniformAndStorage &&
870e5c31af7Sopenharmony_ci           storage_16bit_features.uniformAndStorageBuffer16BitAccess ==
871e5c31af7Sopenharmony_ci               VK_FALSE) ||
872e5c31af7Sopenharmony_ci          (feature == kShaderSubgroupExtendedTypes &&
873e5c31af7Sopenharmony_ci           shader_subgroup_extended_types_features
874e5c31af7Sopenharmony_ci                   .shaderSubgroupExtendedTypes == VK_FALSE)) {
875e5c31af7Sopenharmony_ci        return amber::Result("Device does not support all required features");
876e5c31af7Sopenharmony_ci      }
877e5c31af7Sopenharmony_ci    }
878e5c31af7Sopenharmony_ci
879e5c31af7Sopenharmony_ci    amber::Result r =
880e5c31af7Sopenharmony_ci        NamesToVulkanFeatures(required_features1, &required_vulkan_features);
881e5c31af7Sopenharmony_ci    if (!r.IsSuccess())
882e5c31af7Sopenharmony_ci      return r;
883e5c31af7Sopenharmony_ci
884e5c31af7Sopenharmony_ci  } else {
885e5c31af7Sopenharmony_ci    amber::Result r =
886e5c31af7Sopenharmony_ci        NamesToVulkanFeatures(required_features, &required_vulkan_features);
887e5c31af7Sopenharmony_ci    if (!r.IsSuccess())
888e5c31af7Sopenharmony_ci      return r;
889e5c31af7Sopenharmony_ci
890e5c31af7Sopenharmony_ci    vkGetPhysicalDeviceFeatures(physical_device, &available_features_);
891e5c31af7Sopenharmony_ci  }
892e5c31af7Sopenharmony_ci  if (!AreAllRequiredFeaturesSupported(available_features_,
893e5c31af7Sopenharmony_ci                                       required_vulkan_features)) {
894e5c31af7Sopenharmony_ci    return amber::Result("Device does not support all required features");
895e5c31af7Sopenharmony_ci  }
896e5c31af7Sopenharmony_ci
897e5c31af7Sopenharmony_ci  vulkan_queue_family_index_ = ChooseQueueFamilyIndex(physical_device);
898e5c31af7Sopenharmony_ci  if (vulkan_queue_family_index_ == std::numeric_limits<uint32_t>::max()) {
899e5c31af7Sopenharmony_ci    return amber::Result("Device does not support required queue flags");
900e5c31af7Sopenharmony_ci  }
901e5c31af7Sopenharmony_ci
902e5c31af7Sopenharmony_ci  return {};
903e5c31af7Sopenharmony_ci}
904e5c31af7Sopenharmony_ci
905e5c31af7Sopenharmony_ciamber::Result ConfigHelperVulkan::ChooseVulkanPhysicalDevice(
906e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_features,
907e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_extensions,
908e5c31af7Sopenharmony_ci    const int32_t selected_device) {
909e5c31af7Sopenharmony_ci  uint32_t count = 0;
910e5c31af7Sopenharmony_ci  std::vector<VkPhysicalDevice> physical_devices;
911e5c31af7Sopenharmony_ci
912e5c31af7Sopenharmony_ci  if (vkEnumeratePhysicalDevices(vulkan_instance_, &count, nullptr) !=
913e5c31af7Sopenharmony_ci      VK_SUCCESS) {
914e5c31af7Sopenharmony_ci    return amber::Result("Unable to enumerate physical devices");
915e5c31af7Sopenharmony_ci  }
916e5c31af7Sopenharmony_ci
917e5c31af7Sopenharmony_ci  physical_devices.resize(count);
918e5c31af7Sopenharmony_ci  if (vkEnumeratePhysicalDevices(vulkan_instance_, &count,
919e5c31af7Sopenharmony_ci                                 physical_devices.data()) != VK_SUCCESS) {
920e5c31af7Sopenharmony_ci    return amber::Result("Unable to enumerate physical devices");
921e5c31af7Sopenharmony_ci  }
922e5c31af7Sopenharmony_ci
923e5c31af7Sopenharmony_ci  if (selected_device > -1) {
924e5c31af7Sopenharmony_ci    uint32_t deviceID = static_cast<uint32_t>(selected_device);
925e5c31af7Sopenharmony_ci    if (deviceID >= count) {
926e5c31af7Sopenharmony_ci      return amber::Result("Unable to find Vulkan device with ID " +
927e5c31af7Sopenharmony_ci                           std::to_string(deviceID));
928e5c31af7Sopenharmony_ci    }
929e5c31af7Sopenharmony_ci    amber::Result r = CheckVulkanPhysicalDeviceRequirements(
930e5c31af7Sopenharmony_ci        physical_devices[deviceID], required_features, required_extensions);
931e5c31af7Sopenharmony_ci    if (!r.IsSuccess())
932e5c31af7Sopenharmony_ci      return r;
933e5c31af7Sopenharmony_ci    vulkan_physical_device_ = physical_devices[deviceID];
934e5c31af7Sopenharmony_ci    return {};
935e5c31af7Sopenharmony_ci  } else {
936e5c31af7Sopenharmony_ci    for (uint32_t i = 0; i < count; ++i) {
937e5c31af7Sopenharmony_ci      amber::Result r = CheckVulkanPhysicalDeviceRequirements(
938e5c31af7Sopenharmony_ci          physical_devices[i], required_features, required_extensions);
939e5c31af7Sopenharmony_ci      if (!r.IsSuccess())
940e5c31af7Sopenharmony_ci        continue;
941e5c31af7Sopenharmony_ci      vulkan_physical_device_ = physical_devices[i];
942e5c31af7Sopenharmony_ci      return {};
943e5c31af7Sopenharmony_ci    }
944e5c31af7Sopenharmony_ci  }
945e5c31af7Sopenharmony_ci
946e5c31af7Sopenharmony_ci  std::ostringstream out;
947e5c31af7Sopenharmony_ci  out << "Unable to find Vulkan device supporting:" << std::endl;
948e5c31af7Sopenharmony_ci  for (const auto& str : required_features)
949e5c31af7Sopenharmony_ci    out << "  " << str << std::endl;
950e5c31af7Sopenharmony_ci  for (const auto& str : required_extensions)
951e5c31af7Sopenharmony_ci    out << "  " << str << std::endl;
952e5c31af7Sopenharmony_ci
953e5c31af7Sopenharmony_ci  return amber::Result(out.str());
954e5c31af7Sopenharmony_ci}
955e5c31af7Sopenharmony_ci
956e5c31af7Sopenharmony_ciamber::Result ConfigHelperVulkan::CreateVulkanDevice(
957e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_features,
958e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_extensions) {
959e5c31af7Sopenharmony_ci  VkDeviceQueueCreateInfo queue_info = VkDeviceQueueCreateInfo();
960e5c31af7Sopenharmony_ci  const float priorities[] = {1.0f};
961e5c31af7Sopenharmony_ci
962e5c31af7Sopenharmony_ci  queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
963e5c31af7Sopenharmony_ci  queue_info.queueFamilyIndex = vulkan_queue_family_index_;
964e5c31af7Sopenharmony_ci  queue_info.queueCount = 1;
965e5c31af7Sopenharmony_ci  queue_info.pQueuePriorities = priorities;
966e5c31af7Sopenharmony_ci
967e5c31af7Sopenharmony_ci  std::vector<const char*> required_extensions_in_char;
968e5c31af7Sopenharmony_ci  std::transform(
969e5c31af7Sopenharmony_ci      required_extensions.begin(), required_extensions.end(),
970e5c31af7Sopenharmony_ci      std::back_inserter(required_extensions_in_char),
971e5c31af7Sopenharmony_ci      [](const std::string& ext) -> const char* { return ext.c_str(); });
972e5c31af7Sopenharmony_ci
973e5c31af7Sopenharmony_ci  VkDeviceCreateInfo info = VkDeviceCreateInfo();
974e5c31af7Sopenharmony_ci  info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
975e5c31af7Sopenharmony_ci  info.pQueueCreateInfos = &queue_info;
976e5c31af7Sopenharmony_ci  info.queueCreateInfoCount = 1;
977e5c31af7Sopenharmony_ci  info.enabledExtensionCount =
978e5c31af7Sopenharmony_ci      static_cast<uint32_t>(required_extensions_in_char.size());
979e5c31af7Sopenharmony_ci  info.ppEnabledExtensionNames = required_extensions_in_char.data();
980e5c31af7Sopenharmony_ci
981e5c31af7Sopenharmony_ci  if (supports_get_physical_device_properties2_)
982e5c31af7Sopenharmony_ci    return CreateDeviceWithFeatures2(required_features, &info);
983e5c31af7Sopenharmony_ci  return CreateDeviceWithFeatures1(required_features, &info);
984e5c31af7Sopenharmony_ci}
985e5c31af7Sopenharmony_ci
986e5c31af7Sopenharmony_ciamber::Result ConfigHelperVulkan::CreateDeviceWithFeatures1(
987e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_features,
988e5c31af7Sopenharmony_ci    VkDeviceCreateInfo* info) {
989e5c31af7Sopenharmony_ci  VkPhysicalDeviceFeatures required_vulkan_features =
990e5c31af7Sopenharmony_ci      VkPhysicalDeviceFeatures();
991e5c31af7Sopenharmony_ci  amber::Result r =
992e5c31af7Sopenharmony_ci      NamesToVulkanFeatures(required_features, &required_vulkan_features);
993e5c31af7Sopenharmony_ci  if (!r.IsSuccess())
994e5c31af7Sopenharmony_ci    return r;
995e5c31af7Sopenharmony_ci
996e5c31af7Sopenharmony_ci  info->pEnabledFeatures = &required_vulkan_features;
997e5c31af7Sopenharmony_ci  return DoCreateDevice(info);
998e5c31af7Sopenharmony_ci}
999e5c31af7Sopenharmony_ci
1000e5c31af7Sopenharmony_ciamber::Result ConfigHelperVulkan::CreateDeviceWithFeatures2(
1001e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_features,
1002e5c31af7Sopenharmony_ci    VkDeviceCreateInfo* info) {
1003e5c31af7Sopenharmony_ci  variable_pointers_feature_.sType =
1004e5c31af7Sopenharmony_ci      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR;
1005e5c31af7Sopenharmony_ci  variable_pointers_feature_.pNext = nullptr;
1006e5c31af7Sopenharmony_ci
1007e5c31af7Sopenharmony_ci  float16_int8_feature_.sType =
1008e5c31af7Sopenharmony_ci      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR;
1009e5c31af7Sopenharmony_ci  float16_int8_feature_.pNext = nullptr;
1010e5c31af7Sopenharmony_ci
1011e5c31af7Sopenharmony_ci  storage_8bit_feature_.sType =
1012e5c31af7Sopenharmony_ci      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR;
1013e5c31af7Sopenharmony_ci  storage_8bit_feature_.pNext = nullptr;
1014e5c31af7Sopenharmony_ci
1015e5c31af7Sopenharmony_ci  storage_16bit_feature_.sType =
1016e5c31af7Sopenharmony_ci      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR;
1017e5c31af7Sopenharmony_ci  storage_16bit_feature_.pNext = nullptr;
1018e5c31af7Sopenharmony_ci
1019e5c31af7Sopenharmony_ci  subgroup_size_control_feature_.sType =
1020e5c31af7Sopenharmony_ci      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT;
1021e5c31af7Sopenharmony_ci  subgroup_size_control_feature_.pNext = nullptr;
1022e5c31af7Sopenharmony_ci
1023e5c31af7Sopenharmony_ci  shader_subgroup_extended_types_feature_.sType =
1024e5c31af7Sopenharmony_ci      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES;
1025e5c31af7Sopenharmony_ci  shader_subgroup_extended_types_feature_.pNext = nullptr;
1026e5c31af7Sopenharmony_ci
1027e5c31af7Sopenharmony_ci  void** next_ptr = &variable_pointers_feature_.pNext;
1028e5c31af7Sopenharmony_ci
1029e5c31af7Sopenharmony_ci  if (supports_shader_float16_int8_) {
1030e5c31af7Sopenharmony_ci    *next_ptr = &float16_int8_feature_;
1031e5c31af7Sopenharmony_ci    next_ptr = &float16_int8_feature_.pNext;
1032e5c31af7Sopenharmony_ci  }
1033e5c31af7Sopenharmony_ci
1034e5c31af7Sopenharmony_ci  if (supports_shader_8bit_storage_) {
1035e5c31af7Sopenharmony_ci    *next_ptr = &storage_8bit_feature_;
1036e5c31af7Sopenharmony_ci    next_ptr = &storage_8bit_feature_.pNext;
1037e5c31af7Sopenharmony_ci  }
1038e5c31af7Sopenharmony_ci
1039e5c31af7Sopenharmony_ci  if (supports_shader_16bit_storage_) {
1040e5c31af7Sopenharmony_ci    *next_ptr = &storage_16bit_feature_;
1041e5c31af7Sopenharmony_ci    next_ptr = &storage_16bit_feature_.pNext;
1042e5c31af7Sopenharmony_ci  }
1043e5c31af7Sopenharmony_ci
1044e5c31af7Sopenharmony_ci  if (supports_subgroup_size_control_) {
1045e5c31af7Sopenharmony_ci    *next_ptr = &subgroup_size_control_feature_;
1046e5c31af7Sopenharmony_ci    next_ptr = &subgroup_size_control_feature_.pNext;
1047e5c31af7Sopenharmony_ci  }
1048e5c31af7Sopenharmony_ci
1049e5c31af7Sopenharmony_ci  if (supports_shader_subgroup_extended_types_) {
1050e5c31af7Sopenharmony_ci    *next_ptr = &shader_subgroup_extended_types_feature_;
1051e5c31af7Sopenharmony_ci    next_ptr = &shader_subgroup_extended_types_feature_.pNext;
1052e5c31af7Sopenharmony_ci  }
1053e5c31af7Sopenharmony_ci
1054e5c31af7Sopenharmony_ci  available_features2_.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
1055e5c31af7Sopenharmony_ci  available_features2_.pNext = &variable_pointers_feature_;
1056e5c31af7Sopenharmony_ci
1057e5c31af7Sopenharmony_ci  std::vector<std::string> feature1_names;
1058e5c31af7Sopenharmony_ci  for (const auto& feature : required_features) {
1059e5c31af7Sopenharmony_ci    // No dot means this is a features1 feature.
1060e5c31af7Sopenharmony_ci    if (feature.find_first_of('.') == std::string::npos) {
1061e5c31af7Sopenharmony_ci      feature1_names.push_back(feature);
1062e5c31af7Sopenharmony_ci      continue;
1063e5c31af7Sopenharmony_ci    }
1064e5c31af7Sopenharmony_ci
1065e5c31af7Sopenharmony_ci    if (feature == kVariablePointers)
1066e5c31af7Sopenharmony_ci      variable_pointers_feature_.variablePointers = VK_TRUE;
1067e5c31af7Sopenharmony_ci    else if (feature == kVariablePointersStorageBuffer)
1068e5c31af7Sopenharmony_ci      variable_pointers_feature_.variablePointersStorageBuffer = VK_TRUE;
1069e5c31af7Sopenharmony_ci    else if (feature == kFloat16Int8_Float16)
1070e5c31af7Sopenharmony_ci      float16_int8_feature_.shaderFloat16 = VK_TRUE;
1071e5c31af7Sopenharmony_ci    else if (feature == kFloat16Int8_Int8)
1072e5c31af7Sopenharmony_ci      float16_int8_feature_.shaderInt8 = VK_TRUE;
1073e5c31af7Sopenharmony_ci    else if (feature == k8BitStorage_Storage)
1074e5c31af7Sopenharmony_ci      storage_8bit_feature_.storageBuffer8BitAccess = VK_TRUE;
1075e5c31af7Sopenharmony_ci    else if (feature == k8BitStorage_UniformAndStorage)
1076e5c31af7Sopenharmony_ci      storage_8bit_feature_.uniformAndStorageBuffer8BitAccess = VK_TRUE;
1077e5c31af7Sopenharmony_ci    else if (feature == k8BitStorage_PushConstant)
1078e5c31af7Sopenharmony_ci      storage_8bit_feature_.storagePushConstant8 = VK_TRUE;
1079e5c31af7Sopenharmony_ci    else if (feature == k16BitStorage_Storage)
1080e5c31af7Sopenharmony_ci      storage_16bit_feature_.storageBuffer16BitAccess = VK_TRUE;
1081e5c31af7Sopenharmony_ci    else if (feature == k16BitStorage_UniformAndStorage)
1082e5c31af7Sopenharmony_ci      storage_16bit_feature_.uniformAndStorageBuffer16BitAccess = VK_TRUE;
1083e5c31af7Sopenharmony_ci    else if (feature == k16BitStorage_PushConstant)
1084e5c31af7Sopenharmony_ci      storage_16bit_feature_.storagePushConstant16 = VK_TRUE;
1085e5c31af7Sopenharmony_ci    else if (feature == k16BitStorage_InputOutput)
1086e5c31af7Sopenharmony_ci      storage_16bit_feature_.storageInputOutput16 = VK_TRUE;
1087e5c31af7Sopenharmony_ci    else if (feature == kSubgroupSizeControl)
1088e5c31af7Sopenharmony_ci      subgroup_size_control_feature_.subgroupSizeControl = VK_TRUE;
1089e5c31af7Sopenharmony_ci    else if (feature == kComputeFullSubgroups)
1090e5c31af7Sopenharmony_ci      subgroup_size_control_feature_.computeFullSubgroups = VK_TRUE;
1091e5c31af7Sopenharmony_ci    else if (feature == kShaderSubgroupExtendedTypes)
1092e5c31af7Sopenharmony_ci      shader_subgroup_extended_types_feature_.shaderSubgroupExtendedTypes =
1093e5c31af7Sopenharmony_ci          VK_TRUE;
1094e5c31af7Sopenharmony_ci  }
1095e5c31af7Sopenharmony_ci
1096e5c31af7Sopenharmony_ci  VkPhysicalDeviceFeatures required_vulkan_features =
1097e5c31af7Sopenharmony_ci      VkPhysicalDeviceFeatures();
1098e5c31af7Sopenharmony_ci  amber::Result r =
1099e5c31af7Sopenharmony_ci      NamesToVulkanFeatures(feature1_names, &required_vulkan_features);
1100e5c31af7Sopenharmony_ci  if (!r.IsSuccess())
1101e5c31af7Sopenharmony_ci    return r;
1102e5c31af7Sopenharmony_ci
1103e5c31af7Sopenharmony_ci  available_features2_.features = required_vulkan_features;
1104e5c31af7Sopenharmony_ci
1105e5c31af7Sopenharmony_ci  info->pNext = &available_features2_;
1106e5c31af7Sopenharmony_ci  info->pEnabledFeatures = nullptr;
1107e5c31af7Sopenharmony_ci  return DoCreateDevice(info);
1108e5c31af7Sopenharmony_ci}
1109e5c31af7Sopenharmony_ci
1110e5c31af7Sopenharmony_ciamber::Result ConfigHelperVulkan::DoCreateDevice(VkDeviceCreateInfo* info) {
1111e5c31af7Sopenharmony_ci  if (vkCreateDevice(vulkan_physical_device_, info, nullptr, &vulkan_device_) !=
1112e5c31af7Sopenharmony_ci      VK_SUCCESS) {
1113e5c31af7Sopenharmony_ci    return amber::Result("Unable to create vulkan device");
1114e5c31af7Sopenharmony_ci  }
1115e5c31af7Sopenharmony_ci  return {};
1116e5c31af7Sopenharmony_ci}
1117e5c31af7Sopenharmony_ci
1118e5c31af7Sopenharmony_civoid ConfigHelperVulkan::DumpPhysicalDeviceInfo() {
1119e5c31af7Sopenharmony_ci  VkPhysicalDeviceProperties2KHR properties2 = {
1120e5c31af7Sopenharmony_ci      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
1121e5c31af7Sopenharmony_ci      nullptr,  // pNext: will point to our driver_properties struct if the
1122e5c31af7Sopenharmony_ci                // "VK_KHR_get_physical_device_properties2" and
1123e5c31af7Sopenharmony_ci                // "VK_KHR_driver_properties" extensions are both available.
1124e5c31af7Sopenharmony_ci      {},  // properties: this is the older VkPhysicalDeviceProperties struct,
1125e5c31af7Sopenharmony_ci           // wrapped by this newer struct that adds the pNext member. We use
1126e5c31af7Sopenharmony_ci           // this older struct if the "VK_KHR_get_physical_device_properties2"
1127e5c31af7Sopenharmony_ci           // extension is unavailable.
1128e5c31af7Sopenharmony_ci  };
1129e5c31af7Sopenharmony_ci
1130e5c31af7Sopenharmony_ci  VkPhysicalDeviceDriverPropertiesKHR driver_properties = {
1131e5c31af7Sopenharmony_ci      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR,
1132e5c31af7Sopenharmony_ci      nullptr,
1133e5c31af7Sopenharmony_ci      {},
1134e5c31af7Sopenharmony_ci      {},
1135e5c31af7Sopenharmony_ci      {},
1136e5c31af7Sopenharmony_ci      {},
1137e5c31af7Sopenharmony_ci  };
1138e5c31af7Sopenharmony_ci
1139e5c31af7Sopenharmony_ci  VkPhysicalDeviceSubgroupSizeControlPropertiesEXT
1140e5c31af7Sopenharmony_ci      subgroup_size_control_properties = {
1141e5c31af7Sopenharmony_ci          VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT,  // NOLINT(whitespace/line_length)
1142e5c31af7Sopenharmony_ci          nullptr,
1143e5c31af7Sopenharmony_ci          {},
1144e5c31af7Sopenharmony_ci          {},
1145e5c31af7Sopenharmony_ci          {},
1146e5c31af7Sopenharmony_ci          {}};
1147e5c31af7Sopenharmony_ci
1148e5c31af7Sopenharmony_ci  // If the vkGetPhysicalDeviceProperties2KHR function is unavailable (because
1149e5c31af7Sopenharmony_ci  // the "VK_KHR_get_physical_device_properties2" extension is unavailable or
1150e5c31af7Sopenharmony_ci  // because vkGetInstanceProcAddr failed) or the "VK_KHR_driver_properties"
1151e5c31af7Sopenharmony_ci  // extension is unavailable, then this will stay as nullptr and we will
1152e5c31af7Sopenharmony_ci  // instead call the older vkGetPhysicalDeviceProperties function.
1153e5c31af7Sopenharmony_ci  PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR =
1154e5c31af7Sopenharmony_ci      nullptr;
1155e5c31af7Sopenharmony_ci
1156e5c31af7Sopenharmony_ci  if (supports_get_physical_device_properties2_ &&
1157e5c31af7Sopenharmony_ci      std::find(available_device_extensions_.begin(),
1158e5c31af7Sopenharmony_ci                available_device_extensions_.end(),
1159e5c31af7Sopenharmony_ci                "VK_KHR_driver_properties") !=
1160e5c31af7Sopenharmony_ci          available_device_extensions_.end()) {
1161e5c31af7Sopenharmony_ci    properties2.pNext = &driver_properties;
1162e5c31af7Sopenharmony_ci
1163e5c31af7Sopenharmony_ci    vkGetPhysicalDeviceProperties2KHR =
1164e5c31af7Sopenharmony_ci        reinterpret_cast<PFN_vkGetPhysicalDeviceProperties2KHR>(
1165e5c31af7Sopenharmony_ci            vkGetInstanceProcAddr(vulkan_instance_,
1166e5c31af7Sopenharmony_ci                                  "vkGetPhysicalDeviceProperties2KHR"));
1167e5c31af7Sopenharmony_ci    if (!vkGetPhysicalDeviceProperties2KHR) {
1168e5c31af7Sopenharmony_ci      std::cout << "Warning: device claimed to support "
1169e5c31af7Sopenharmony_ci                   "vkGetPhysicalDeviceProperties2KHR but could not find this "
1170e5c31af7Sopenharmony_ci                   "function."
1171e5c31af7Sopenharmony_ci                << std::endl;
1172e5c31af7Sopenharmony_ci    }
1173e5c31af7Sopenharmony_ci    if (supports_subgroup_size_control_) {
1174e5c31af7Sopenharmony_ci      driver_properties.pNext = &subgroup_size_control_properties;
1175e5c31af7Sopenharmony_ci    }
1176e5c31af7Sopenharmony_ci  }
1177e5c31af7Sopenharmony_ci
1178e5c31af7Sopenharmony_ci  if (vkGetPhysicalDeviceProperties2KHR) {
1179e5c31af7Sopenharmony_ci    vkGetPhysicalDeviceProperties2KHR(vulkan_physical_device_, &properties2);
1180e5c31af7Sopenharmony_ci  } else {
1181e5c31af7Sopenharmony_ci    vkGetPhysicalDeviceProperties(vulkan_physical_device_,
1182e5c31af7Sopenharmony_ci                                  &properties2.properties);
1183e5c31af7Sopenharmony_ci  }
1184e5c31af7Sopenharmony_ci
1185e5c31af7Sopenharmony_ci  const VkPhysicalDeviceProperties& props = properties2.properties;
1186e5c31af7Sopenharmony_ci
1187e5c31af7Sopenharmony_ci  uint32_t api_version = props.apiVersion;
1188e5c31af7Sopenharmony_ci
1189e5c31af7Sopenharmony_ci  std::cout << std::endl;
1190e5c31af7Sopenharmony_ci  std::cout << "Physical device properties:" << std::endl;
1191e5c31af7Sopenharmony_ci  std::cout << "  apiVersion: " << static_cast<uint32_t>(api_version >> 22u)
1192e5c31af7Sopenharmony_ci            << "." << static_cast<uint32_t>((api_version >> 12u) & 0x3ffu)
1193e5c31af7Sopenharmony_ci            << "." << static_cast<uint32_t>(api_version & 0xfffu) << std::endl;
1194e5c31af7Sopenharmony_ci  std::cout << "  driverVersion: " << props.driverVersion << std::endl;
1195e5c31af7Sopenharmony_ci  std::cout << "  vendorID: " << props.vendorID << std::endl;
1196e5c31af7Sopenharmony_ci  std::cout << "  deviceID: " << props.deviceID << std::endl;
1197e5c31af7Sopenharmony_ci  std::cout << "  deviceType: " << deviceTypeToName(props.deviceType)
1198e5c31af7Sopenharmony_ci            << std::endl;
1199e5c31af7Sopenharmony_ci  std::cout << "  deviceName: " << props.deviceName << std::endl;
1200e5c31af7Sopenharmony_ci  if (vkGetPhysicalDeviceProperties2KHR) {
1201e5c31af7Sopenharmony_ci    std::cout << "  driverName: " << driver_properties.driverName << std::endl;
1202e5c31af7Sopenharmony_ci    std::cout << "  driverInfo: " << driver_properties.driverInfo << std::endl;
1203e5c31af7Sopenharmony_ci    if (supports_subgroup_size_control_) {
1204e5c31af7Sopenharmony_ci      std::cout << "  minSubgroupSize: "
1205e5c31af7Sopenharmony_ci                << subgroup_size_control_properties.minSubgroupSize
1206e5c31af7Sopenharmony_ci                << std::endl;
1207e5c31af7Sopenharmony_ci      std::cout << "  maxSubgroupSize: "
1208e5c31af7Sopenharmony_ci                << subgroup_size_control_properties.maxSubgroupSize
1209e5c31af7Sopenharmony_ci                << std::endl;
1210e5c31af7Sopenharmony_ci      std::cout << "  maxComputeWorkgroupSubgroups: "
1211e5c31af7Sopenharmony_ci                << subgroup_size_control_properties.maxComputeWorkgroupSubgroups
1212e5c31af7Sopenharmony_ci                << std::endl;
1213e5c31af7Sopenharmony_ci      std::cout << "  requiredSubgroupSizeStages: "
1214e5c31af7Sopenharmony_ci                << stageFlagBitsToNames(subgroup_size_control_properties
1215e5c31af7Sopenharmony_ci                                            .requiredSubgroupSizeStages)
1216e5c31af7Sopenharmony_ci                << std::endl;
1217e5c31af7Sopenharmony_ci    }
1218e5c31af7Sopenharmony_ci  }
1219e5c31af7Sopenharmony_ci  std::cout << "End of physical device properties." << std::endl;
1220e5c31af7Sopenharmony_ci}
1221e5c31af7Sopenharmony_ci
1222e5c31af7Sopenharmony_ciamber::Result ConfigHelperVulkan::CreateConfig(
1223e5c31af7Sopenharmony_ci    uint32_t engine_major,
1224e5c31af7Sopenharmony_ci    uint32_t engine_minor,
1225e5c31af7Sopenharmony_ci    int32_t selected_device,
1226e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_features,
1227e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_instance_extensions,
1228e5c31af7Sopenharmony_ci    const std::vector<std::string>& required_device_extensions,
1229e5c31af7Sopenharmony_ci    bool disable_validation_layer,
1230e5c31af7Sopenharmony_ci    bool show_version_info,
1231e5c31af7Sopenharmony_ci    std::unique_ptr<amber::EngineConfig>* cfg_holder) {
1232e5c31af7Sopenharmony_ci  amber::Result r = CreateVulkanInstance(engine_major, engine_minor,
1233e5c31af7Sopenharmony_ci                                         required_instance_extensions,
1234e5c31af7Sopenharmony_ci                                         disable_validation_layer);
1235e5c31af7Sopenharmony_ci  if (!r.IsSuccess())
1236e5c31af7Sopenharmony_ci    return r;
1237e5c31af7Sopenharmony_ci
1238e5c31af7Sopenharmony_ci  if (!disable_validation_layer) {
1239e5c31af7Sopenharmony_ci    r = CreateDebugReportCallback();
1240e5c31af7Sopenharmony_ci    if (!r.IsSuccess())
1241e5c31af7Sopenharmony_ci      return r;
1242e5c31af7Sopenharmony_ci  }
1243e5c31af7Sopenharmony_ci
1244e5c31af7Sopenharmony_ci  r = ChooseVulkanPhysicalDevice(required_features, required_device_extensions,
1245e5c31af7Sopenharmony_ci                                 selected_device);
1246e5c31af7Sopenharmony_ci  if (!r.IsSuccess())
1247e5c31af7Sopenharmony_ci    return r;
1248e5c31af7Sopenharmony_ci
1249e5c31af7Sopenharmony_ci  if (show_version_info)
1250e5c31af7Sopenharmony_ci    DumpPhysicalDeviceInfo();
1251e5c31af7Sopenharmony_ci
1252e5c31af7Sopenharmony_ci  r = CreateVulkanDevice(required_features, required_device_extensions);
1253e5c31af7Sopenharmony_ci  if (!r.IsSuccess())
1254e5c31af7Sopenharmony_ci    return r;
1255e5c31af7Sopenharmony_ci
1256e5c31af7Sopenharmony_ci  vkGetDeviceQueue(vulkan_device_, vulkan_queue_family_index_, 0,
1257e5c31af7Sopenharmony_ci                   &vulkan_queue_);
1258e5c31af7Sopenharmony_ci
1259e5c31af7Sopenharmony_ci  *cfg_holder =
1260e5c31af7Sopenharmony_ci      std::unique_ptr<amber::EngineConfig>(new amber::VulkanEngineConfig());
1261e5c31af7Sopenharmony_ci  amber::VulkanEngineConfig* config =
1262e5c31af7Sopenharmony_ci      static_cast<amber::VulkanEngineConfig*>(cfg_holder->get());
1263e5c31af7Sopenharmony_ci  config->physical_device = vulkan_physical_device_;
1264e5c31af7Sopenharmony_ci  config->available_features = available_features_;
1265e5c31af7Sopenharmony_ci  config->available_features2 = available_features2_;
1266e5c31af7Sopenharmony_ci  config->available_instance_extensions = available_instance_extensions_;
1267e5c31af7Sopenharmony_ci  config->available_device_extensions = available_device_extensions_;
1268e5c31af7Sopenharmony_ci  config->instance = vulkan_instance_;
1269e5c31af7Sopenharmony_ci  config->queue_family_index = vulkan_queue_family_index_;
1270e5c31af7Sopenharmony_ci  config->queue = vulkan_queue_;
1271e5c31af7Sopenharmony_ci  config->device = vulkan_device_;
1272e5c31af7Sopenharmony_ci  config->vkGetInstanceProcAddr = vkGetInstanceProcAddr;
1273e5c31af7Sopenharmony_ci
1274e5c31af7Sopenharmony_ci  return {};
1275e5c31af7Sopenharmony_ci}
1276e5c31af7Sopenharmony_ci
1277e5c31af7Sopenharmony_ci}  // namespace sample
1278