2017-07-14 21:51:27 +02:00
|
|
|
#include "OVR_CAPI_Vk.h"
|
|
|
|
|
#include "Assert.h"
|
|
|
|
|
#include "Session.h"
|
2017-08-19 14:42:56 +02:00
|
|
|
#include "CompositorVk.h"
|
|
|
|
|
#include "TextureVk.h"
|
2017-08-20 01:37:08 +02:00
|
|
|
#include "vulkan.h"
|
2017-07-14 21:51:27 +02:00
|
|
|
|
2017-08-20 01:37:08 +02:00
|
|
|
#include <Windows.h>
|
2017-08-19 14:42:56 +02:00
|
|
|
#include <openvr.h>
|
|
|
|
|
#include <vector>
|
2017-07-14 21:51:27 +02:00
|
|
|
|
2017-08-20 01:37:08 +02:00
|
|
|
HMODULE VulkanLibrary;
|
2017-10-09 22:41:12 +02:00
|
|
|
VkPhysicalDevice g_physicalDevice;
|
2017-08-20 01:37:08 +02:00
|
|
|
|
|
|
|
|
// Global functions
|
|
|
|
|
VK_DEFINE_FUNCTION(vkGetInstanceProcAddr)
|
|
|
|
|
VK_DEFINE_FUNCTION(vkGetDeviceProcAddr)
|
|
|
|
|
VK_DEFINE_FUNCTION(vkEnumeratePhysicalDevices)
|
|
|
|
|
VK_DEFINE_FUNCTION(vkGetPhysicalDeviceMemoryProperties)
|
|
|
|
|
VK_DEFINE_FUNCTION(vkGetPhysicalDeviceProperties2KHR)
|
|
|
|
|
|
2017-10-09 22:41:12 +02:00
|
|
|
OVR_PUBLIC_FUNCTION(ovrResult)
|
|
|
|
|
ovr_GetInstanceExtensionsVk(
|
|
|
|
|
ovrGraphicsLuid luid,
|
|
|
|
|
char* extensionNames,
|
|
|
|
|
uint32_t* inoutExtensionNamesSize)
|
|
|
|
|
{
|
|
|
|
|
if (!inoutExtensionNamesSize)
|
|
|
|
|
ovrError_InvalidParameter;
|
|
|
|
|
|
2017-12-13 16:10:17 +01:00
|
|
|
uint32_t size = *inoutExtensionNamesSize;
|
|
|
|
|
uint32_t required = vr::VRCompositor()->GetVulkanInstanceExtensionsRequired(extensionNames, *inoutExtensionNamesSize);
|
2017-10-17 22:47:29 +02:00
|
|
|
|
|
|
|
|
if (required <= size)
|
|
|
|
|
{
|
|
|
|
|
strncpy(extensionNames + required, VK_KHR_SURFACE_EXTENSION_NAME, size);
|
2017-12-13 16:10:17 +01:00
|
|
|
extensionNames[required - 1] = '\0';
|
2017-10-17 22:47:29 +02:00
|
|
|
}
|
2017-12-13 16:10:17 +01:00
|
|
|
required += (uint32_t)strlen(VK_KHR_SURFACE_EXTENSION_NAME) + 1;
|
2017-10-17 22:47:29 +02:00
|
|
|
if (required <= size)
|
|
|
|
|
{
|
|
|
|
|
strncpy(extensionNames + required, VK_KHR_WIN32_SURFACE_EXTENSION_NAME, size);
|
2017-12-13 16:10:17 +01:00
|
|
|
extensionNames[required - 1] = '\0';
|
2017-10-17 22:47:29 +02:00
|
|
|
}
|
2017-12-13 16:10:17 +01:00
|
|
|
required += (uint32_t)strlen(VK_KHR_WIN32_SURFACE_EXTENSION_NAME) + 1;
|
2017-10-17 22:47:29 +02:00
|
|
|
|
2017-10-09 22:41:12 +02:00
|
|
|
*inoutExtensionNamesSize = required;
|
|
|
|
|
|
|
|
|
|
return (size < required) ? ovrError_InsufficientArraySize : ovrSuccess;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVR_PUBLIC_FUNCTION(ovrResult)
|
|
|
|
|
ovr_GetDeviceExtensionsVk(
|
|
|
|
|
ovrGraphicsLuid luid,
|
|
|
|
|
char* extensionNames,
|
|
|
|
|
uint32_t* inoutExtensionNamesSize)
|
|
|
|
|
{
|
|
|
|
|
if (!inoutExtensionNamesSize)
|
|
|
|
|
ovrError_InvalidParameter;
|
|
|
|
|
|
2017-12-13 16:10:17 +01:00
|
|
|
uint32_t size = *inoutExtensionNamesSize;
|
|
|
|
|
uint32_t required = vr::VRCompositor()->GetVulkanDeviceExtensionsRequired(g_physicalDevice, extensionNames, *inoutExtensionNamesSize);
|
2017-10-17 22:47:29 +02:00
|
|
|
|
|
|
|
|
if (required <= size)
|
|
|
|
|
{
|
|
|
|
|
strncpy(extensionNames + required, VK_KHR_SWAPCHAIN_EXTENSION_NAME, size);
|
2017-12-13 16:10:17 +01:00
|
|
|
extensionNames[required - 1] = '\0';
|
2017-10-17 22:47:29 +02:00
|
|
|
}
|
2017-12-13 16:10:17 +01:00
|
|
|
required += (uint32_t)strlen(VK_KHR_SWAPCHAIN_EXTENSION_NAME) + 1;
|
2017-10-17 22:47:29 +02:00
|
|
|
|
2017-10-09 22:41:12 +02:00
|
|
|
*inoutExtensionNamesSize = required;
|
|
|
|
|
|
|
|
|
|
return (size < required) ? ovrError_InsufficientArraySize : ovrSuccess;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-14 21:51:27 +02:00
|
|
|
OVR_PUBLIC_FUNCTION(ovrResult)
|
|
|
|
|
ovr_GetSessionPhysicalDeviceVk(
|
|
|
|
|
ovrSession session,
|
|
|
|
|
ovrGraphicsLuid luid,
|
|
|
|
|
VkInstance instance,
|
|
|
|
|
VkPhysicalDevice* out_physicalDevice)
|
|
|
|
|
{
|
2017-08-20 01:37:08 +02:00
|
|
|
VulkanLibrary = LoadLibraryW(L"vulkan-1.dll");
|
|
|
|
|
if (!VulkanLibrary)
|
|
|
|
|
return ovrError_InitializeVulkan;
|
|
|
|
|
|
|
|
|
|
VK_LIBRARY_FUNCTION(VulkanLibrary, vkGetInstanceProcAddr)
|
|
|
|
|
VK_INSTANCE_FUNCTION(instance, vkGetDeviceProcAddr)
|
|
|
|
|
VK_INSTANCE_FUNCTION(instance, vkEnumeratePhysicalDevices)
|
|
|
|
|
VK_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceMemoryProperties)
|
|
|
|
|
VK_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceProperties2KHR)
|
2017-07-14 21:51:27 +02:00
|
|
|
|
2017-07-26 00:37:57 +02:00
|
|
|
VkPhysicalDevice physicalDevice = 0;
|
2017-09-04 12:46:10 +02:00
|
|
|
vr::VRSystem()->GetOutputDevice((uint64_t*)&physicalDevice, vr::TextureType_Vulkan, instance);
|
2017-07-20 16:31:57 +02:00
|
|
|
|
2017-09-04 12:46:10 +02:00
|
|
|
// Fall-back in case GetOutputDevice fails.
|
|
|
|
|
if (physicalDevice == 0)
|
|
|
|
|
{
|
|
|
|
|
uint32_t gpu_count;
|
|
|
|
|
std::vector<VkPhysicalDevice> devices;
|
2017-07-20 16:31:57 +02:00
|
|
|
|
2017-09-04 12:46:10 +02:00
|
|
|
// Get the number of devices (GPUs) available.
|
|
|
|
|
VkResult res = vkEnumeratePhysicalDevices(instance, &gpu_count, NULL);
|
|
|
|
|
// Allocate space and get the list of devices.
|
|
|
|
|
devices.resize(gpu_count);
|
|
|
|
|
res = vkEnumeratePhysicalDevices(instance, &gpu_count, devices.data());
|
2017-07-20 16:31:57 +02:00
|
|
|
|
2017-09-04 12:46:10 +02:00
|
|
|
for (VkPhysicalDevice device : devices)
|
|
|
|
|
{
|
|
|
|
|
VkPhysicalDeviceIDPropertiesKHR uid = {};
|
|
|
|
|
uid.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR;
|
|
|
|
|
VkPhysicalDeviceProperties2KHR properties = {};
|
|
|
|
|
properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
|
|
|
|
|
properties.pNext = &uid;
|
2017-07-20 16:31:57 +02:00
|
|
|
|
2017-09-04 12:46:10 +02:00
|
|
|
vkGetPhysicalDeviceProperties2KHR(device, &properties);
|
2017-07-20 16:31:57 +02:00
|
|
|
|
2017-09-04 12:46:10 +02:00
|
|
|
if (!uid.deviceLUIDValid)
|
|
|
|
|
continue;
|
2017-07-20 16:31:57 +02:00
|
|
|
|
2017-09-04 12:46:10 +02:00
|
|
|
if (memcmp(uid.deviceLUID, luid.Reserved, VK_LUID_SIZE_KHR) == 0)
|
|
|
|
|
{
|
|
|
|
|
physicalDevice = device;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2017-07-20 16:31:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-09 22:41:12 +02:00
|
|
|
g_physicalDevice = physicalDevice;
|
|
|
|
|
|
2017-08-19 14:42:56 +02:00
|
|
|
if (!session->Compositor)
|
|
|
|
|
{
|
|
|
|
|
session->Compositor.reset(new CompositorVk(physicalDevice, instance));
|
|
|
|
|
if (!session->Compositor)
|
|
|
|
|
return ovrError_RuntimeException;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-20 16:31:57 +02:00
|
|
|
if (out_physicalDevice)
|
|
|
|
|
*out_physicalDevice = physicalDevice;
|
|
|
|
|
|
|
|
|
|
return physicalDevice ? ovrSuccess : ovrError_MismatchedAdapters;
|
2017-07-14 21:51:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVR_PUBLIC_FUNCTION(ovrResult) ovr_SetSynchonizationQueueVk(ovrSession session, VkQueue queue)
|
|
|
|
|
{
|
2017-08-19 14:42:56 +02:00
|
|
|
CompositorVk* compositor = dynamic_cast<CompositorVk*>(session->Compositor.get());
|
|
|
|
|
|
|
|
|
|
if (!compositor)
|
|
|
|
|
return ovrError_RuntimeException;
|
|
|
|
|
|
|
|
|
|
compositor->SetQueue(queue);
|
|
|
|
|
return ovrSuccess;
|
2017-07-14 21:51:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVR_PUBLIC_FUNCTION(ovrResult)
|
|
|
|
|
ovr_CreateTextureSwapChainVk(
|
|
|
|
|
ovrSession session,
|
|
|
|
|
VkDevice device,
|
|
|
|
|
const ovrTextureSwapChainDesc* desc,
|
|
|
|
|
ovrTextureSwapChain* out_TextureSwapChain)
|
|
|
|
|
{
|
2017-08-19 14:42:56 +02:00
|
|
|
REV_TRACE(ovr_CreateTextureSwapChainVk);
|
|
|
|
|
|
|
|
|
|
if (!session)
|
|
|
|
|
return ovrError_InvalidSession;
|
|
|
|
|
|
|
|
|
|
if (!device || !desc || !out_TextureSwapChain || desc->Type != ovrTexture_2D)
|
|
|
|
|
return ovrError_InvalidParameter;
|
|
|
|
|
|
|
|
|
|
CompositorVk* compositor = dynamic_cast<CompositorVk*>(session->Compositor.get());
|
|
|
|
|
|
|
|
|
|
if (!compositor)
|
|
|
|
|
return ovrError_RuntimeException;
|
|
|
|
|
|
|
|
|
|
compositor->SetDevice(device);
|
|
|
|
|
|
|
|
|
|
if (session->Compositor->GetAPI() != vr::TextureType_Vulkan)
|
|
|
|
|
return ovrError_RuntimeException;
|
|
|
|
|
|
|
|
|
|
return session->Compositor->CreateTextureSwapChain(desc, out_TextureSwapChain);
|
2017-07-14 21:51:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVR_PUBLIC_FUNCTION(ovrResult)
|
|
|
|
|
ovr_GetTextureSwapChainBufferVk(
|
|
|
|
|
ovrSession session,
|
|
|
|
|
ovrTextureSwapChain chain,
|
|
|
|
|
int index,
|
|
|
|
|
VkImage* out_Image)
|
|
|
|
|
{
|
2017-08-19 14:42:56 +02:00
|
|
|
REV_TRACE(ovr_GetTextureSwapChainBufferDX);
|
|
|
|
|
|
|
|
|
|
if (!session)
|
|
|
|
|
return ovrError_InvalidSession;
|
|
|
|
|
|
|
|
|
|
if (!chain || !out_Image)
|
|
|
|
|
return ovrError_InvalidParameter;
|
|
|
|
|
|
|
|
|
|
if (index < 0)
|
|
|
|
|
index = chain->CurrentIndex;
|
|
|
|
|
|
|
|
|
|
TextureVk* texture = dynamic_cast<TextureVk*>(chain->Textures[index].get());
|
|
|
|
|
if (!texture)
|
|
|
|
|
return ovrError_RuntimeException;
|
|
|
|
|
|
|
|
|
|
*out_Image = texture->Image();
|
|
|
|
|
|
|
|
|
|
return ovrSuccess;
|
2017-07-14 21:51:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVR_PUBLIC_FUNCTION(ovrResult)
|
|
|
|
|
ovr_CreateMirrorTextureWithOptionsVk(
|
|
|
|
|
ovrSession session,
|
|
|
|
|
VkDevice device,
|
|
|
|
|
const ovrMirrorTextureDesc* desc,
|
|
|
|
|
ovrMirrorTexture* out_MirrorTexture)
|
|
|
|
|
{
|
2017-08-19 14:42:56 +02:00
|
|
|
REV_TRACE(ovr_CreateMirrorTextureWithOptionsVk);
|
|
|
|
|
|
|
|
|
|
if (!session)
|
|
|
|
|
return ovrError_InvalidSession;
|
|
|
|
|
|
|
|
|
|
if (!device || !desc || !out_MirrorTexture)
|
|
|
|
|
return ovrError_InvalidParameter;
|
|
|
|
|
|
|
|
|
|
CompositorVk* compositor = dynamic_cast<CompositorVk*>(session->Compositor.get());
|
|
|
|
|
if (!compositor)
|
|
|
|
|
return ovrError_RuntimeException;
|
|
|
|
|
|
|
|
|
|
compositor->SetDevice(device);
|
|
|
|
|
|
|
|
|
|
if (session->Compositor->GetAPI() != vr::TextureType_Vulkan)
|
|
|
|
|
return ovrError_RuntimeException;
|
|
|
|
|
|
|
|
|
|
return session->Compositor->CreateMirrorTexture(desc, out_MirrorTexture);
|
2017-07-14 21:51:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OVR_PUBLIC_FUNCTION(ovrResult)
|
|
|
|
|
ovr_GetMirrorTextureBufferVk(
|
|
|
|
|
ovrSession session,
|
|
|
|
|
ovrMirrorTexture mirrorTexture,
|
|
|
|
|
VkImage* out_Image)
|
|
|
|
|
{
|
2017-08-19 14:42:56 +02:00
|
|
|
REV_TRACE(ovr_GetMirrorTextureBufferVk);
|
|
|
|
|
|
|
|
|
|
if (!session)
|
|
|
|
|
return ovrError_InvalidSession;
|
|
|
|
|
|
|
|
|
|
if (!mirrorTexture || !out_Image)
|
|
|
|
|
return ovrError_InvalidParameter;
|
|
|
|
|
|
|
|
|
|
TextureVk* texture = dynamic_cast<TextureVk*>(mirrorTexture->Texture.get());
|
|
|
|
|
if (!texture)
|
|
|
|
|
return ovrError_RuntimeException;
|
|
|
|
|
|
|
|
|
|
*out_Image = texture->Image();
|
|
|
|
|
|
|
|
|
|
return ovrSuccess;
|
2017-07-14 21:51:27 +02:00
|
|
|
}
|
|
|
|
|
|