Vulkan: Load Vulkan library and gather global info

This commit is contained in:
Corentin Wallez 2017-11-17 17:52:04 -05:00 committed by Corentin Wallez
parent a2d2cfe2f5
commit f2adf6d5bd
8 changed files with 267 additions and 0 deletions

View File

@ -282,11 +282,17 @@ if (NXT_ENABLE_VULKAN)
)
target_link_libraries(vulkan_autogen nxtcpp)
target_include_directories(vulkan_autogen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(vulkan_autogen PUBLIC ${VULKAN_HEADERS_INCLUDE_DIR})
target_include_directories(vulkan_autogen PUBLIC ${SRC_DIR})
list(APPEND BACKEND_SOURCES
${VULKAN_DIR}/vulkan_platform.h
${VULKAN_DIR}/VulkanBackend.cpp
${VULKAN_DIR}/VulkanBackend.h
${VULKAN_DIR}/VulkanFunctions.cpp
${VULKAN_DIR}/VulkanFunctions.h
${VULKAN_DIR}/VulkanInfo.cpp
${VULKAN_DIR}/VulkanInfo.h
)
endif()

View File

@ -15,9 +15,18 @@
#include "backend/vulkan/VulkanBackend.h"
#include "backend/Commands.h"
#include "common/Platform.h"
#include <spirv-cross/spirv_cross.hpp>
#if NXT_PLATFORM_LINUX
const char kVulkanLibName[] = "libvulkan.so.1";
#elif NXT_PLATFORM_WINDOWS
const char kVulkanLibName[] = "vulkan-1.dll";
#else
#error "Unimplemented Vulkan backend platform"
#endif
namespace backend {
namespace vulkan {
@ -32,6 +41,23 @@ namespace vulkan {
// Device
Device::Device() {
if (!vulkanLib.Open(kVulkanLibName)) {
ASSERT(false);
return;
}
VulkanFunctions* functions = GetMutableFunctions();
VulkanInfo* vulkanInfo = GetMutableInfo();
if (!functions->LoadGlobalProcs(vulkanLib)) {
ASSERT(false);
return;
}
if (!vulkanInfo->GatherGlobalInfo(*this)) {
ASSERT(false);
return;
}
}
Device::~Device() {
@ -103,6 +129,14 @@ namespace vulkan {
void Device::TickImpl() {
}
VulkanFunctions* Device::GetMutableFunctions() {
return const_cast<VulkanFunctions*>(&fn);
}
VulkanInfo* Device::GetMutableInfo() {
return const_cast<VulkanInfo*>(&info);
}
// Buffer
Buffer::Buffer(BufferBuilder* builder)

View File

@ -17,6 +17,8 @@
#include "nxt/nxtcpp.h"
#include "backend/vulkan/VulkanFunctions.h"
#include "backend/vulkan/VulkanInfo.h"
#include "backend/Buffer.h"
#include "backend/BindGroup.h"
#include "backend/BindGroupLayout.h"
@ -36,6 +38,7 @@
#include "backend/SwapChain.h"
#include "backend/Texture.h"
#include "backend/ToBackend.h"
#include "common/DynamicLib.h"
namespace backend {
namespace vulkan {
@ -115,6 +118,19 @@ namespace vulkan {
TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override;
void TickImpl() override;
// Contains all the Vulkan entry points, vkDoFoo is called via device->fn.DoFoo.
const VulkanFunctions fn;
// All the information queried about this Vulkan system
const VulkanInfo info;
private:
// To make it easier to use fn it is a public const member. However
// the Device is allowed to mutate them through these private methods.
VulkanFunctions* GetMutableFunctions();
VulkanInfo* GetMutableInfo();
DynamicLib vulkanLib;
};
class Buffer : public BufferBase {

View File

@ -0,0 +1,42 @@
// Copyright 2017 The NXT Authors
//
// 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 "backend/vulkan/VulkanFunctions.h"
#include "common/DynamicLib.h"
namespace backend {
namespace vulkan {
#define GET_GLOBAL_PROC(name) \
name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(nullptr, "vk" #name)); \
if (name == nullptr) { \
return false; \
}
bool VulkanFunctions::LoadGlobalProcs(const DynamicLib& vulkanLib) {
if (!vulkanLib.GetProc(&GetInstanceProcAddr, "vkGetInstanceProcAddr")) {
return false;
}
GET_GLOBAL_PROC(CreateInstance);
GET_GLOBAL_PROC(DestroyInstance);
GET_GLOBAL_PROC(EnumerateInstanceExtensionProperties);
GET_GLOBAL_PROC(EnumerateInstanceLayerProperties);
return true;
}
}
}

View File

@ -0,0 +1,44 @@
// Copyright 2017 The NXT Authors
//
// 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.
#ifndef BACKEND_VULKAN_VULKANFUNCTIONS_H_
#define BACKEND_VULKAN_VULKANFUNCTIONS_H_
#include "backend/vulkan/vulkan_platform.h"
class DynamicLib;
namespace backend {
namespace vulkan {
// Stores the Vulkan entry points. Also loads them from the dynamic library
// and the vkGet*ProcAddress entry points.
struct VulkanFunctions {
bool LoadGlobalProcs(const DynamicLib& vulkanLib);
// Initial proc from which we can get all the others
PFN_vkGetInstanceProcAddr GetInstanceProcAddr = nullptr;
// Global procs, can be used without an instance
PFN_vkCreateInstance CreateInstance = nullptr;
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties = nullptr;
PFN_vkEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties = nullptr;
// DestroyInstance isn't technically a global proc but we want to be able to use it
// before querying the instance procs in case we need to error out during initialization.
PFN_vkDestroyInstance DestroyInstance = nullptr;
};
}
}
#endif // BACKEND_VULKAN_VULKANFUNCTIONS_H_

View File

@ -0,0 +1,61 @@
// Copyright 2017 The NXT Authors
//
// 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 "backend/vulkan/VulkanInfo.h"
#include "backend/vulkan/VulkanBackend.h"
namespace backend {
namespace vulkan {
bool VulkanInfo::GatherGlobalInfo(const Device& device) {
// Gather the info about the instance layers
{
uint32_t count = 0;
VkResult result = device.fn.EnumerateInstanceLayerProperties(&count, nullptr);
// From the Vulkan spec result should be success if there are 0 layers,
// incomplete otherwise. This means that both values represent a success.
// This is the same for all Enumarte functions
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return false;
}
global.layers.resize(count);
result = device.fn.EnumerateInstanceLayerProperties(&count, global.layers.data());
if (result != VK_SUCCESS) {
return false;
}
}
// Gather the info about the instance extensions
{
uint32_t count = 0;
VkResult result = device.fn.EnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
return false;
}
global.extensions.resize(count);
result = device.fn.EnumerateInstanceExtensionProperties(nullptr, &count, global.extensions.data());
if (result != VK_SUCCESS) {
return false;
}
}
// TODO(cwallez@chromium:org): Each layer can expose additional extensions, query them?
return true;
}
}
}

View File

@ -0,0 +1,44 @@
// Copyright 2017 The NXT Authors
//
// 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.
#ifndef BACKEND_VULKAN_VULKANINFO_H_
#define BACKEND_VULKAN_VULKANINFO_H_
#include "backend/vulkan/vulkan_platform.h"
#include <vector>
namespace backend {
namespace vulkan {
class Device;
// Stores the information about the Vulkan system that are required to use Vulkan.
// Also does the querying of the information.
struct VulkanInfo {
// Global information - gathered before the instance is created
struct {
std::vector<VkLayerProperties> layers;
std::vector<VkExtensionProperties> extensions;
// TODO(cwallez@chromium.org): layer instance extensions
} global;
bool GatherGlobalInfo(const Device& device);
};
}
}
#endif // BACKEND_VULKAN_VULKANINFO_H_

View File

@ -0,0 +1,20 @@
// Copyright 2017 The NXT Authors
//
// 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.
#ifndef BACKEND_VULKAN_VULKANPLATFORM_H_
#define BACKEND_VULKAN_VULKANPLATFORM_H_
#include <vulkan/vulkan.h>
#endif // BACKEND_VULKAN_VULKANPLATFORM_H_