diff --git a/backends/vulkan/runtime/vk_api/Adapter.cpp b/backends/vulkan/runtime/vk_api/Adapter.cpp index b2be214c6fe..91e32e3ba77 100644 --- a/backends/vulkan/runtime/vk_api/Adapter.cpp +++ b/backends/vulkan/runtime/vk_api/Adapter.cpp @@ -73,9 +73,15 @@ VkDevice create_logical_device( #ifdef VK_ANDROID_external_memory_android_hardware_buffer VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, #endif /* VK_ANDROID_external_memory_android_hardware_buffer */ +#ifdef VK_KHR_16bit_storage VK_KHR_16BIT_STORAGE_EXTENSION_NAME, +#endif /* VK_KHR_16bit_storage */ +#ifdef VK_KHR_8bit_storage VK_KHR_8BIT_STORAGE_EXTENSION_NAME, +#endif /* VK_KHR_8bit_storage */ +#ifdef VK_KHR_shader_float16_int8 VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, +#endif /* VK_KHR_shader_float16_int8 */ }; std::vector enabled_device_extensions; @@ -240,6 +246,7 @@ std::string Adapter::stringize() const { PRINT_PROP_VEC3(limits, maxComputeWorkGroupSize); ss << " }" << std::endl; +#ifdef VK_KHR_16bit_storage ss << " 16bit Storage Features {" << std::endl; PRINT_PROP(physical_device_.shader_16bit_storage, storageBuffer16BitAccess); PRINT_PROP( @@ -248,18 +255,23 @@ std::string Adapter::stringize() const { PRINT_PROP(physical_device_.shader_16bit_storage, storagePushConstant16); PRINT_PROP(physical_device_.shader_16bit_storage, storageInputOutput16); ss << " }" << std::endl; +#endif /* VK_KHR_16bit_storage */ +#ifdef VK_KHR_8bit_storage ss << " 8bit Storage Features {" << std::endl; PRINT_PROP(physical_device_.shader_8bit_storage, storageBuffer8BitAccess); PRINT_PROP( physical_device_.shader_8bit_storage, uniformAndStorageBuffer8BitAccess); PRINT_PROP(physical_device_.shader_8bit_storage, storagePushConstant8); ss << " }" << std::endl; +#endif /* VK_KHR_8bit_storage */ +#ifdef VK_KHR_shader_float16_int8 ss << " Shader 16bit and 8bit Features {" << std::endl; PRINT_PROP(physical_device_.shader_float16_int8_types, shaderFloat16); PRINT_PROP(physical_device_.shader_float16_int8_types, shaderInt8); ss << " }" << std::endl; +#endif /* VK_KHR_shader_float16_int8 */ const VkPhysicalDeviceMemoryProperties& mem_props = physical_device_.memory_properties; diff --git a/backends/vulkan/runtime/vk_api/Adapter.h b/backends/vulkan/runtime/vk_api/Adapter.h index 635502ca2b2..26d024de2b8 100644 --- a/backends/vulkan/runtime/vk_api/Adapter.h +++ b/backends/vulkan/runtime/vk_api/Adapter.h @@ -156,21 +156,37 @@ class Adapter final { // Physical Device Features inline bool supports_16bit_storage_buffers() { +#ifdef VK_KHR_16bit_storage return physical_device_.shader_16bit_storage.storageBuffer16BitAccess == VK_TRUE; +#else + return false; +#endif /* VK_KHR_16bit_storage */ } inline bool supports_8bit_storage_buffers() { +#ifdef VK_KHR_8bit_storage return physical_device_.shader_8bit_storage.storageBuffer8BitAccess == VK_TRUE; +#else + return false; +#endif /* VK_KHR_8bit_storage */ } inline bool supports_float16_shader_types() { +#ifdef VK_KHR_shader_float16_int8 return physical_device_.shader_float16_int8_types.shaderFloat16 == VK_TRUE; +#else + return false; +#endif /* VK_KHR_shader_float16_int8 */ } inline bool supports_int8_shader_types() { +#ifdef VK_KHR_shader_float16_int8 return physical_device_.shader_float16_int8_types.shaderInt8 == VK_TRUE; +#else + return false; +#endif /* VK_KHR_shader_float16_int8 */ } inline bool supports_int16_shader_types() { diff --git a/backends/vulkan/runtime/vk_api/Device.cpp b/backends/vulkan/runtime/vk_api/Device.cpp index 08d4565dbab..01af8687a3e 100644 --- a/backends/vulkan/runtime/vk_api/Device.cpp +++ b/backends/vulkan/runtime/vk_api/Device.cpp @@ -22,19 +22,27 @@ PhysicalDevice::PhysicalDevice(VkPhysicalDevice physical_device_handle) : handle(physical_device_handle), properties{}, memory_properties{}, +#ifdef VK_KHR_16bit_storage + extension_features(&shader_16bit_storage), shader_16bit_storage{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES}, +#else + extension_features{nullptr}, +#endif /* VK_KHR_16bit_storage */ +#ifdef VK_KHR_8bit_storage shader_8bit_storage{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES}, +#endif /* VK_KHR_8bit_storage */ +#ifdef VK_KHR_shader_float16_int8 shader_float16_int8_types{ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR}, +#endif /* VK_KHR_shader_float16_int8 */ queue_families{}, num_compute_queues(0), supports_int16_shader_types(false), has_unified_memory(false), has_timestamps(properties.limits.timestampComputeAndGraphics), - timestamp_period(properties.limits.timestampPeriod), - extension_features(&shader_16bit_storage) { + timestamp_period(properties.limits.timestampPeriod) { // Extract physical device properties vkGetPhysicalDeviceProperties(handle, &properties); vkGetPhysicalDeviceMemoryProperties(handle, &memory_properties); @@ -43,10 +51,32 @@ PhysicalDevice::PhysicalDevice(VkPhysicalDevice physical_device_handle) VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2}; // Create linked list to query availability of extensions + +#ifdef VK_KHR_16bit_storage features2.pNext = &shader_16bit_storage; +#elif defined(VK_KHR_8bit_storage) + features2.pNext = &shader_8bit_storage; +#elif defined(VK_KHR_shader_float16_int8) + features2.pNext = &shader_float16_int8_types; +#endif /* VK_KHR_16bit_storage */ + +#if defined(VK_KHR_16bit_storage) && defined(VK_KHR_8bit_storage) shader_16bit_storage.pNext = &shader_8bit_storage; +#elif defined(VK_KHR_16bit_storage) && defined(VK_KHR_shader_float16_int8) + shader_16bit_storage.pNext = &shader_float16_int8_types; +#elif defined(VK_KHR_16bit_storage) + shader_16bit_storage.pNext = nullptr; +#endif + +#if defined(VK_KHR_8bit_storage) && defined(VK_KHR_shader_float16_int8) shader_8bit_storage.pNext = &shader_float16_int8_types; +#elif defined(VK_KHR_8bit_storage) + shader_8bit_storage.pNext = nullptr; +#endif + +#ifdef VK_KHR_shader_float16_int8 shader_float16_int8_types.pNext = nullptr; +#endif vkGetPhysicalDeviceFeatures2(handle, &features2); diff --git a/backends/vulkan/runtime/vk_api/Device.h b/backends/vulkan/runtime/vk_api/Device.h index 6d6e28857af..6dee9119a39 100644 --- a/backends/vulkan/runtime/vk_api/Device.h +++ b/backends/vulkan/runtime/vk_api/Device.h @@ -25,10 +25,20 @@ struct PhysicalDevice final { // Properties obtained from Vulkan VkPhysicalDeviceProperties properties; VkPhysicalDeviceMemoryProperties memory_properties; + + // Head of the linked list of extensions to be requested + void* extension_features{nullptr}; + // Additional features available from extensions +#ifdef VK_KHR_16bit_storage VkPhysicalDevice16BitStorageFeatures shader_16bit_storage; +#endif /* VK_KHR_16bit_storage */ +#ifdef VK_KHR_8bit_storage VkPhysicalDevice8BitStorageFeatures shader_8bit_storage; +#endif /* VK_KHR_8bit_storage */ +#ifdef VK_KHR_shader_float16_int8 VkPhysicalDeviceShaderFloat16Int8Features shader_float16_int8_types; +#endif /* VK_KHR_shader_float16_int8 */ // Available GPU queues std::vector queue_families; @@ -40,9 +50,6 @@ struct PhysicalDevice final { bool has_timestamps; float timestamp_period; - // Head of the linked list of extensions to be requested - void* extension_features{nullptr}; - explicit PhysicalDevice(VkPhysicalDevice); }; diff --git a/backends/vulkan/targets.bzl b/backends/vulkan/targets.bzl index 267628cd18e..ed98e19b13b 100644 --- a/backends/vulkan/targets.bzl +++ b/backends/vulkan/targets.bzl @@ -4,7 +4,7 @@ load("@fbsource//xplat/executorch/build:runtime_wrapper.bzl", "runtime") def get_vulkan_compiler_flags(): return ["-Wno-missing-prototypes", "-Wno-global-constructors"] -def vulkan_spv_shader_lib(name, spv_filegroups, is_fbcode = False): +def vulkan_spv_shader_lib(name, spv_filegroups, is_fbcode = False, no_volk = False): gen_vulkan_spv_target = "//xplat/executorch/backends/vulkan:gen_vulkan_spv_bin" glslc_path = "//xplat/caffe2/fb/vulkan/dotslash:glslc" @@ -42,6 +42,7 @@ def vulkan_spv_shader_lib(name, spv_filegroups, is_fbcode = False): labels = ["uses_dotslash"], ) + suffix = "_no_volk" if no_volk else "" runtime.cxx_library( name = name, srcs = [ @@ -56,7 +57,7 @@ def vulkan_spv_shader_lib(name, spv_filegroups, is_fbcode = False): # Define a soname that can be used for dynamic loading in Java, Python, etc. soname = "lib{}.$(ext)".format(name), exported_deps = [ - "//executorch/backends/vulkan:vulkan_compute_api", + "//executorch/backends/vulkan:vulkan_compute_api{}".format(suffix), ], ) @@ -89,126 +90,136 @@ def define_common_targets(is_fbcode = False): ]), ) - vulkan_spv_shader_lib( - name = "vulkan_graph_runtime_shaderlib", - spv_filegroups = { - ":vulkan_graph_runtime_shaders": "runtime/graph/ops/glsl", - }, - is_fbcode = is_fbcode, - ) + for no_volk in [True, False]: + suffix = "_no_volk" if no_volk else "" - VK_API_PREPROCESSOR_FLAGS = [] - VK_API_DEPS = [ - "fbsource//third-party/VulkanMemoryAllocator/3.0.1:VulkanMemoryAllocator_xplat", - ] + VK_API_PREPROCESSOR_FLAGS = [] + VK_API_DEPS = [ + "fbsource//third-party/VulkanMemoryAllocator/3.0.1:VulkanMemoryAllocator_xplat", + ] - if is_fbcode: - VK_API_DEPS += [ - "fbsource//third-party/swiftshader:swiftshader_vk_headers", - "fbsource//third-party/swiftshader/lib/linux-x64:libvk_swiftshader_fbcode", - "fbsource//third-party/swiftshader/lib/linux-x64:libvk_swiftshader_so", + default_deps = [] + android_deps = [ + "fbsource//third-party/toolchains:android", ] - else: - VK_API_DEPS += select({ - "DEFAULT": [ - "fbsource//third-party/volk:volk", - ], - "ovr_config//os:android": [ - "fbsource//third-party/volk:volk", - "fbsource//third-party/toolchains:android" - ], - "ovr_config//os:macos": [ - "//third-party/khronos:moltenVK_static" + default_flags = [] + android_flags = [] + + if not no_volk: + for deps in [default_deps, android_deps]: + deps.append("fbsource//third-party/volk:volk") + for flags in [default_flags, android_flags]: + flags.append("-DUSE_VULKAN_WRAPPER") + flags.append("-DUSE_VULKAN_VOLK") + android_flags.append("-DVK_ANDROID_external_memory_android_hardware_buffer") + else: + android_deps.append("fbsource//third-party/toolchains:vulkan") + + if is_fbcode: + VK_API_DEPS += [ + "fbsource//third-party/swiftshader:swiftshader_vk_headers", + "fbsource//third-party/swiftshader/lib/linux-x64:libvk_swiftshader_fbcode", + "fbsource//third-party/swiftshader/lib/linux-x64:libvk_swiftshader_so", + ] + else: + VK_API_DEPS += select({ + "DEFAULT": default_deps, + "ovr_config//os:android": android_deps, + "ovr_config//os:macos": [ + "//third-party/khronos:moltenVK_static" + ], + }) + VK_API_PREPROCESSOR_FLAGS += select({ + "DEFAULT": default_flags, + "ovr_config//os:android": android_flags, + "ovr_config//os:macos-arm64": [] + }) + + runtime.cxx_library( + name = "vulkan_compute_api{}".format(suffix), + compiler_flags = get_vulkan_compiler_flags(), + srcs = native.glob([ + "runtime/api/**/*.cpp", + "runtime/utils/**/*.cpp", + "runtime/vk_api/**/*.cpp", + ]), + exported_headers = native.glob([ + "runtime/api/**/*.h", + "runtime/utils/**/*.h", + "runtime/vk_api/**/*.h", + ]), + visibility = [ + "//executorch/backends/vulkan/...", + "@EXECUTORCH_CLIENTS", ], - }) - VK_API_PREPROCESSOR_FLAGS += select({ - "DEFAULT": [ - "-DUSE_VULKAN_WRAPPER", - "-DUSE_VULKAN_VOLK", + exported_preprocessor_flags = VK_API_PREPROCESSOR_FLAGS, + exported_deps = VK_API_DEPS, + ) + + runtime.cxx_library( + name = "vulkan_graph_runtime{}".format(suffix), + srcs = native.glob([ + "runtime/graph/**/*.cpp", + ]), + compiler_flags = get_vulkan_compiler_flags(), + exported_headers = native.glob([ + "runtime/graph/**/*.h", + ]), + visibility = [ + "//executorch/backends/...", + "//executorch/extension/pybindings/...", + "//executorch/test/...", + "@EXECUTORCH_CLIENTS", ], - "ovr_config//os:android": [ - "-DUSE_VULKAN_WRAPPER", - "-DUSE_VULKAN_VOLK", - "-DVK_ANDROID_external_memory_android_hardware_buffer" + exported_deps = [ + ":vulkan_graph_runtime_shaderlib{}".format(suffix), ], - "ovr_config//os:macos": [] - }) + define_static_target = False, + # Static initialization is used to register operators to the global operator registry, + # therefore link_whole must be True to make sure unused symbols are not discarded. + # @lint-ignore BUCKLINT: Avoid `link_whole=True` + link_whole = True, + # Define an soname that can be used for dynamic loading in Java, Python, etc. + soname = "libvulkan_graph_runtime.$(ext)", + ) - runtime.cxx_library( - name = "vulkan_compute_api", - compiler_flags = get_vulkan_compiler_flags(), - srcs = native.glob([ - "runtime/api/**/*.cpp", - "runtime/utils/**/*.cpp", - "runtime/vk_api/**/*.cpp", - ]), - exported_headers = native.glob([ - "runtime/api/**/*.h", - "runtime/utils/**/*.h", - "runtime/vk_api/**/*.h", - ]), - visibility = [ - "//executorch/backends/vulkan/...", - "@EXECUTORCH_CLIENTS", - ], - exported_preprocessor_flags = VK_API_PREPROCESSOR_FLAGS, - exported_deps = VK_API_DEPS, - ) + vulkan_spv_shader_lib( + name = "vulkan_graph_runtime_shaderlib{}".format(suffix), + spv_filegroups = { + ":vulkan_graph_runtime_shaders": "runtime/graph/ops/glsl", + }, + is_fbcode = is_fbcode, + no_volk = no_volk, + ) - runtime.cxx_library( - name = "vulkan_graph_runtime", - srcs = native.glob([ - "runtime/graph/**/*.cpp", - ]), - compiler_flags = get_vulkan_compiler_flags(), - exported_headers = native.glob([ - "runtime/graph/**/*.h", - ]), - visibility = [ - "//executorch/backends/...", - "//executorch/extension/pybindings/...", - "//executorch/test/...", - "@EXECUTORCH_CLIENTS", - ], - exported_deps = [ - ":vulkan_graph_runtime_shaderlib", - ], - define_static_target = False, - # Static initialization is used to register operators to the global operator registry, - # therefore link_whole must be True to make sure unused symbols are not discarded. - # @lint-ignore BUCKLINT: Avoid `link_whole=True` - link_whole = True, - # Define an soname that can be used for dynamic loading in Java, Python, etc. - soname = "libvulkan_graph_runtime.$(ext)", - ) - runtime.cxx_library( - name = "vulkan_backend_lib", - srcs = native.glob([ - "runtime/*.cpp", - ]), - compiler_flags = get_vulkan_compiler_flags(), - headers = native.glob([ - "runtime/*.h", - ]), - visibility = [ - "//executorch/backends/...", - "//executorch/extension/pybindings/...", - "//executorch/test/...", - "@EXECUTORCH_CLIENTS", - ], - deps = [ - ":vulkan_graph_runtime", - "//executorch/backends/vulkan/serialization:vk_delegate_schema", - "//executorch/runtime/core:event_tracer", - "//executorch/runtime/backend:interface", - "//executorch/runtime/core/exec_aten/util:tensor_util", - ], - define_static_target = False, - # VulkanBackend.cpp needs to compile with executor as whole - # @lint-ignore BUCKLINT: Avoid `link_whole=True` (https://fburl.com/avoid-link-whole) - link_whole = True, - ) + runtime.cxx_library( + name = "vulkan_backend_lib{}".format(suffix), + srcs = native.glob([ + "runtime/*.cpp", + ]), + compiler_flags = get_vulkan_compiler_flags(), + headers = native.glob([ + "runtime/*.h", + ]), + visibility = [ + "//executorch/backends/...", + "//executorch/extension/pybindings/...", + "//executorch/test/...", + "@EXECUTORCH_CLIENTS", + ], + deps = [ + ":vulkan_graph_runtime{}".format(suffix), + "//executorch/backends/vulkan/serialization:vk_delegate_schema", + "//executorch/runtime/core:event_tracer", + "//executorch/runtime/backend:interface", + "//executorch/runtime/core/exec_aten/util:tensor_util", + ], + define_static_target = False, + # VulkanBackend.cpp needs to compile with executor as whole + # @lint-ignore BUCKLINT: Avoid `link_whole=True` (https://fburl.com/avoid-link-whole) + link_whole = True, + ) ## ## AOT targets diff --git a/backends/vulkan/test/compute_api_tests.bzl b/backends/vulkan/test/compute_api_tests.bzl new file mode 100644 index 00000000000..233df6a6279 --- /dev/null +++ b/backends/vulkan/test/compute_api_tests.bzl @@ -0,0 +1,63 @@ +load("@fbsource//tools/build_defs:fb_xplat_cxx_binary.bzl", "fb_xplat_cxx_binary") +load("@fbsource//tools/build_defs:fb_xplat_cxx_test.bzl", "fb_xplat_cxx_test") +load("@fbsource//tools/build_defs:platform_defs.bzl", "ANDROID", "MACOSX") +load( + "@fbsource//xplat/executorch/backends/vulkan:targets.bzl", + "vulkan_spv_shader_lib", +) + +def define_compute_api_test_targets(): + for no_volk in [True, False]: + suffix = "_no_volk" if no_volk else "" + vulkan_spv_shader_lib( + name = "test_shader_lib{}".format(suffix), + spv_filegroups = { + ":test_shaders": "glsl", + }, + no_volk = no_volk, + ) + + fb_xplat_cxx_binary( + name = "vulkan_compute_api_test_bin{}".format(suffix), + srcs = [ + "utils/test_utils.cpp", + "vulkan_compute_api_test.cpp", + ], + headers = [ + "utils/test_utils.h", + ], + apple_sdks = MACOSX, + visibility = ["PUBLIC"], + deps = [ + ":test_shader_lib{}".format(suffix), + "//third-party/googletest:gtest_main", + "//xplat/executorch/backends/vulkan:vulkan_graph_runtime{}".format(suffix), + "//xplat/executorch/runtime/core/exec_aten:lib", + ], + ) + + fb_xplat_cxx_test( + name = "vulkan_compute_api_test{}".format(suffix), + srcs = [ + "utils/test_utils.cpp", + "vulkan_compute_api_test.cpp", + ], + headers = [ + "utils/test_utils.h", + ], + contacts = ["oncall+ai_infra_mobile_platform@xmail.facebook.com"], + fbandroid_additional_loaded_sonames = [ + "test_shader_lib", + "vulkan_graph_runtime", + "vulkan_graph_runtime_shaderlib", + ], + platforms = [ANDROID], + use_instrumentation_test = True, + visibility = ["PUBLIC"], + deps = [ + ":test_shader_lib", + "//third-party/googletest:gtest_main", + "//xplat/executorch/backends/vulkan:vulkan_graph_runtime{}".format(suffix), + "//xplat/executorch/runtime/core/exec_aten:lib", + ], + )