Commit 5fd73782 by Tobin Ehlis Committed by Commit Bot

Vulkan: Use volk to load vk* func ptrs

Thanks to Jamie Madill for some fixes to get all CI test passing w/ volk. This change updates all ANGLE targets that use Vulkan to dyanmically link all of the VK entrypoints using the volk OSS library from https://github.com/zeux/volk. It's only two source files so baking them directly into ANGLE repo. Also it's used in both the tests and libANGLE trees so added to src/common/third_party/volk dir. Updated volk and the renderer to track latest instance and device that were loaded and renderer will refresh vk* function pointers if the current and previous device and/or instance don't match. This prevents errors in the test framework as we transition between backends, especially between VK HW & SwiftShader ICDs. This change rolls the Vulkan Loader forward to use the latest loader version which no longer allows static linking but requires dynamic linking. Bug: angleproject:3740 Bug: angleproject:4092 Bug: angleproject:4162 Bug: angleproject:4210 Bug: angleproject:4225 Change-Id: I8a0b7d24c9545bbfdfaa4b9357a9bfe6793e0140 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1965640 Commit-Queue: Tobin Ehlis <tobine@google.com> Reviewed-by: 's avatarTobin Ehlis <tobine@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 2eeb980e
......@@ -54,7 +54,7 @@ vars = {
'vulkan_headers_revision': '0e57fc1cfa56a203efe43e4dfb9b3c9e9b105593',
# Current revision of Khronos Vulkan-Loader.
'vulkan_loader_revision': '79e03670c2a328bea3c1a3f80ea913f296a487e6',
'vulkan_loader_revision': '2d6f74c6d4319e94cf1fa33954c619ab4428f2b8',
# Current revision of Khronos Vulkan-Tools.
'vulkan_tools_revision': '0c2618b2c31e2f216e131ff4c1c83e2c92c6ae66',
......
......@@ -7,4 +7,4 @@ import("//gni/angle.gni")
vulkan_headers_dir = "//third_party/vulkan-headers/src"
vulkan_gen_subdir = "angle/vulkan"
vulkan_loader_shared = angle_shared_libvulkan
vulkan_loader_shared = true
......@@ -41,13 +41,6 @@ qapitrace mytrace
## Running ANGLE under GAPID on Linux
[GAPID](https://github.com/google/gapid) can be used to capture trace of Vulkan commands on Linux.
For it to work, libvulkan has to be a shared library, instead of being statically linked into ANGLE,
which is the default behavior. This is done with the gn arg:
```
angle_shared_libvulkan = true
```
When capturing traces of gtest based tests built inside Chromium checkout, make sure to run the
tests with `--single-process-tests` argument.
......@@ -126,13 +119,6 @@ $ QT_SELECT=5 make -j -C build
$ ./build/bin/qrenderdoc
```
Additionally, libvulkan has to be a shared library, instead of being statically linked into ANGLE,
which is the default behavior. This is done with the gn arg:
```
angle_shared_libvulkan = true
```
If your distribution does not provide a recent Vulkan SDK package, you would need to manually
install that. This script tries to perform this installation as safely as possible. It would
overwrite the system package's files, so follow at your own risk. Place this script just above the
......
......@@ -69,7 +69,9 @@ declare_args() {
(!angle_64bit_current_cpu && android32_ndk_api_level >= 26) ||
(angle_64bit_current_cpu && android64_ndk_api_level >= 26)
}
angle_shared_libvulkan = false
# TODO(tobine): Remove this after roll. http://anglebug.com/4162
angle_shared_libvulkan = true
# There's no "is_winuwp" helper in BUILDCONFIG.gn, so we define one ourselves
angle_is_winuwp = is_win && current_os == "winuwp"
......
......@@ -160,6 +160,7 @@ config("angle_vulkan_lib_android") {
group("angle_vulkan_entry_points") {
public_configs = [ ":angle_vulkan_lib_android" ]
public_deps = [
"$angle_root/src/third_party/volk:volk",
"$angle_root/third_party/vulkan-headers/src:vulkan_headers",
]
if (is_fuchsia) {
......
......@@ -167,7 +167,7 @@ const char *GetStoreOpShorthand(uint32_t storeOp)
return "D";
}
}
#if !defined(ANGLE_PLATFORM_ANDROID)
void MakeDebugUtilsLabel(GLenum source, const char *marker, VkDebugUtilsLabelEXT *label)
{
static constexpr angle::ColorF kLabelColors[6] = {
......@@ -187,7 +187,7 @@ void MakeDebugUtilsLabel(GLenum source, const char *marker, VkDebugUtilsLabelEXT
label->pLabelName = marker;
kLabelColors[colorIndex].writeData(label->color);
}
#endif
constexpr VkSubpassContents kRenderPassContents =
CommandBuffer::ExecutesInline() ? VK_SUBPASS_CONTENTS_INLINE
: VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
......@@ -737,7 +737,7 @@ angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
case CommandGraphNodeFunction::InsertDebugMarker:
ASSERT(!mOutsideRenderPassCommands.valid() && !mInsideRenderPassCommands.valid());
#if !defined(ANGLE_PLATFORM_ANDROID)
if (vkCmdInsertDebugUtilsLabelEXT)
{
VkDebugUtilsLabelEXT label;
......@@ -745,11 +745,12 @@ angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
vkCmdInsertDebugUtilsLabelEXT(primaryCommandBuffer->getHandle(), &label);
}
#endif
break;
case CommandGraphNodeFunction::PushDebugMarker:
ASSERT(!mOutsideRenderPassCommands.valid() && !mInsideRenderPassCommands.valid());
#if !defined(ANGLE_PLATFORM_ANDROID)
if (vkCmdBeginDebugUtilsLabelEXT)
{
VkDebugUtilsLabelEXT label;
......@@ -757,15 +758,17 @@ angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
vkCmdBeginDebugUtilsLabelEXT(primaryCommandBuffer->getHandle(), &label);
}
#endif
break;
case CommandGraphNodeFunction::PopDebugMarker:
ASSERT(!mOutsideRenderPassCommands.valid() && !mInsideRenderPassCommands.valid());
#if !defined(ANGLE_PLATFORM_ANDROID)
if (vkCmdEndDebugUtilsLabelEXT)
{
vkCmdEndDebugUtilsLabelEXT(primaryCommandBuffer->getHandle());
}
#endif
break;
case CommandGraphNodeFunction::HostAvailabilityOperation:
......
......@@ -2526,6 +2526,7 @@ GLint64 ContextVk::getTimestamp()
angle::Result ContextVk::onMakeCurrent(const gl::Context *context)
{
mRenderer->reloadVolkIfNeeded();
ASSERT(mCommandGraph.empty());
// Flip viewports if FeaturesVk::flipViewportY is enabled and the user did not request that
......
......@@ -10,7 +10,7 @@
#ifndef LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
#define LIBANGLE_RENDERER_VULKAN_CONTEXTVK_H_
#include <vulkan/vulkan.h>
#include "volk.h"
#include "common/PackedEnums.h"
#include "libANGLE/renderer/ContextImpl.h"
......
......@@ -41,6 +41,8 @@ egl::Error DisplayVk::initialize(egl::Display *display)
void DisplayVk::terminate()
{
mRenderer->reloadVolkIfNeeded();
ASSERT(mRenderer);
mRenderer->onDestroy(this);
}
......
......@@ -9,8 +9,8 @@
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include <vulkan/vulkan.h>
#include <array>
#include "volk.h"
#include "common/debug.h"
#include "libANGLE/Context.h"
......
......@@ -7,7 +7,7 @@
#include "libANGLE/renderer/vulkan/MemoryObjectVk.h"
#include <vulkan/vulkan.h>
#include "volk.h"
#include "common/debug.h"
#include "libANGLE/Context.h"
......
......@@ -10,7 +10,7 @@
#ifndef LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_
#define LIBANGLE_RENDERER_VULKAN_RENDERTARGETVK_H_
#include <vulkan/vulkan.h>
#include "volk.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/renderer/renderer_utils.h"
......
......@@ -619,6 +619,8 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
const char *wsiExtension,
const char *wsiLayer)
{
// Set all vk* function ptrs
ANGLE_VK_TRY(displayVk, volkInitialize());
mDisplay = display;
const egl::AttributeMap &attribs = mDisplay->getAttributeMap();
ScopedVkLoaderEnvironment scopedEnvironment(ShouldUseValidationLayers(attribs),
......@@ -766,12 +768,11 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
instanceInfo.enabledLayerCount = static_cast<uint32_t>(enabledInstanceLayerNames.size());
instanceInfo.ppEnabledLayerNames = enabledInstanceLayerNames.data();
ANGLE_VK_TRY(displayVk, vkCreateInstance(&instanceInfo, nullptr, &mInstance));
volkLoadInstance(mInstance);
if (enableDebugUtils)
{
// Try to use the newer EXT_debug_utils if it exists.
InitDebugUtilsEXTFunctions(mInstance);
// Use the newer EXT_debug_utils if it exists.
// Create the messenger callback.
VkDebugUtilsMessengerCreateInfoEXT messengerInfo = {};
......@@ -796,8 +797,6 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
else if (enableDebugReport)
{
// Fallback to EXT_debug_report.
InitDebugReportEXTFunctions(mInstance);
VkDebugReportCallbackCreateInfoEXT debugReportInfo = {};
debugReportInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
......@@ -813,7 +812,6 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) !=
enabledInstanceExtensions.end())
{
InitGetPhysicalDeviceProperties2KHRFunctions(mInstance);
ASSERT(vkGetPhysicalDeviceProperties2KHR);
}
......@@ -1032,7 +1030,6 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME);
enabledDeviceExtensions.push_back(
VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME);
InitExternalMemoryHardwareBufferANDROIDFunctions(mInstance);
}
#else
ASSERT(!getFeatures().supportsAndroidHardwareBuffer.enabled);
......@@ -1046,7 +1043,6 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
if (getFeatures().supportsExternalSemaphoreFd.enabled)
{
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
InitExternalSemaphoreFdFunctions(mInstance);
}
if (getFeatures().supportsExternalSemaphoreFd.enabled)
......@@ -1136,16 +1132,12 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data();
ANGLE_VK_TRY(displayVk, vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice));
volkLoadDevice(mDevice);
mCurrentQueueFamilyIndex = queueFamilyIndex;
vkGetDeviceQueue(mDevice, mCurrentQueueFamilyIndex, 0, &mQueue);
if (supportsTransformFeedbackExt)
{
InitTransformFeedbackEXTFunctions(mDevice);
}
// Initialize the vulkan pipeline cache.
bool success = false;
ANGLE_TRY(initPipelineCache(displayVk, &mPipelineCache, &success));
......@@ -1818,4 +1810,17 @@ void RendererVk::onCompletedSerial(Serial serial)
mLastCompletedQueueSerial = serial;
}
}
void RendererVk::reloadVolkIfNeeded() const
{
if (volkGetLoadedInstance() != mInstance)
{
volkLoadInstance(mInstance);
}
if (volkGetLoadedDevice() != mDevice)
{
volkLoadDevice(mDevice);
}
}
} // namespace rx
......@@ -10,10 +10,10 @@
#ifndef LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
#define LIBANGLE_RENDERER_VULKAN_RENDERERVK_H_
#include <vulkan/vulkan.h>
#include <memory>
#include <mutex>
#include "vk_ext_provoking_vertex.h"
#include "volk.h"
#include "common/PoolAlloc.h"
#include "common/angleutils.h"
......@@ -68,6 +68,8 @@ class RendererVk : angle::NonCopyable
egl::Display *display,
const char *wsiExtension,
const char *wsiLayer);
// Reload volk vk* function ptrs if needed for an already initialized RendererVk
void reloadVolkIfNeeded() const;
void onDestroy(vk::Context *context);
void notifyDeviceLost();
......
......@@ -11,7 +11,7 @@
#ifndef LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_
#define LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_
#include <vulkan/vulkan.h>
#include "volk.h"
#include "common/PoolAlloc.h"
#include "libANGLE/renderer/vulkan/vk_wrapper.h"
......
......@@ -191,6 +191,8 @@ angle::Result OffscreenSurfaceVk::initializeImpl(DisplayVk *displayVk)
RendererVk *renderer = displayVk->getRenderer();
const egl::Config *config = mState.config;
renderer->reloadVolkIfNeeded();
GLint samples = GetSampleCount(mState.config);
ANGLE_VK_CHECK(displayVk, samples > 0, VK_ERROR_INITIALIZATION_FAILED);
......@@ -462,6 +464,8 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk)
{
RendererVk *renderer = displayVk->getRenderer();
renderer->reloadVolkIfNeeded();
gl::Extents windowSize;
ANGLE_TRY(createSurfaceVk(displayVk, &windowSize));
......
......@@ -10,7 +10,7 @@
#ifndef LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_
#define LIBANGLE_RENDERER_VULKAN_SURFACEVK_H_
#include <vulkan/vulkan.h>
#include "volk.h"
#include "libANGLE/renderer/SurfaceImpl.h"
#include "libANGLE/renderer/vulkan/RenderTargetVk.h"
......
......@@ -36,7 +36,6 @@ bool WindowSurfaceVkFuchsia::isValidNativeWindow(EGLNativeWindowType window)
angle::Result WindowSurfaceVkFuchsia::createSurfaceVk(vk::Context *context, gl::Extents *extentsOut)
{
InitImagePipeSurfaceFUCHSIAFunctions(context->getRenderer()->getInstance());
fuchsia_egl_window *egl_window = reinterpret_cast<fuchsia_egl_window *>(mNativeWindowType);
VkImagePipeSurfaceCreateInfoFUCHSIA createInfo = {};
......
......@@ -10,7 +10,7 @@
#ifndef LIBANGLE_RENDERER_VULKAN_VK_CAPS_UTILS_H_
#define LIBANGLE_RENDERER_VULKAN_VK_CAPS_UTILS_H_
#include <vulkan/vulkan.h>
#include "volk.h"
#include "libANGLE/Config.h"
......
......@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <vulkan/vulkan.h>
#include "volk.h"
// THIS FILE SHOULD BE DELETED IF VK_EXT_provoking_vertex IS EVER ADDED TO THE VULKAN HEADERS
#ifdef VK_EXT_provoking_vertex
......
......@@ -9,7 +9,7 @@
#ifndef LIBANGLE_RENDERER_VULKAN_VK_FORMAT_UTILS_H_
#define LIBANGLE_RENDERER_VULKAN_VK_FORMAT_UTILS_H_
#include <vulkan/vulkan.h>
#include "volk.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/Format.h"
......
......@@ -545,117 +545,6 @@ void GarbageObject::destroy(VkDevice device)
} // namespace vk
// VK_EXT_debug_utils
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = nullptr;
PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = nullptr;
PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT = nullptr;
PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT = nullptr;
PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT = nullptr;
// VK_EXT_debug_report
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = nullptr;
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = nullptr;
// VK_KHR_get_physical_device_properties2
PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = nullptr;
PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR = nullptr;
// VK_KHR_external_semaphore_fd
PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR = nullptr;
// VK_EXT_transform_feedback
PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT = nullptr;
PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT = nullptr;
PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT = nullptr;
PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT = nullptr;
PFN_vkCmdEndQueryIndexedEXT vkCmdEndQueryIndexedEXT = nullptr;
PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT = nullptr;
#if defined(ANGLE_PLATFORM_FUCHSIA)
// VK_FUCHSIA_imagepipe_surface
PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA = nullptr;
#endif
#define GET_INSTANCE_FUNC(vkName) \
do \
{ \
vkName = reinterpret_cast<PFN_##vkName>(vkGetInstanceProcAddr(instance, #vkName)); \
ASSERT(vkName); \
} while (0)
#define GET_DEVICE_FUNC(vkName) \
do \
{ \
vkName = reinterpret_cast<PFN_##vkName>(vkGetDeviceProcAddr(device, #vkName)); \
ASSERT(vkName); \
} while (0)
void InitDebugUtilsEXTFunctions(VkInstance instance)
{
GET_INSTANCE_FUNC(vkCreateDebugUtilsMessengerEXT);
GET_INSTANCE_FUNC(vkDestroyDebugUtilsMessengerEXT);
GET_INSTANCE_FUNC(vkCmdBeginDebugUtilsLabelEXT);
GET_INSTANCE_FUNC(vkCmdEndDebugUtilsLabelEXT);
GET_INSTANCE_FUNC(vkCmdInsertDebugUtilsLabelEXT);
}
void InitDebugReportEXTFunctions(VkInstance instance)
{
GET_INSTANCE_FUNC(vkCreateDebugReportCallbackEXT);
GET_INSTANCE_FUNC(vkDestroyDebugReportCallbackEXT);
}
void InitGetPhysicalDeviceProperties2KHRFunctions(VkInstance instance)
{
GET_INSTANCE_FUNC(vkGetPhysicalDeviceProperties2KHR);
GET_INSTANCE_FUNC(vkGetPhysicalDeviceFeatures2KHR);
}
void InitTransformFeedbackEXTFunctions(VkDevice device)
{
GET_DEVICE_FUNC(vkCmdBindTransformFeedbackBuffersEXT);
GET_DEVICE_FUNC(vkCmdBeginTransformFeedbackEXT);
GET_DEVICE_FUNC(vkCmdEndTransformFeedbackEXT);
GET_DEVICE_FUNC(vkCmdBeginQueryIndexedEXT);
GET_DEVICE_FUNC(vkCmdEndQueryIndexedEXT);
GET_DEVICE_FUNC(vkCmdDrawIndirectByteCountEXT);
}
#if defined(ANGLE_PLATFORM_FUCHSIA)
void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance)
{
GET_INSTANCE_FUNC(vkCreateImagePipeSurfaceFUCHSIA);
}
#endif
#if defined(ANGLE_PLATFORM_ANDROID)
PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID =
nullptr;
PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID = nullptr;
void InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance)
{
GET_INSTANCE_FUNC(vkGetAndroidHardwareBufferPropertiesANDROID);
GET_INSTANCE_FUNC(vkGetMemoryAndroidHardwareBufferANDROID);
}
#endif
#if defined(ANGLE_PLATFORM_GGP)
PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP = nullptr;
void InitGGPStreamDescriptorSurfaceFunctions(VkInstance instance)
{
GET_INSTANCE_FUNC(vkCreateStreamDescriptorSurfaceGGP);
}
#endif // defined(ANGLE_PLATFORM_GGP)
void InitExternalSemaphoreFdFunctions(VkInstance instance)
{
GET_INSTANCE_FUNC(vkImportSemaphoreFdKHR);
}
#undef GET_INSTANCE_FUNC
#undef GET_DEVICE_FUNC
namespace gl_vk
{
......
......@@ -606,59 +606,6 @@ class Recycler final : angle::NonCopyable
} // namespace vk
// List of function pointers for used extensions.
// VK_EXT_debug_utils
extern PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT;
extern PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
extern PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT;
extern PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT;
extern PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT;
// VK_EXT_debug_report
extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
// VK_KHR_get_physical_device_properties2
extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
extern PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
// VK_KHR_external_semaphore_fd
extern PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR;
extern PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT;
extern PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT;
extern PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT;
extern PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT;
extern PFN_vkCmdEndQueryIndexedEXT vkCmdEndQueryIndexedEXT;
extern PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT;
// Lazily load entry points for each extension as necessary.
void InitDebugUtilsEXTFunctions(VkInstance instance);
void InitDebugReportEXTFunctions(VkInstance instance);
void InitGetPhysicalDeviceProperties2KHRFunctions(VkInstance instance);
void InitTransformFeedbackEXTFunctions(VkDevice device);
#if defined(ANGLE_PLATFORM_FUCHSIA)
// VK_FUCHSIA_imagepipe_surface
extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA;
void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance);
#endif
#if defined(ANGLE_PLATFORM_ANDROID)
// VK_ANDROID_external_memory_android_hardware_buffer
extern PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID;
extern PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID;
void InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance);
#endif
#if defined(ANGLE_PLATFORM_GGP)
// VK_GGP_stream_descriptor_surface
extern PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP;
void InitGGPStreamDescriptorSurfaceFunctions(VkInstance instance);
#endif // defined(ANGLE_PLATFORM_GGP)
void InitExternalSemaphoreFdFunctions(VkInstance instance);
namespace gl_vk
{
VkRect2D GetRect(const gl::Rectangle &source);
......
......@@ -11,7 +11,7 @@
#ifndef LIBANGLE_RENDERER_VULKAN_VK_WRAPPER_H_
#define LIBANGLE_RENDERER_VULKAN_VK_WRAPPER_H_
#include <vulkan/vulkan.h>
#include "volk.h"
#include "libANGLE/renderer/renderer_utils.h"
......
......@@ -11,8 +11,8 @@
#include "libANGLE/renderer/vulkan/DisplayVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include <vulkan/vulkan.h>
#include <windows.h>
#include "volk.h"
#include "libANGLE/renderer/vulkan/vk_caps_utils.h"
#include "libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h"
......
......@@ -141,8 +141,6 @@ void main()
// numbers.
TEST_P(PackUnpackTest, PackUnpackSnormNormal)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF((IsAndroid() && IsVulkan()) || isSwiftshader());
// Expect the shader to output the same value as the input
compareBeforeAfter(mSNormProgram, 0.5f, -0.2f);
compareBeforeAfter(mSNormProgram, -0.35f, 0.75f);
......@@ -154,8 +152,6 @@ TEST_P(PackUnpackTest, PackUnpackSnormNormal)
// numbers.
TEST_P(PackUnpackTest, PackUnpackUnormNormal)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF((IsAndroid() && IsVulkan()) || isSwiftshader());
// Expect the shader to output the same value as the input
compareBeforeAfter(mUNormProgram, 0.5f, 0.2f, 0.5f, 0.2f);
compareBeforeAfter(mUNormProgram, 0.35f, 0.75f, 0.35f, 0.75f);
......@@ -167,8 +163,6 @@ TEST_P(PackUnpackTest, PackUnpackUnormNormal)
// numbers.
TEST_P(PackUnpackTest, PackUnpackHalfNormal)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF((IsAndroid() && IsVulkan()) || isSwiftshader());
// Expect the shader to output the same value as the input
compareBeforeAfter(mHalfProgram, 0.5f, -0.2f);
compareBeforeAfter(mHalfProgram, -0.35f, 0.75f);
......@@ -180,8 +174,6 @@ TEST_P(PackUnpackTest, PackUnpackHalfNormal)
// floating numbers.
TEST_P(PackUnpackTest, PackUnpackSnormSubnormal)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF((IsAndroid() && IsVulkan()) || isSwiftshader());
// Expect the shader to output the same value as the input
compareBeforeAfter(mSNormProgram, 0.00001f, -0.00001f);
}
......@@ -190,8 +182,6 @@ TEST_P(PackUnpackTest, PackUnpackSnormSubnormal)
// floating numbers.
TEST_P(PackUnpackTest, PackUnpackUnormSubnormal)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF((IsAndroid() && IsVulkan()) || isSwiftshader());
// Expect the shader to output the same value as the input for positive numbers and clamp
// to [0, 1]
compareBeforeAfter(mUNormProgram, 0.00001f, -0.00001f, 0.00001f, 0.0f);
......@@ -201,8 +191,6 @@ TEST_P(PackUnpackTest, PackUnpackUnormSubnormal)
// numbers.
TEST_P(PackUnpackTest, PackUnpackHalfSubnormal)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF((IsAndroid() && IsVulkan()) || isSwiftshader());
// Expect the shader to output the same value as the input
compareBeforeAfter(mHalfProgram, 0.00001f, -0.00001f);
}
......@@ -211,8 +199,6 @@ TEST_P(PackUnpackTest, PackUnpackHalfSubnormal)
// numbers.
TEST_P(PackUnpackTest, PackUnpackSnormZero)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF((IsAndroid() && IsVulkan()) || isSwiftshader());
// Expect the shader to output the same value as the input
compareBeforeAfter(mSNormProgram, 0.00000f, -0.00000f);
}
......@@ -221,8 +207,6 @@ TEST_P(PackUnpackTest, PackUnpackSnormZero)
// numbers.
TEST_P(PackUnpackTest, PackUnpackUnormZero)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF((IsAndroid() && IsVulkan()) || isSwiftshader());
compareBeforeAfter(mUNormProgram, 0.00000f, -0.00000f, 0.00000f, 0.00000f);
}
......@@ -230,8 +214,6 @@ TEST_P(PackUnpackTest, PackUnpackUnormZero)
// numbers.
TEST_P(PackUnpackTest, PackUnpackHalfZero)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF((IsAndroid() && IsVulkan()) || isSwiftshader());
// Expect the shader to output the same value as the input
compareBeforeAfter(mHalfProgram, 0.00000f, -0.00000f);
}
......@@ -240,8 +222,6 @@ TEST_P(PackUnpackTest, PackUnpackHalfZero)
// numbers.
TEST_P(PackUnpackTest, PackUnpackUnormOverflow)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF((IsAndroid() && IsVulkan()) || isSwiftshader());
// Expect the shader to clamp the input to [0, 1]
compareBeforeAfter(mUNormProgram, 67000.0f, -67000.0f, 1.0f, 0.0f);
}
......@@ -250,11 +230,10 @@ TEST_P(PackUnpackTest, PackUnpackUnormOverflow)
// numbers.
TEST_P(PackUnpackTest, PackUnpackSnormOverflow)
{
// http://anglebug.com/4092
ANGLE_SKIP_TEST_IF((IsAndroid() && IsVulkan()) || isSwiftshader());
// Expect the shader to clamp the input to [-1, 1]
compareBeforeAfter(mSNormProgram, 67000.0f, -67000.0f, 1.0f, -1.0f);
}
ANGLE_INSTANTIATE_TEST_ES3(PackUnpackTest);
ANGLE_INSTANTIATE_TEST(PackUnpackTest, ES3_OPENGL(), ES3_OPENGLES());
// http://anglebug.com/4092 Not instantiating on other backends currently
} // namespace
......@@ -8,7 +8,6 @@
#include "test_utils/VulkanExternalHelper.h"
#include <vulkan/vulkan.h>
#include <vector>
#include "common/bitset_utils.h"
......@@ -142,7 +141,8 @@ VulkanExternalHelper::~VulkanExternalHelper()
void VulkanExternalHelper::initialize()
{
ASSERT(mInstance == VK_NULL_HANDLE);
VkResult result = volkInitialize();
ASSERT(result == VK_SUCCESS);
std::vector<VkExtensionProperties> instanceExtensionProperties =
EnumerateInstanceExtensionProperties(nullptr);
......@@ -185,9 +185,10 @@ void VulkanExternalHelper::initialize()
/* .ppEnabledExtensionName = */ enabledInstanceExtensions.data(),
};
VkResult result = vkCreateInstance(&instanceCreateInfo, nullptr, &mInstance);
result = vkCreateInstance(&instanceCreateInfo, nullptr, &mInstance);
ASSERT(result == VK_SUCCESS);
ASSERT(mInstance != VK_NULL_HANDLE);
volkLoadInstance(mInstance);
std::vector<VkPhysicalDevice> physicalDevices = EnumeratePhysicalDevices(mInstance);
ASSERT(physicalDevices.size() > 0);
......@@ -261,6 +262,7 @@ void VulkanExternalHelper::initialize()
result = vkCreateDevice(mPhysicalDevice, &deviceCreateInfo, nullptr, &mDevice);
ASSERT(result == VK_SUCCESS);
ASSERT(mDevice != VK_NULL_HANDLE);
volkLoadDevice(mDevice);
constexpr uint32_t kGraphicsQueueIndex = 0;
static_assert(kGraphicsQueueIndex < kGraphicsQueueCount, "must be in range");
......
......@@ -8,7 +8,7 @@
#ifndef ANGLE_TESTS_TESTUTILS_VULKANEXTERNALHELPER_H_
#define ANGLE_TESTS_TESTUTILS_VULKANEXTERNALHELPER_H_
#include <vulkan/vulkan.h>
#include "volk.h"
namespace angle
{
......
......@@ -223,6 +223,8 @@ void init_instance_extension_names(struct sample_info &info)
VkResult init_instance(struct sample_info &info, char const *const app_short_name)
{
VkResult res = volkInitialize();
ASSERT(res == VK_SUCCESS);
VkApplicationInfo app_info = {};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pNext = NULL;
......@@ -243,8 +245,9 @@ VkResult init_instance(struct sample_info &info, char const *const app_short_nam
inst_info.enabledExtensionCount = info.instance_extension_names.size();
inst_info.ppEnabledExtensionNames = info.instance_extension_names.data();
VkResult res = vkCreateInstance(&inst_info, NULL, &info.inst);
res = vkCreateInstance(&inst_info, NULL, &info.inst);
ASSERT(res == VK_SUCCESS);
volkLoadInstance(info.inst);
return res;
}
......@@ -701,6 +704,7 @@ VkResult init_device(struct sample_info &info)
res = vkCreateDevice(info.gpus[0], &device_info, NULL, &info.device);
ASSERT(res == VK_SUCCESS);
volkLoadDevice(info.device);
return res;
}
......
......@@ -60,7 +60,7 @@ ANGLE_REENABLE_EXTRA_SEMI_WARNING
# include "vulkan/vk_sdk_platform.h"
#endif
#include <vulkan/vulkan.h>
#include "volk.h"
/* Number of descriptor sets needs to be the same at alloc, */
/* pipeline layout creation, and descriptor set layout creation */
......
# Copyright 2019 The ANGLE Project Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
config("volk_config") {
include_dirs = [ "." ]
}
source_set("volk") {
sources = [
"volk.c",
"volk.h",
]
public_configs = [ ":volk_config" ]
public_deps = [
"../../../third_party/vulkan-headers/src:vulkan_headers",
]
}
Copyright (c) 2018-2019 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
Name: Volk Meta loader for Vulkan API
Short Name: volk
URL: https://github.com/zeux/volk
Version: 0
License: MIT
Security Critical: yes
Description:
volk is a meta-loader for Vulkan. It allows you to dynamically load
entrypoints required to use Vulkan without linking to vulkan-1.dll
or statically linking Vulkan loader. Additionally, volk simplifies
the use of Vulkan extensions by automatically loading all associated
entrypoints. Finally, volk enables loading Vulkan entrypoints directly
from the driver which can increase performance by skipping loader
dispatch overhead.
Local Modifications:
Added static variables to track VkInstance and VkDevice that were last loaded by volk.
This data is then used by ANGLE renderer to make sure that the current device/instance
match up with previously loaded values. When they don't match, we re-load vk* function
pointers.
# 🐺 volk [![Build Status](https://travis-ci.org/zeux/volk.svg?branch=master)](https://travis-ci.org/zeux/volk)
## ANGLE Integration
Note that the entirety of the volk README.md is included below. This is an additional section with information
on volk's integration into ANGLE. The volk source files are copied directly from the volk GitHub repo.
To update volk in ANGLE, copy the latest volk.h/c files into ANGLE "src/third_party/volk" dir and push update.
If any changes are made to volk source files locally within ANGLE, please also make corresponding PRs so that
the changes land in the upstream source volk GitHub repo.
## Purpose
volk is a meta-loader for Vulkan. It allows you to dynamically load entrypoints required to use Vulkan
without linking to vulkan-1.dll or statically linking Vulkan loader. Additionally, volk simplifies the use of Vulkan extensions by automatically loading all associated entrypoints. Finally, volk enables loading
Vulkan entrypoints directly from the driver which can increase performance by skipping loader dispatch overhead.
volk is written in C89 and supports Windows, Linux, Android and macOS (via MoltenVK).
## Building
volk comes with one header and source file; to build it, just add the source file, `volk.c`, to your build system.
To use volk, you have to include `volk.h` instead of `vulkan/vulkan.h`; this is necessary to use function definitions from volk.
If some files in your application include `vulkan/vulkan.h` and don't include `volk.h`, this can result in symbol conflicts; consider defining `VK_NO_PROTOTYPES` when compiling code that uses Vulkan to make sure this doesn't happen.
## Basic usage
To initialize volk, call this function first:
```c++
VkResult volkInitialize();
```
This will attempt to load Vulkan loader from the system; if this function returns `VK_SUCCESS` you can proceed to create Vulkan instance.
If this function fails, this means Vulkan loader isn't installed on your system.
After creating the Vulkan instance using Vulkan API, call this function:
```c++
void volkLoadInstance(VkInstance instance);
```
This function will load all required Vulkan entrypoints, including all extensions; you can use Vulkan from here on as usual.
## Optimizing device calls
If you use volk as described in the previous section, all device-related function calls, such as `vkCmdDraw`, will go through Vulkan loader dispatch code.
This allows you to transparently support multiple VkDevice objects in the same application, but comes at a price of dispatch overhead which can be as high as 7% depending on the driver and application.
To avoid this, you have one of two options:
1. For applications that use just one VkDevice object, load device-related Vulkan entrypoints directly from the driver with this function:
```c++
void volkLoadDevice(VkDevice device);
```
2. For applications that use multiple VkDevice objects, load device-related Vulkan entrypoints into a table:
```c++
void volkLoadDeviceTable(struct VolkDeviceTable* table, VkDevice device);
```
The second option requires you to change the application code to store one `VolkDeviceTable` per `VkDevice` and call functions from this table instead.
Device entrypoints are loaded using `vkGetDeviceProcAddr`; when no layers are present, this commonly results in most function pointers pointing directly at the driver functions, minimizing the call overhead. When layers are loaded, the entrypoints will point at the implementations in the first applicable layer, so this is compatible with any layers including validation layers.
## License
This library is available to anybody free of charge, under the terms of MIT License:
Copyright (c) 2018-2019 Arseny Kapoulkine
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment