libs/vkd3d: Create Vulkan instance when creating D3D12 device.

We link directly to the Vulkan loader library and use few exported
procedures. According to the documentation the loader library
exports all core Vulkan procedures on Windows, Linux and Android.
This commit is contained in:
Józef Kucia 2016-09-22 16:56:58 +02:00
parent 19eca43f2c
commit f86ca50443
6 changed files with 375 additions and 2 deletions

View File

@ -38,6 +38,12 @@ then
VKD3D_CHECK_CFLAGS([-Wvla])
fi
dnl Check for headers
AC_CHECK_HEADERS([vulkan/vulkan.h], [], [AC_MSG_ERROR([vulkan.h not found.])])
dnl Check for libraries
AC_CHECK_LIB([vulkan], [vkGetInstanceProcAddr], [], [AC_MSG_ERROR([libvulkan not found.])])
dnl Check for __sync_add_and_fetch
AC_MSG_CHECKING([for __sync_add_and_fetch])
AC_LINK_IFELSE(

View File

@ -22,6 +22,62 @@
#include "vkd3d_private.h"
static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance)
{
VkApplicationInfo application_info;
VkInstanceCreateInfo instance_info;
VkInstance vk_instance;
VkResult vr;
HRESULT hr;
TRACE("instance %p.\n", instance);
application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
application_info.pNext = NULL;
application_info.pApplicationName = PACKAGE_NAME;
application_info.applicationVersion = 0;
application_info.pEngineName = NULL;
application_info.engineVersion = 0;
application_info.apiVersion = VK_API_VERSION_1_0;
instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_info.pNext = NULL;
instance_info.flags = 0;
instance_info.pApplicationInfo = &application_info;
instance_info.enabledLayerCount = 0;
instance_info.ppEnabledLayerNames = NULL;
instance_info.enabledExtensionCount = 0;
instance_info.ppEnabledExtensionNames = NULL;
if ((vr = vkCreateInstance(&instance_info, NULL, &vk_instance)))
{
ERR("Failed to create Vulkan instance, vr %d.\n", vr);
return hresult_from_vk_result(vr);
}
if (FAILED(hr = vkd3d_load_vk_instance_procs(&instance->vk_procs, vk_instance)))
{
ERR("Failed to load instance procs, hr %#x.\n", hr);
vkDestroyInstance(vk_instance, NULL);
return hr;
}
instance->vk_instance = vk_instance;
TRACE("Created Vulkan instance %p.\n", vk_instance);
return S_OK;
}
static void vkd3d_instance_destroy(struct vkd3d_instance *instance)
{
const struct vkd3d_vk_instance_procs *vk_procs = &instance->vk_procs;
TRACE("instance %p.\n", instance);
VK_CALL(vkDestroyInstance(instance->vk_instance, NULL));
}
/* ID3D12Device */
static inline struct d3d12_device *impl_from_ID3D12Device(ID3D12Device *iface)
{
@ -66,7 +122,10 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device *iface)
TRACE("%p decreasing refcount to %u.\n", device, refcount);
if (!refcount)
{
vkd3d_instance_destroy(&device->vkd3d_instance);
vkd3d_free(device);
}
return refcount;
}
@ -567,20 +626,29 @@ static const struct ID3D12DeviceVtbl d3d12_device_vtbl =
d3d12_device_GetAdapterLuid,
};
static void d3d12_device_init(struct d3d12_device *device)
static HRESULT d3d12_device_init(struct d3d12_device *device)
{
HRESULT hr;
device->ID3D12Device_iface.lpVtbl = &d3d12_device_vtbl;
device->refcount = 1;
if (FAILED(hr = vkd3d_instance_init(&device->vkd3d_instance)))
return hr;
return S_OK;
}
HRESULT d3d12_device_create(struct d3d12_device **device)
{
struct d3d12_device *object;
HRESULT hr;
if (!(object = vkd3d_malloc(sizeof(*object))))
return E_OUTOFMEMORY;
d3d12_device_init(object);
if (FAILED(hr = d3d12_device_init(object)))
return hr;
TRACE("Created device %p.\n", object);

View File

@ -67,3 +67,59 @@ HRESULT return_interface(IUnknown *iface, REFIID iface_riid,
IUnknown_Release(iface);
return hr;
}
HRESULT hresult_from_vk_result(VkResult vr)
{
switch (vr)
{
case VK_SUCCESS:
return S_OK;
case VK_ERROR_OUT_OF_HOST_MEMORY:
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
return E_OUTOFMEMORY;
default:
FIXME("Unhandled VkResult %d.\n", vr);
return E_FAIL;
}
}
#define LOAD_INSTANCE_PFN(name) \
if (!(procs->name = (void *)vkGetInstanceProcAddr(instance, #name))) \
{ \
ERR("Could not get instance proc addr for '" #name "'.\n"); \
return E_FAIL; \
}
HRESULT vkd3d_load_vk_instance_procs(struct vkd3d_vk_instance_procs *procs,
VkInstance instance)
{
memset(procs, 0, sizeof(*procs));
#define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
#include "vulkan_procs.h"
TRACE("Loaded procs for VkInstance %p.\n", instance);
return S_OK;
}
#define COPY_PARENT_PFN(name) procs->name = parent_procs->name;
#define LOAD_DEVICE_PFN(name) \
if (!(procs->name = (void *)procs->vkGetDeviceProcAddr(device, #name))) \
{ \
ERR("Could not get device proc addr for '" #name "'.\n"); \
return E_FAIL; \
}
HRESULT vkd3d_load_vk_device_procs(struct vkd3d_vk_device_procs *procs,
const struct vkd3d_vk_instance_procs *parent_procs, VkDevice device)
{
memset(procs, 0, sizeof(*procs));
#define VK_INSTANCE_PFN COPY_PARENT_PFN
#define VK_DEVICE_PFN LOAD_DEVICE_PFN
#include "vulkan_procs.h"
TRACE("Loaded procs for VkDevice %p.\n", device);
return S_OK;
}

View File

@ -26,6 +26,7 @@
#define COBJMACROS
#include "vkd3d_common.h"
#include "vkd3d_debug.h"
#include "vkd3d_vulkan.h"
#include "d3d12.h"
@ -33,6 +34,12 @@
struct d3d12_device;
struct vkd3d_instance
{
VkInstance vk_instance;
struct vkd3d_vk_instance_procs vk_procs;
};
/* ID3D12CommandAllocator */
struct d3d12_command_allocator
{
@ -81,6 +88,8 @@ struct d3d12_device
{
ID3D12Device ID3D12Device_iface;
ULONG refcount;
struct vkd3d_instance vkd3d_instance;
};
HRESULT d3d12_device_create(struct d3d12_device **device) DECLSPEC_HIDDEN;
@ -113,4 +122,11 @@ static inline void vkd3d_free(void *ptr)
free(ptr);
}
HRESULT hresult_from_vk_result(VkResult vr) DECLSPEC_HIDDEN;
HRESULT vkd3d_load_vk_instance_procs(struct vkd3d_vk_instance_procs *procs,
VkInstance instance) DECLSPEC_HIDDEN;
HRESULT vkd3d_load_vk_device_procs(struct vkd3d_vk_device_procs *procs,
const struct vkd3d_vk_instance_procs *parent_procs, VkDevice device) DECLSPEC_HIDDEN;
#endif /* __VKD3D_PRIVATE_H */

58
libs/vkd3d/vkd3d_vulkan.h Normal file
View File

@ -0,0 +1,58 @@
/*
* Copyright 2016 Józef Kucia for CodeWeavers
*
* 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.
*/
#ifndef __VKD3D_VULKAN_H
#define __VKD3D_VULKAN_H
#define VK_NO_PROTOTYPES
#include "vulkan/vulkan.h"
#define DECLARE_VK_PFN(name) PFN_##name name;
/* We link directly to the loader library and use the following exported functions. */
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance,
const char *name);
VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo *create_info,
const VkAllocationCallbacks *allocator, VkInstance *instance);
VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *layer_name,
uint32_t *property_count, VkExtensionProperties *properties);
VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *property_count,
VkLayerProperties *properties);
VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *allocator);
VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *allocator);
struct vkd3d_vk_instance_procs
{
#define VK_INSTANCE_PFN DECLARE_VK_PFN
#include "vulkan_procs.h"
};
struct vkd3d_vk_device_procs
{
#define VK_INSTANCE_PFN DECLARE_VK_PFN
#define VK_DEVICE_PFN DECLARE_VK_PFN
#include "vulkan_procs.h"
};
#define VK_CALL(f) (vk_procs->f)
#endif /* __VKD3D_VULKAN_H */

169
libs/vkd3d/vulkan_procs.h Normal file
View File

@ -0,0 +1,169 @@
/*
* Copyright 2016 Józef Kucia for CodeWeavers
*
* 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.
*/
#ifndef VK_INSTANCE_PFN
# define VK_INSTANCE_PFN(x)
#endif
#ifndef VK_DEVICE_PFN
# define VK_DEVICE_PFN(x)
#endif
/* Instance functions (obtained by vkGetInstanceProcAddr). */
VK_INSTANCE_PFN(vkCreateDevice)
VK_INSTANCE_PFN(vkDestroyInstance)
VK_INSTANCE_PFN(vkEnumerateDeviceExtensionProperties)
VK_INSTANCE_PFN(vkEnumerateDeviceLayerProperties)
VK_INSTANCE_PFN(vkEnumeratePhysicalDevices)
VK_INSTANCE_PFN(vkGetDeviceProcAddr)
VK_INSTANCE_PFN(vkGetPhysicalDeviceFeatures)
VK_INSTANCE_PFN(vkGetPhysicalDeviceFormatProperties)
VK_INSTANCE_PFN(vkGetPhysicalDeviceImageFormatProperties)
VK_INSTANCE_PFN(vkGetPhysicalDeviceMemoryProperties)
VK_INSTANCE_PFN(vkGetPhysicalDeviceProperties)
VK_INSTANCE_PFN(vkGetPhysicalDeviceQueueFamilyProperties)
VK_INSTANCE_PFN(vkGetPhysicalDeviceSparseImageFormatProperties)
/* Device functions (obtained by vkGetDeviceProcAddr). */
VK_DEVICE_PFN(vkAllocateCommandBuffers)
VK_DEVICE_PFN(vkAllocateDescriptorSets)
VK_DEVICE_PFN(vkAllocateMemory)
VK_DEVICE_PFN(vkBeginCommandBuffer)
VK_DEVICE_PFN(vkBindBufferMemory)
VK_DEVICE_PFN(vkBindImageMemory)
VK_DEVICE_PFN(vkCmdBeginQuery)
VK_DEVICE_PFN(vkCmdBeginRenderPass)
VK_DEVICE_PFN(vkCmdBindDescriptorSets)
VK_DEVICE_PFN(vkCmdBindIndexBuffer)
VK_DEVICE_PFN(vkCmdBindPipeline)
VK_DEVICE_PFN(vkCmdBindVertexBuffers)
VK_DEVICE_PFN(vkCmdBlitImage)
VK_DEVICE_PFN(vkCmdClearAttachments)
VK_DEVICE_PFN(vkCmdClearColorImage)
VK_DEVICE_PFN(vkCmdClearDepthStencilImage)
VK_DEVICE_PFN(vkCmdCopyBuffer)
VK_DEVICE_PFN(vkCmdCopyBufferToImage)
VK_DEVICE_PFN(vkCmdCopyImage)
VK_DEVICE_PFN(vkCmdCopyImageToBuffer)
VK_DEVICE_PFN(vkCmdCopyQueryPoolResults)
VK_DEVICE_PFN(vkCmdDispatch)
VK_DEVICE_PFN(vkCmdDispatchIndirect)
VK_DEVICE_PFN(vkCmdDraw)
VK_DEVICE_PFN(vkCmdDrawIndexed)
VK_DEVICE_PFN(vkCmdDrawIndexedIndirect)
VK_DEVICE_PFN(vkCmdDrawIndirect)
VK_DEVICE_PFN(vkCmdEndQuery)
VK_DEVICE_PFN(vkCmdEndRenderPass)
VK_DEVICE_PFN(vkCmdExecuteCommands)
VK_DEVICE_PFN(vkCmdFillBuffer)
VK_DEVICE_PFN(vkCmdNextSubpass)
VK_DEVICE_PFN(vkCmdPipelineBarrier)
VK_DEVICE_PFN(vkCmdPushConstants)
VK_DEVICE_PFN(vkCmdResetEvent)
VK_DEVICE_PFN(vkCmdResetQueryPool)
VK_DEVICE_PFN(vkCmdResolveImage)
VK_DEVICE_PFN(vkCmdSetBlendConstants)
VK_DEVICE_PFN(vkCmdSetDepthBias)
VK_DEVICE_PFN(vkCmdSetDepthBounds)
VK_DEVICE_PFN(vkCmdSetEvent)
VK_DEVICE_PFN(vkCmdSetLineWidth)
VK_DEVICE_PFN(vkCmdSetScissor)
VK_DEVICE_PFN(vkCmdSetStencilCompareMask)
VK_DEVICE_PFN(vkCmdSetStencilReference)
VK_DEVICE_PFN(vkCmdSetStencilWriteMask)
VK_DEVICE_PFN(vkCmdSetViewport)
VK_DEVICE_PFN(vkCmdUpdateBuffer)
VK_DEVICE_PFN(vkCmdWaitEvents)
VK_DEVICE_PFN(vkCmdWriteTimestamp)
VK_DEVICE_PFN(vkCreateBuffer)
VK_DEVICE_PFN(vkCreateBufferView)
VK_DEVICE_PFN(vkCreateCommandPool)
VK_DEVICE_PFN(vkCreateComputePipelines)
VK_DEVICE_PFN(vkCreateDescriptorPool)
VK_DEVICE_PFN(vkCreateDescriptorSetLayout)
VK_DEVICE_PFN(vkCreateEvent)
VK_DEVICE_PFN(vkCreateFence)
VK_DEVICE_PFN(vkCreateFramebuffer)
VK_DEVICE_PFN(vkCreateGraphicsPipelines)
VK_DEVICE_PFN(vkCreateImage)
VK_DEVICE_PFN(vkCreateImageView)
VK_DEVICE_PFN(vkCreatePipelineCache)
VK_DEVICE_PFN(vkCreatePipelineLayout)
VK_DEVICE_PFN(vkCreateQueryPool)
VK_DEVICE_PFN(vkCreateRenderPass)
VK_DEVICE_PFN(vkCreateSampler)
VK_DEVICE_PFN(vkCreateSemaphore)
VK_DEVICE_PFN(vkCreateShaderModule)
VK_DEVICE_PFN(vkDestroyBuffer)
VK_DEVICE_PFN(vkDestroyBufferView)
VK_DEVICE_PFN(vkDestroyCommandPool)
VK_DEVICE_PFN(vkDestroyDescriptorPool)
VK_DEVICE_PFN(vkDestroyDescriptorSetLayout)
VK_DEVICE_PFN(vkDestroyDevice)
VK_DEVICE_PFN(vkDestroyEvent)
VK_DEVICE_PFN(vkDestroyFence)
VK_DEVICE_PFN(vkDestroyFramebuffer)
VK_DEVICE_PFN(vkDestroyImage)
VK_DEVICE_PFN(vkDestroyImageView)
VK_DEVICE_PFN(vkDestroyPipeline)
VK_DEVICE_PFN(vkDestroyPipelineCache)
VK_DEVICE_PFN(vkDestroyPipelineLayout)
VK_DEVICE_PFN(vkDestroyQueryPool)
VK_DEVICE_PFN(vkDestroyRenderPass)
VK_DEVICE_PFN(vkDestroySampler)
VK_DEVICE_PFN(vkDestroySemaphore)
VK_DEVICE_PFN(vkDestroyShaderModule)
VK_DEVICE_PFN(vkDeviceWaitIdle)
VK_DEVICE_PFN(vkEndCommandBuffer)
VK_DEVICE_PFN(vkFlushMappedMemoryRanges)
VK_DEVICE_PFN(vkFreeCommandBuffers)
VK_DEVICE_PFN(vkFreeDescriptorSets)
VK_DEVICE_PFN(vkFreeMemory)
VK_DEVICE_PFN(vkGetBufferMemoryRequirements)
VK_DEVICE_PFN(vkGetDeviceMemoryCommitment)
VK_DEVICE_PFN(vkGetDeviceQueue)
VK_DEVICE_PFN(vkGetEventStatus)
VK_DEVICE_PFN(vkGetFenceStatus)
VK_DEVICE_PFN(vkGetImageMemoryRequirements)
VK_DEVICE_PFN(vkGetImageSparseMemoryRequirements)
VK_DEVICE_PFN(vkGetImageSubresourceLayout)
VK_DEVICE_PFN(vkGetPipelineCacheData)
VK_DEVICE_PFN(vkGetQueryPoolResults)
VK_DEVICE_PFN(vkGetRenderAreaGranularity)
VK_DEVICE_PFN(vkInvalidateMappedMemoryRanges)
VK_DEVICE_PFN(vkMapMemory)
VK_DEVICE_PFN(vkMergePipelineCaches)
VK_DEVICE_PFN(vkQueueBindSparse)
VK_DEVICE_PFN(vkQueueSubmit)
VK_DEVICE_PFN(vkQueueWaitIdle)
VK_DEVICE_PFN(vkResetCommandBuffer)
VK_DEVICE_PFN(vkResetCommandPool)
VK_DEVICE_PFN(vkResetDescriptorPool)
VK_DEVICE_PFN(vkResetEvent)
VK_DEVICE_PFN(vkResetFences)
VK_DEVICE_PFN(vkSetEvent)
VK_DEVICE_PFN(vkUnmapMemory)
VK_DEVICE_PFN(vkUpdateDescriptorSets)
VK_DEVICE_PFN(vkWaitForFences)
#undef VK_INSTANCE_PFN
#undef VK_DEVICE_PFN