diff --git a/configure.ac b/configure.ac index 6dd107ed..af7b87eb 100644 --- a/configure.ac +++ b/configure.ac @@ -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( diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index e775d1d5..33afe32a 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -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); diff --git a/libs/vkd3d/utils.c b/libs/vkd3d/utils.c index f5ed1d9f..862cb124 100644 --- a/libs/vkd3d/utils.c +++ b/libs/vkd3d/utils.c @@ -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; +} diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 3b919658..762f8e15 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -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 */ diff --git a/libs/vkd3d/vkd3d_vulkan.h b/libs/vkd3d/vkd3d_vulkan.h new file mode 100644 index 00000000..7c5c6854 --- /dev/null +++ b/libs/vkd3d/vkd3d_vulkan.h @@ -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 */ diff --git a/libs/vkd3d/vulkan_procs.h b/libs/vkd3d/vulkan_procs.h new file mode 100644 index 00000000..d8841998 --- /dev/null +++ b/libs/vkd3d/vulkan_procs.h @@ -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