# See the License for the specific language governing permissions and
# limitations under the License.
+import("//build_overrides/build.gni")
import("//build_overrides/vulkan_loader.gni")
-# Fuchsia has non-upstream changes to the vulkan loader, so we don't want
-# to build it from upstream sources.
-assert(!is_fuchsia)
+if (is_fuchsia) {
+ import("//build/cpp/sdk_shared_library.gni")
+ import("//build/sdk/sdk_documentation.gni")
+}
if (!is_android) {
vulkan_undefine_configs = []
config("vulkan_internal_config") {
defines = [ "VULKAN_NON_CMAKE_BUILD" ]
if (is_clang || !is_win) {
- cflags = [ "-Wno-unused-function" ]
+ cflags = [
+ "-Wno-conversion",
+ "-Wno-extra-semi",
+ "-Wno-sign-compare",
+ "-Wno-unreachable-code",
+ "-Wno-unused-function",
+ "-Wno-unused-variable",
+ ]
+ }
+ if (is_fuchsia) {
+ defines += [
+ "SYSCONFDIR=\"/config\"",
+ "EXTRASYSCONFDIR=\"/pkg/data\"",
+ ]
}
if (is_linux || is_mac) {
defines += [
}
if (!is_android) {
- if (vulkan_loader_shared) {
+ if (is_fuchsia) {
+ library_type = "sdk_shared_library"
+ } else if (vulkan_loader_shared) {
library_type = "shared_library"
} else {
library_type = "static_library"
frameworks = [ "CoreFoundation.framework" ]
}
public_deps = [ "$vulkan_headers_dir:vulkan_headers" ]
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
+ if (build_with_chromium) {
+ configs -= [ "//build/config/compiler:chromium_code" ]
+ configs += [ "//build/config/compiler:no_chromium_code" ]
+ }
configs += [ ":vulkan_internal_config" ]
public_configs = [ ":vulkan_loader_config" ]
configs -= vulkan_undefine_configs
+
+ if (is_fuchsia) {
+ output_name = "vulkan"
+ category = "partner"
+
+ # The Vulkan loader's interface is defined by standard Khronos vulkan headers
+ # which can be obtained separately from the loader implementation itself.
+ no_headers = true
+
+ deps = [
+ ":dlopen_fuchsia",
+ "//sdk/lib/fdio",
+ ]
+
+ runtime_deps = [ "//sdk/lib/fdio:fdio_sdk" ]
+ }
}
if (is_linux && vulkan_loader_shared) {
}
}
}
+
+if (is_fuchsia) {
+ config("fuchsia_config") {
+ include_dirs = [ "fuchsia" ]
+ }
+
+ source_set("dlopen_fuchsia") {
+ public_configs = [ ":fuchsia_config" ]
+
+ sources = [
+ "fuchsia/dlopen_fuchsia.c",
+ "fuchsia/dlopen_fuchsia.h",
+ ]
+
+ deps = [
+ "//sdk/fidl/fuchsia.vulkan.loader:fuchsia.vulkan.loader_c_client",
+ "//sdk/lib/fdio",
+ ]
+ }
+
+ sdk_documentation("vulkan_license") {
+ name = "vulkan_license"
+ category = "public"
+
+ files = [
+ {
+ source = "LICENSE.txt"
+ dest = "LICENSE.vulkan"
+ },
+ ]
+ }
+}
1. [Windows Build](#building-on-windows)
1. [Linux Build](#building-on-linux)
1. [MacOS build](#building-on-macos)
+1. [Fuchsia build](#building-on-fuchsia)
## Contributing to the Repository
Vulkan-Loader repository, and run:
./vk_loader_validation_tests
+
+## Building on Fuchsia
+
+Fuchsia uses the project's GN build system to integrate with the Fuchsia platform build.
+
+### SDK Symbols
+
+The Vulkan Loader is a component of the Fuchsia SDK, so it must explicitly declare its exported symbols in
+the file vulkan.symbols.api; see [SDK](https://fuchsia.dev/fuchsia-src/development/sdk).
--- /dev/null
+/*
+ *
+ * Copyright (c) 2018 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "dlopen_fuchsia.h"
+
+#include <fcntl.h>
+#include <fuchsia/vulkan/loader/c/fidl.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/directory.h>
+#include <stdio.h>
+#include <string.h>
+#include <threads.h>
+#include <zircon/dlfcn.h>
+#include <zircon/syscalls.h>
+
+static char g_error[128] = {};
+
+const char *dlerror_fuchsia(void) { return g_error; }
+
+static zx_handle_t vulkan_loader_svc = ZX_HANDLE_INVALID;
+void connect_to_vulkan_loader_svc(void) {
+ zx_handle_t svc1, svc2;
+ if (zx_channel_create(0, &svc1, &svc2) != ZX_OK) return;
+
+ if (fdio_service_connect("/svc/" fuchsia_vulkan_loader_Loader_Name, svc1) != ZX_OK) {
+ zx_handle_close(svc2);
+ return;
+ }
+
+ vulkan_loader_svc = svc2;
+}
+
+static once_flag svc_connect_once_flag = ONCE_FLAG_INIT;
+
+void *dlopen_fuchsia(const char *name, int mode, bool driver) {
+ // First try to just dlopen() from our own namespace. This will succeed for
+ // any layers that are packaged with the application, but will fail for
+ // client drivers loaded from the system.
+ void *result;
+ if (!driver) {
+ result = dlopen(name, mode);
+ if (result != NULL) return result;
+ }
+
+ // If we couldn't find the library in our own namespace, connect to the
+ // loader service to request this library.
+ call_once(&svc_connect_once_flag, connect_to_vulkan_loader_svc);
+
+ if (vulkan_loader_svc == ZX_HANDLE_INVALID) {
+ snprintf(g_error, sizeof(g_error), "libvulkan.so:dlopen_fuchsia: no connection to loader svc\n");
+ return NULL;
+ }
+
+ zx_handle_t vmo = ZX_HANDLE_INVALID;
+ zx_status_t st = fuchsia_vulkan_loader_LoaderGet(vulkan_loader_svc, name, strlen(name), &vmo);
+ if (st != ZX_OK) {
+ snprintf(g_error, sizeof(g_error), "libvulkan.so:dlopen_fuchsia: Get() failed: %d\n", st);
+ return NULL;
+ }
+
+ if (vmo == ZX_HANDLE_INVALID) {
+ snprintf(g_error, sizeof(g_error), "libvulkan.so:dlopen_fuchsia: Get() returned invalid vmo\n");
+ return NULL;
+ }
+
+ result = dlopen_vmo(vmo, mode);
+ zx_handle_close(vmo);
+ if (!result) {
+ snprintf(g_error, sizeof(g_error), "%s", dlerror());
+ }
+ return result;
+}
--- /dev/null
+/*
+ *
+ * Copyright (c) 2018 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#pragma once
+
+#include <zircon/compiler.h>
+#include <stdbool.h>
+
+__BEGIN_CDECLS
+
+// If not |driver|, then the request is to load a layer.
+void *dlopen_fuchsia(const char *name, int mode, bool driver);
+const char *dlerror_fuchsia(void);
+
+__END_CDECLS
}
// Environment variables
-#if defined(__linux__) || defined(__APPLE__)
+#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__)
static inline bool IsHighIntegrity() {
return geteuid() != getuid() || getegid() != getgid();
// This algorithm is derived from glibc code that sets an internal
// variable (__libc_enable_secure) if the process is running under setuid or setgid.
return IsHighIntegrity() ? NULL : loader_getenv(name, inst);
+#elif defined(__Fuchsia__)
+ return loader_getenv(name, inst);
#else
// Linux
#if defined(HAVE_SECURE_GETENV) && !defined(USE_UNSAFE_FILE_SEARCH)
// TODO implement smarter opening/closing of libraries. For now this
// function leaves libraries open and the scanned_icd_clear closes them
+#if defined(__Fuchsia__)
+ handle = loader_platform_open_driver(filename);
+#else
handle = loader_platform_open_library(filename);
+#endif
if (NULL == handle) {
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, loader_platform_open_library_error(filename));
goto out;
if (xdgdatadirs == NULL) {
xdgdata_alloc = false;
}
+#if !defined(__Fuchsia__)
if (xdgconfdirs == NULL || xdgconfdirs[0] == '\0') {
xdgconfdirs = FALLBACK_CONFIG_DIRS;
}
if (xdgdatadirs == NULL || xdgdatadirs[0] == '\0') {
xdgdatadirs = FALLBACK_DATA_DIRS;
}
+#endif
// Only use HOME if XDG_DATA_HOME is not present on the system
if (NULL == xdgdatahome) {
static VkResult ReadDataFilesInRegistry(const struct loader_instance *inst, enum loader_data_files_type data_file_type,
bool warn_if_not_present, char *registry_location, struct loader_data_files *out_files) {
VkResult vk_result = VK_SUCCESS;
- bool is_icd = (data_file_type == LOADER_DATA_FILE_MANIFEST_ICD);
char *search_path = NULL;
// These calls look at the PNP/Device section of the registry.
#include <winsock2.h>
#endif // _WIN32
+#if defined(__Fuchsia__)
+#include "dlopen_fuchsia.h"
+#endif // defined(__Fuchsia__)
+
#include "vulkan/vk_platform.h"
#include "vulkan/vk_sdk_platform.h"
-#if defined(__linux__) || defined(__APPLE__)
+#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__)
/* Linux-specific common code: */
// Headers:
buffer[ret] = '\0';
return buffer;
}
+#elif defined(__Fuchsia__)
+static inline char *loader_platform_executable_path(char *buffer, size_t size) { return NULL; }
#endif // defined (__APPLE__)
// Compatability with compilers that don't support __has_feature
// Dynamic Loading of libraries:
typedef void *loader_platform_dl_handle;
-static inline loader_platform_dl_handle loader_platform_open_library(const char *libPath) {
// When loading the library, we use RTLD_LAZY so that not all symbols have to be
// resolved at this time (which improves performance). Note that if not all symbols
// can be resolved, this could cause crashes later. Use the LD_BIND_NOW environment
// variable to force all symbols to be resolved here.
- return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
+#define LOADER_DLOPEN_MODE (RTLD_LAZY | RTLD_LOCAL)
+
+#if defined(__Fuchsia__)
+static inline loader_platform_dl_handle loader_platform_open_driver(const char *libPath) {
+ return dlopen_fuchsia(libPath, LOADER_DLOPEN_MODE, true);
+}
+static inline loader_platform_dl_handle loader_platform_open_library(const char *libPath) {
+ return dlopen_fuchsia(libPath, LOADER_DLOPEN_MODE, false);
+}
+#else
+static inline loader_platform_dl_handle loader_platform_open_library(const char *libPath) {
+ return dlopen(libPath, LOADER_DLOPEN_MODE);
+}
+#endif
+
+static inline const char *loader_platform_open_library_error(const char *libPath) {
+#ifdef __Fuchsia__
+ return dlerror_fuchsia();
+#else
+ return dlerror();
+#endif
}
-static inline const char *loader_platform_open_library_error(const char *libPath) { return dlerror(); }
static inline void loader_platform_close_library(loader_platform_dl_handle library) { dlclose(library); }
static inline void *loader_platform_get_proc_address(loader_platform_dl_handle library, const char *name) {
assert(library);
--- /dev/null
+vkAcquireNextImage2KHR
+vkAcquireNextImageKHR
+vkAllocateCommandBuffers
+vkAllocateDescriptorSets
+vkAllocateMemory
+vkBeginCommandBuffer
+vkBindBufferMemory
+vkBindBufferMemory2
+vkBindImageMemory
+vkBindImageMemory2
+vkCmdBeginQuery
+vkCmdBeginRenderPass
+vkCmdBeginRenderPass2
+vkCmdBindDescriptorSets
+vkCmdBindIndexBuffer
+vkCmdBindPipeline
+vkCmdBindVertexBuffers
+vkCmdBlitImage
+vkCmdClearAttachments
+vkCmdClearColorImage
+vkCmdClearDepthStencilImage
+vkCmdCopyBuffer
+vkCmdCopyBufferToImage
+vkCmdCopyImage
+vkCmdCopyImageToBuffer
+vkCmdCopyQueryPoolResults
+vkCmdDispatch
+vkCmdDispatchBase
+vkCmdDispatchIndirect
+vkCmdDraw
+vkCmdDrawIndexed
+vkCmdDrawIndexedIndirect
+vkCmdDrawIndexedIndirectCount
+vkCmdDrawIndirect
+vkCmdDrawIndirectCount
+vkCmdEndQuery
+vkCmdEndRenderPass
+vkCmdEndRenderPass2
+vkCmdExecuteCommands
+vkCmdFillBuffer
+vkCmdNextSubpass
+vkCmdNextSubpass2
+vkCmdPipelineBarrier
+vkCmdPushConstants
+vkCmdResetEvent
+vkCmdResetQueryPool
+vkCmdResolveImage
+vkCmdSetBlendConstants
+vkCmdSetDepthBias
+vkCmdSetDepthBounds
+vkCmdSetDeviceMask
+vkCmdSetEvent
+vkCmdSetLineWidth
+vkCmdSetScissor
+vkCmdSetStencilCompareMask
+vkCmdSetStencilReference
+vkCmdSetStencilWriteMask
+vkCmdSetViewport
+vkCmdUpdateBuffer
+vkCmdWaitEvents
+vkCmdWriteTimestamp
+vkCreateBuffer
+vkCreateBufferView
+vkCreateCommandPool
+vkCreateComputePipelines
+vkCreateDescriptorPool
+vkCreateDescriptorSetLayout
+vkCreateDescriptorUpdateTemplate
+vkCreateDevice
+vkCreateDisplayModeKHR
+vkCreateDisplayPlaneSurfaceKHR
+vkCreateEvent
+vkCreateFence
+vkCreateFramebuffer
+vkCreateGraphicsPipelines
+vkCreateImage
+vkCreateImagePipeSurfaceFUCHSIA
+vkCreateImageView
+vkCreateInstance
+vkCreatePipelineCache
+vkCreatePipelineLayout
+vkCreateQueryPool
+vkCreateRenderPass
+vkCreateRenderPass2
+vkCreateSampler
+vkCreateSamplerYcbcrConversion
+vkCreateSemaphore
+vkCreateShaderModule
+vkCreateSharedSwapchainsKHR
+vkCreateSwapchainKHR
+vkDestroyBuffer
+vkDestroyBufferView
+vkDestroyCommandPool
+vkDestroyDescriptorPool
+vkDestroyDescriptorSetLayout
+vkDestroyDescriptorUpdateTemplate
+vkDestroyDevice
+vkDestroyEvent
+vkDestroyFence
+vkDestroyFramebuffer
+vkDestroyImage
+vkDestroyImageView
+vkDestroyInstance
+vkDestroyPipeline
+vkDestroyPipelineCache
+vkDestroyPipelineLayout
+vkDestroyQueryPool
+vkDestroyRenderPass
+vkDestroySampler
+vkDestroySamplerYcbcrConversion
+vkDestroySemaphore
+vkDestroyShaderModule
+vkDestroySurfaceKHR
+vkDestroySwapchainKHR
+vkDeviceWaitIdle
+vkEndCommandBuffer
+vkEnumerateDeviceExtensionProperties
+vkEnumerateDeviceLayerProperties
+vkEnumerateInstanceExtensionProperties
+vkEnumerateInstanceLayerProperties
+vkEnumerateInstanceVersion
+vkEnumeratePhysicalDeviceGroups
+vkEnumeratePhysicalDevices
+vkFlushMappedMemoryRanges
+vkFreeCommandBuffers
+vkFreeDescriptorSets
+vkFreeMemory
+vkGetBufferDeviceAddress
+vkGetBufferMemoryRequirements
+vkGetBufferMemoryRequirements2
+vkGetBufferOpaqueCaptureAddress
+vkGetDescriptorSetLayoutSupport
+vkGetDeviceGroupPeerMemoryFeatures
+vkGetDeviceGroupPresentCapabilitiesKHR
+vkGetDeviceGroupSurfacePresentModesKHR
+vkGetDeviceMemoryCommitment
+vkGetDeviceMemoryOpaqueCaptureAddress
+vkGetDeviceProcAddr
+vkGetDeviceQueue
+vkGetDeviceQueue2
+vkGetDisplayModeProperties2KHR
+vkGetDisplayModePropertiesKHR
+vkGetDisplayPlaneCapabilities2KHR
+vkGetDisplayPlaneCapabilitiesKHR
+vkGetDisplayPlaneSupportedDisplaysKHR
+vkGetEventStatus
+vkGetFenceStatus
+vkGetImageMemoryRequirements
+vkGetImageMemoryRequirements2
+vkGetImageSparseMemoryRequirements
+vkGetImageSparseMemoryRequirements2
+vkGetImageSubresourceLayout
+vkGetInstanceProcAddr
+vkGetPhysicalDeviceDisplayPlaneProperties2KHR
+vkGetPhysicalDeviceDisplayPlanePropertiesKHR
+vkGetPhysicalDeviceDisplayProperties2KHR
+vkGetPhysicalDeviceDisplayPropertiesKHR
+vkGetPhysicalDeviceExternalBufferProperties
+vkGetPhysicalDeviceExternalFenceProperties
+vkGetPhysicalDeviceExternalSemaphoreProperties
+vkGetPhysicalDeviceFeatures
+vkGetPhysicalDeviceFeatures2
+vkGetPhysicalDeviceFormatProperties
+vkGetPhysicalDeviceFormatProperties2
+vkGetPhysicalDeviceImageFormatProperties
+vkGetPhysicalDeviceImageFormatProperties2
+vkGetPhysicalDeviceMemoryProperties
+vkGetPhysicalDeviceMemoryProperties2
+vkGetPhysicalDevicePresentRectanglesKHR
+vkGetPhysicalDeviceProperties
+vkGetPhysicalDeviceProperties2
+vkGetPhysicalDeviceQueueFamilyProperties
+vkGetPhysicalDeviceQueueFamilyProperties2
+vkGetPhysicalDeviceSparseImageFormatProperties
+vkGetPhysicalDeviceSparseImageFormatProperties2
+vkGetPhysicalDeviceSurfaceCapabilities2KHR
+vkGetPhysicalDeviceSurfaceCapabilitiesKHR
+vkGetPhysicalDeviceSurfaceFormats2KHR
+vkGetPhysicalDeviceSurfaceFormatsKHR
+vkGetPhysicalDeviceSurfacePresentModesKHR
+vkGetPhysicalDeviceSurfaceSupportKHR
+vkGetPipelineCacheData
+vkGetQueryPoolResults
+vkGetRenderAreaGranularity
+vkGetSemaphoreCounterValue
+vkGetSwapchainImagesKHR
+vkInvalidateMappedMemoryRanges
+vkMapMemory
+vkMergePipelineCaches
+vkQueueBindSparse
+vkQueuePresentKHR
+vkQueueSubmit
+vkQueueWaitIdle
+vkResetCommandBuffer
+vkResetCommandPool
+vkResetDescriptorPool
+vkResetEvent
+vkResetFences
+vkResetQueryPool
+vkSetEvent
+vkSignalSemaphore
+vkTrimCommandPool
+vkUnmapMemory
+vkUpdateDescriptorSetWithTemplate
+vkUpdateDescriptorSets
+vkWaitForFences
+vkWaitSemaphores