From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- include/vkd3d.h | 3 +++ libs/vkd3d/device.c | 52 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/include/vkd3d.h b/include/vkd3d.h index 033017e78f2f..de75ee3a3894 100644 --- a/include/vkd3d.h +++ b/include/vkd3d.h @@ -66,6 +66,9 @@ struct vkd3d_device_create_info
VkPhysicalDevice vk_physical_device;
+ const char * const *device_extensions; + uint32_t device_extension_count; + LUID adapter_luid; };
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index e6210fc4dc9d..bec8f354c3d2 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -50,9 +50,6 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = {VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, offsetof(struct vkd3d_vulkan_info, KHR_push_descriptor)}, };
-#define MAX_DEVICE_EXTENSION_COUNT \ - (ARRAY_SIZE(required_device_extensions) + ARRAY_SIZE(optional_device_extensions)) - static bool is_extension_disabled(const char *extension_name) { const char *disabled_extensions; @@ -673,8 +670,9 @@ static void vkd3d_check_feature_level_11_requirements(const VkPhysicalDeviceLimi #undef CHECK_FEATURE }
-static void vkd3d_init_device_caps(struct d3d12_device *device, - const VkPhysicalDeviceFeatures *features) +static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, + const struct vkd3d_device_create_info *create_info, + const VkPhysicalDeviceFeatures *features, uint32_t *device_extension_count) { const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs; VkPhysicalDevice physical_device = device->vk_physical_device; @@ -684,6 +682,8 @@ static void vkd3d_init_device_caps(struct d3d12_device *device, uint32_t count; VkResult vr;
+ *device_extension_count = 0; + VK_CALL(vkGetPhysicalDeviceProperties(physical_device, &device_properties)); vulkan_info->device_limits = device_properties.limits; vulkan_info->sparse_properties = device_properties.sparseProperties; @@ -729,13 +729,13 @@ static void vkd3d_init_device_caps(struct d3d12_device *device, &count, NULL))) < 0) { ERR("Failed to enumerate device extensions, vr %d.\n", vr); - return; + return hresult_from_vk_result(vr); } if (!count) - return; + return S_OK;
if (!(vk_extensions = vkd3d_calloc(count, sizeof(*vk_extensions)))) - return; + return E_OUTOFMEMORY;
TRACE("Enumerating %u device extensions.\n", count); if ((vr = VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device, NULL, @@ -743,15 +743,17 @@ static void vkd3d_init_device_caps(struct d3d12_device *device, { ERR("Failed to enumerate device extensions, vr %d.\n", vr); vkd3d_free(vk_extensions); - return; + return hresult_from_vk_result(vr); }
- vkd3d_check_extensions(vk_extensions, count, + *device_extension_count = vkd3d_check_extensions(vk_extensions, count, required_device_extensions, ARRAY_SIZE(required_device_extensions), optional_device_extensions, ARRAY_SIZE(optional_device_extensions), - NULL, 0, vulkan_info, "device"); + create_info->device_extensions, create_info->device_extension_count, + vulkan_info, "device");
vkd3d_free(vk_extensions); + return S_OK; }
static HRESULT vkd3d_select_physical_device(struct vkd3d_instance *instance, @@ -855,24 +857,28 @@ static HRESULT d3d12_device_create_vkd3d_queues(struct d3d12_device *device, return S_OK; }
-static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, VkPhysicalDevice physical_device) +static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, + const struct vkd3d_device_create_info *create_info) { uint32_t direct_queue_timestamp_bits, copy_queue_timestamp_bits, compute_queue_timestamp_bits; unsigned int direct_queue_family_index, copy_queue_family_index, compute_queue_family_index; const struct vkd3d_vk_instance_procs *vk_procs = &device->vkd3d_instance->vk_procs; - const char *extensions[MAX_DEVICE_EXTENSION_COUNT]; VkQueueFamilyProperties *queue_properties; VkPhysicalDeviceFeatures device_features; VkDeviceQueueCreateInfo *queue_info; + VkPhysicalDevice physical_device; VkDeviceCreateInfo device_info; uint32_t queue_family_count; + uint32_t extension_count; + const char **extensions; VkDevice vk_device; unsigned int i; VkResult vr; HRESULT hr;
- TRACE("device %p, physical_device %p.\n", device, physical_device); + TRACE("device %p, create_info %p.\n", device, create_info);
+ physical_device = create_info->vk_physical_device; if (!physical_device && FAILED(hr = vkd3d_select_physical_device(device->vkd3d_instance, &physical_device))) return hr; @@ -954,7 +960,17 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, VkPhysicalDev
VK_CALL(vkGetPhysicalDeviceFeatures(physical_device, &device_features)); device->vk_physical_device = physical_device; - vkd3d_init_device_caps(device, &device_features); + if (FAILED(hr = vkd3d_init_device_caps(device, create_info, &device_features, &extension_count))) + { + vkd3d_free(queue_info); + return E_FAIL; + } + + if (!(extensions = vkd3d_calloc(extension_count, sizeof(*extensions)))) + { + vkd3d_free(queue_info); + return E_OUTOFMEMORY; + }
/* Create device */ device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; @@ -967,11 +983,13 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, VkPhysicalDev device_info.enabledExtensionCount = vkd3d_enable_extensions(extensions, required_device_extensions, ARRAY_SIZE(required_device_extensions), optional_device_extensions, ARRAY_SIZE(optional_device_extensions), - NULL, 0, &device->vk_info); + create_info->device_extensions, create_info->device_extension_count, + &device->vk_info); device_info.ppEnabledExtensionNames = extensions; device_info.pEnabledFeatures = &device_features;
vr = VK_CALL(vkCreateDevice(physical_device, &device_info, NULL, &vk_device)); + vkd3d_free(extensions); vkd3d_free(queue_info); if (vr < 0) { @@ -2137,7 +2155,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
device->adapter_luid = create_info->adapter_luid;
- if (FAILED(hr = vkd3d_create_vk_device(device, create_info->vk_physical_device))) + if (FAILED(hr = vkd3d_create_vk_device(device, create_info))) { vkd3d_instance_decref(device->vkd3d_instance); return hr;
From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- tests/vkd3d_api.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 128 insertions(+), 21 deletions(-)
diff --git a/tests/vkd3d_api.c b/tests/vkd3d_api.c index 9efc02a6175a..4def3b7e53e2 100644 --- a/tests/vkd3d_api.c +++ b/tests/vkd3d_api.c @@ -109,12 +109,33 @@ struct vulkan_extension bool is_supported; };
+static uint32_t check_extensions(const char **enabled_extensions, + struct vulkan_extension *extensions, unsigned int extension_count, + const VkExtensionProperties *properties, unsigned int count) +{ + uint32_t enabled_extension_count = 0; + unsigned int i, j; + + for (i = 0; i < count; ++i) + { + for (j = 0; j < extension_count; ++j) + { + if (!strcmp(properties[i].extensionName, extensions[j].name)) + { + extensions[j].is_supported = true; + enabled_extensions[enabled_extension_count++] = extensions[j].name; + } + } + } + + return enabled_extension_count; +} + static uint32_t check_instance_extensions(const char **enabled_extensions, struct vulkan_extension *extensions, unsigned int extension_count) { VkExtensionProperties *properties; uint32_t enabled_extension_count; - unsigned int i, j; uint32_t count; VkResult vr;
@@ -127,27 +148,47 @@ static uint32_t check_instance_extensions(const char **enabled_extensions, ok(properties, "Failed to allocate memory.\n"); vr = vkEnumerateInstanceExtensionProperties(NULL, &count, properties); ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr); + enabled_extension_count = check_extensions(enabled_extensions, + extensions, extension_count, properties, count); + free(properties); + return enabled_extension_count; +}
- enabled_extension_count = 0; - for (i = 0; i < count; ++i) - { - for (j = 0; j < extension_count; ++j) - { - if (!strcmp(properties[i].extensionName, extensions[j].name)) - { - extensions[j].is_supported = true; - enabled_extensions[enabled_extension_count++] = extensions[j].name; - } - } - } +static uint32_t check_device_extensions(VkPhysicalDevice vk_physical_device, + const char **enabled_extensions, struct vulkan_extension *extensions, + unsigned int extension_count) +{ + VkExtensionProperties *properties; + uint32_t enabled_extension_count; + uint32_t count; + VkResult vr; + + vr = vkEnumerateDeviceExtensionProperties(vk_physical_device, NULL, &count, NULL); + ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr); + if (!count) + return 0; + + properties = calloc(count, sizeof(*properties)); + ok(properties, "Failed to allocate memory.\n"); + vr = vkEnumerateDeviceExtensionProperties(vk_physical_device, NULL, &count, properties); + ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr); + enabled_extension_count = check_extensions(enabled_extensions, + extensions, extension_count, properties, count); free(properties); return enabled_extension_count; }
static void test_additional_instance_extensions(void) { + struct vulkan_extension extensions[] = + { + {VK_KHR_SURFACE_EXTENSION_NAME}, + {VK_KHR_XCB_SURFACE_EXTENSION_NAME}, + {VK_KHR_XLIB_SURFACE_EXTENSION_NAME}, + }; + + const char *enabled_extensions[ARRAY_SIZE(extensions)]; struct vkd3d_instance_create_info create_info; - const char *enabled_extensions[3]; struct vkd3d_instance *instance; uint32_t extension_count; PFN_vkVoidFunction pfn; @@ -156,13 +197,6 @@ static void test_additional_instance_extensions(void) ULONG refcount; HRESULT hr;
- struct vulkan_extension extensions[] = - { - {VK_KHR_SURFACE_EXTENSION_NAME}, - {VK_KHR_XCB_SURFACE_EXTENSION_NAME}, - {VK_KHR_XLIB_SURFACE_EXTENSION_NAME}, - }; - if (!(extension_count = check_instance_extensions(enabled_extensions, extensions, ARRAY_SIZE(extensions)))) { @@ -342,6 +376,78 @@ static void test_required_device_extensions(void) ok(!refcount, "Instance has %u references left.\n", refcount); }
+static void test_additional_device_extensions(void) +{ + struct vulkan_extension extensions[] = + { + {VK_KHR_SWAPCHAIN_EXTENSION_NAME}, + }; + + struct vkd3d_instance_create_info instance_create_info; + const char *enabled_extensions[ARRAY_SIZE(extensions)]; + struct vkd3d_device_create_info device_create_info; + VkPhysicalDevice vk_physical_device; + struct vkd3d_instance *instance; + uint32_t extension_count; + PFN_vkVoidFunction pfn; + VkInstance vk_instance; + ID3D12Device *device; + VkDevice vk_device; + uint32_t count; + ULONG refcount; + VkResult vr; + HRESULT hr; + + /* Required by VK_KHR_swapchain. */ + enabled_extensions[0] = VK_KHR_SURFACE_EXTENSION_NAME; + extension_count = 1; + + instance_create_info = instance_default_create_info; + instance_create_info.instance_extensions = enabled_extensions; + instance_create_info.instance_extension_count = extension_count; + if (FAILED(hr = vkd3d_create_instance(&instance_create_info, &instance))) + { + skip("Failed to create instance, hr %#x.\n", hr); + return; + } + ok(hr == S_OK, "Failed to create instance, hr %#x.\n", hr); + vk_instance = vkd3d_instance_get_vk_instance(instance); + ok(vk_instance != VK_NULL_HANDLE, "Failed to get Vulkan instance.\n"); + + vr = vkEnumeratePhysicalDevices(vk_instance, &count, NULL); + ok(vr == VK_SUCCESS, "Got unexpected VkResult %d.\n", vr); + count = 1; + vr = vkEnumeratePhysicalDevices(vk_instance, &count, &vk_physical_device); + ok(vr == VK_SUCCESS || vr == VK_INCOMPLETE, "Got unexpected VkResult %d.\n", vr); + + if (!(extension_count = check_device_extensions(vk_physical_device, + enabled_extensions, extensions, ARRAY_SIZE(extensions)))) + { + skip("%s is not available.\n", VK_KHR_SWAPCHAIN_EXTENSION_NAME); + vkd3d_instance_decref(instance); + return; + } + + device_create_info = device_default_create_info; + device_create_info.instance = instance; + device_create_info.instance_create_info = NULL; + device_create_info.vk_physical_device = vk_physical_device; + device_create_info.device_extensions = enabled_extensions; + device_create_info.device_extension_count = extension_count; + hr = vkd3d_create_device(&device_create_info, &IID_ID3D12Device, (void **)&device); + ok(hr == S_OK, "Failed to create device, hr %#x.\n", hr); + + vk_device = vkd3d_get_vk_device(device); + + pfn = vkGetDeviceProcAddr(vk_device, "vkCreateSwapchainKHR"); + ok(pfn, "Failed to get proc addr for vkCreateSwapchainKHR.\n"); + + refcount = ID3D12Device_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + refcount = vkd3d_instance_decref(instance); + ok(!refcount, "Instance has %u references left.\n", refcount); +} + static void test_physical_device(void) { struct vkd3d_device_create_info create_info; @@ -482,6 +588,7 @@ START_TEST(vkd3d_api) run_test(test_additional_instance_extensions); run_test(test_create_device); run_test(test_required_device_extensions); + run_test(test_additional_device_extensions); run_test(test_physical_device); run_test(test_adapter_luid); run_test(test_vkd3d_queue);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
In preparation for the next patch.
In order to make D3D12CreateDevice() generally usable. We may consider enabling more extensions in the future.
--- libs/vkd3d-utils/vkd3d_utils_main.c | 26 ++++++++++++++++++++------ libs/vkd3d-utils/vkd3d_utils_private.h | 3 +++ 2 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-utils/vkd3d_utils_main.c b/libs/vkd3d-utils/vkd3d_utils_main.c index fb4344ebf086..4537de051a07 100644 --- a/libs/vkd3d-utils/vkd3d_utils_main.c +++ b/libs/vkd3d-utils/vkd3d_utils_main.c @@ -18,21 +18,31 @@
#include "vkd3d_utils_private.h"
-HRESULT WINAPI D3D12GetDebugInterface(REFIID riid, void **debug) +HRESULT WINAPI D3D12GetDebugInterface(REFIID iid, void **debug) { - FIXME("riid %s, debug %p stub!\n", debugstr_guid(riid), debug); + FIXME("iid %s, debug %p stub!\n", debugstr_guid(iid), debug);
return E_NOTIMPL; }
HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter, - D3D_FEATURE_LEVEL minimum_feature_level, REFIID riid, void **device) + D3D_FEATURE_LEVEL minimum_feature_level, REFIID iid, void **device) { struct vkd3d_instance_create_info instance_create_info; struct vkd3d_device_create_info device_create_info;
- TRACE("adapter %p, minimum_feature_level %#x, riid %s, device %p.\n", - adapter, minimum_feature_level, debugstr_guid(riid), device); + static const char * const instance_extensions[] = + { + VK_KHR_SURFACE_EXTENSION_NAME, + VK_KHR_XCB_SURFACE_EXTENSION_NAME, + }; + static const char * const device_extensions[] = + { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + }; + + TRACE("adapter %p, minimum_feature_level %#x, iid %s, device %p.\n", + adapter, minimum_feature_level, debugstr_guid(iid), device);
if (adapter) FIXME("Ignoring adapter %p.\n", adapter); @@ -40,12 +50,16 @@ HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter, memset(&instance_create_info, 0, sizeof(instance_create_info)); instance_create_info.signal_event_pfn = vkd3d_signal_event; instance_create_info.wchar_size = sizeof(WCHAR); + instance_create_info.instance_extensions = instance_extensions; + instance_create_info.instance_extension_count = ARRAY_SIZE(instance_extensions);
memset(&device_create_info, 0, sizeof(device_create_info)); device_create_info.minimum_feature_level = minimum_feature_level; device_create_info.instance_create_info = &instance_create_info; + device_create_info.device_extensions = device_extensions; + device_create_info.device_extension_count = ARRAY_SIZE(device_extensions);
- return vkd3d_create_device(&device_create_info, riid, device); + return vkd3d_create_device(&device_create_info, iid, device); }
HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const void *data, SIZE_T data_size, diff --git a/libs/vkd3d-utils/vkd3d_utils_private.h b/libs/vkd3d-utils/vkd3d_utils_private.h index d4a89eeb6c3c..6aa0df6eeef5 100644 --- a/libs/vkd3d-utils/vkd3d_utils_private.h +++ b/libs/vkd3d-utils/vkd3d_utils_private.h @@ -19,6 +19,9 @@ #ifndef __VKD3D_UTILS_PRIVATE_H #define __VKD3D_UTILS_PRIVATE_H
+#define VK_NO_PROTOTYPES +#define VK_USE_PLATFORM_XCB_KHR + #include <pthread.h> #include <vkd3d.h>
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
libvkd3d doesn't use them.
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- libs/vkd3d/device.c | 13 ++----------- libs/vkd3d/vkd3d_private.h | 1 - 2 files changed, 2 insertions(+), 12 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index bec8f354c3d2..865801465011 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -26,12 +26,6 @@ struct vkd3d_optional_extension_info ptrdiff_t vulkan_info_offset; };
-static const char * const required_instance_extensions[] = -{ - VK_KHR_SURFACE_EXTENSION_NAME, - VK_KHR_XCB_SURFACE_EXTENSION_NAME, -}; - static const struct vkd3d_optional_extension_info optional_instance_extensions[] = { {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, @@ -41,7 +35,6 @@ static const struct vkd3d_optional_extension_info optional_instance_extensions[] static const char * const required_device_extensions[] = { VK_KHR_MAINTENANCE1_EXTENSION_NAME, - VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, };
@@ -195,8 +188,7 @@ static HRESULT vkd3d_init_instance_caps(struct vkd3d_instance *instance, return hresult_from_vk_result(vr); }
- *instance_extension_count = vkd3d_check_extensions(vk_extensions, count, - required_instance_extensions, ARRAY_SIZE(required_instance_extensions), + *instance_extension_count = vkd3d_check_extensions(vk_extensions, count, NULL, 0, optional_instance_extensions, ARRAY_SIZE(optional_instance_extensions), create_info->instance_extensions, create_info->instance_extension_count, vulkan_info, "instance"); @@ -309,8 +301,7 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance, instance_info.pApplicationInfo = &application_info; instance_info.enabledLayerCount = 0; instance_info.ppEnabledLayerNames = NULL; - instance_info.enabledExtensionCount = vkd3d_enable_extensions(extensions, - required_instance_extensions, ARRAY_SIZE(required_instance_extensions), + instance_info.enabledExtensionCount = vkd3d_enable_extensions(extensions, NULL, 0, optional_instance_extensions, ARRAY_SIZE(optional_instance_extensions), create_info->instance_extensions, create_info->instance_extension_count, &instance->vk_info); diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index b3607853fdc1..a60ee991d1ea 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -20,7 +20,6 @@ #define __VKD3D_PRIVATE_H
#define VK_NO_PROTOTYPES -#define VK_USE_PLATFORM_XCB_KHR
#define COBJMACROS #define NONAMELESSUNION
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
From: Józef Kucia jkucia@codeweavers.com
For swapchain back buffers.
Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
In Wine, we use wined3d objects to implement internal reference counting for D3D11. We need internal reference counting for swapchain back buffers in D3D12. D3D12 swapchains hold internal references to back buffers, but public/COM reference counts are equal to 0. This patch adds explicit support for internal reference counting for ID3D12Resources.
--- include/vkd3d.h | 9 ++++-- libs/vkd3d/resource.c | 49 ++++++++++++++++++++++++++++-- libs/vkd3d/vkd3d.map | 2 ++ libs/vkd3d/vkd3d_private.h | 1 + tests/vkd3d_api.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 5 deletions(-)
diff --git a/include/vkd3d.h b/include/vkd3d.h index de75ee3a3894..8f2c9b52b2a3 100644 --- a/include/vkd3d.h +++ b/include/vkd3d.h @@ -83,9 +83,7 @@ VkInstance vkd3d_instance_get_vk_instance(struct vkd3d_instance *instance); ULONG vkd3d_instance_incref(struct vkd3d_instance *instance);
HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info, - REFIID riid, void **device); -HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_DESC *desc, - VkImage vk_image, unsigned int resource_flags, ID3D12Resource **resource); + REFIID iid, void **device); VkDevice vkd3d_get_vk_device(ID3D12Device *device); VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device); struct vkd3d_instance *vkd3d_instance_from_device(ID3D12Device *device); @@ -94,6 +92,11 @@ uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue); VkQueue vkd3d_acquire_vk_queue(ID3D12CommandQueue *queue); void vkd3d_release_vk_queue(ID3D12CommandQueue *queue);
+HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_DESC *desc, + VkImage vk_image, unsigned int resource_flags, ID3D12Resource **resource); +ULONG vkd3d_resource_decref(ID3D12Resource *resource); +ULONG vkd3d_resource_incref(ID3D12Resource *resource); + HRESULT vkd3d_serialize_root_signature(const D3D12_ROOT_SIGNATURE_DESC *root_signature_desc, D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob);
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 264578bd31a8..712ff9c748f6 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -332,6 +332,30 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12 VK_CALL(vkFreeMemory(device->vk_device, resource->vk_memory, NULL)); }
+static ULONG d3d12_resource_incref(struct d3d12_resource *resource) +{ + ULONG refcount = InterlockedIncrement(&resource->internal_refcount); + + TRACE("%p increasing refcount to %u.\n", resource, refcount); + + return refcount; +} + +static ULONG d3d12_resource_decref(struct d3d12_resource *resource) +{ + ULONG refcount = InterlockedDecrement(&resource->internal_refcount); + + TRACE("%p decreasing refcount to %u.\n", resource, refcount); + + if (!refcount) + { + d3d12_resource_destroy(resource, resource->device); + vkd3d_free(resource); + } + + return refcount; +} + /* ID3D12Resource */ static inline struct d3d12_resource *impl_from_ID3D12Resource(ID3D12Resource *iface) { @@ -367,6 +391,14 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource *iface)
TRACE("%p increasing refcount to %u.\n", resource, refcount);
+ if (refcount == 1) + { + struct d3d12_device *device = resource->device; + + ID3D12Device_AddRef(&device->ID3D12Device_iface); + d3d12_resource_incref(resource); + } + return refcount; }
@@ -381,8 +413,7 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource *iface) { struct d3d12_device *device = resource->device;
- d3d12_resource_destroy(resource, device); - vkd3d_free(resource); + d3d12_resource_decref(resource);
ID3D12Device_Release(&device->ID3D12Device_iface); } @@ -641,6 +672,7 @@ static HRESULT d3d12_committed_resource_init(struct d3d12_resource *resource, st
resource->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl; resource->refcount = 1; + resource->internal_refcount = 1;
resource->desc = *desc;
@@ -773,6 +805,7 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_D
object->ID3D12Resource_iface.lpVtbl = &d3d12_resource_vtbl; object->refcount = 1; + object->internal_refcount = 1; object->desc = *desc; object->u.vk_image = vk_image; object->vk_memory = VK_NULL_HANDLE; @@ -793,6 +826,18 @@ HRESULT vkd3d_create_image_resource(ID3D12Device *device, const D3D12_RESOURCE_D return S_OK; }
+ULONG vkd3d_resource_incref(ID3D12Resource *resource) +{ + TRACE("resource %p.\n", resource); + return d3d12_resource_incref(impl_from_ID3D12Resource(resource)); +} + +ULONG vkd3d_resource_decref(ID3D12Resource *resource) +{ + TRACE("resource %p.\n", resource); + return d3d12_resource_decref(impl_from_ID3D12Resource(resource)); +} + /* CBVs, SRVs, UAVs */ static struct vkd3d_view *vkd3d_view_create(void) { diff --git a/libs/vkd3d/vkd3d.map b/libs/vkd3d/vkd3d.map index 9edc3aa5af1c..246275b97a30 100644 --- a/libs/vkd3d/vkd3d.map +++ b/libs/vkd3d/vkd3d.map @@ -15,6 +15,8 @@ global: vkd3d_instance_get_vk_instance; vkd3d_instance_incref; vkd3d_release_vk_queue; + vkd3d_resource_decref; + vkd3d_resource_incref; vkd3d_serialize_root_signature;
local: *; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index a60ee991d1ea..691305158bd7 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -183,6 +183,7 @@ struct d3d12_resource { ID3D12Resource ID3D12Resource_iface; LONG refcount; + LONG internal_refcount;
D3D12_RESOURCE_DESC desc;
diff --git a/tests/vkd3d_api.c b/tests/vkd3d_api.c index 4def3b7e53e2..fc8d985981f5 100644 --- a/tests/vkd3d_api.c +++ b/tests/vkd3d_api.c @@ -24,6 +24,12 @@ #include "vkd3d_test.h" #include <vkd3d.h>
+static ULONG resource_get_internal_refcount(ID3D12Resource *resource) +{ + vkd3d_resource_incref(resource); + return vkd3d_resource_decref(resource); +} + static bool signal_event(HANDLE event) { trace("Signal event %p.\n", event); @@ -69,6 +75,36 @@ static ID3D12CommandQueue *create_command_queue(ID3D12Device *device, return queue; }
+static ID3D12Resource *create_buffer(ID3D12Device *device, D3D12_HEAP_TYPE heap_type, + size_t size, D3D12_RESOURCE_FLAGS resource_flags, D3D12_RESOURCE_STATES initial_resource_state) +{ + D3D12_HEAP_PROPERTIES heap_properties; + D3D12_RESOURCE_DESC resource_desc; + ID3D12Resource *buffer; + HRESULT hr; + + memset(&heap_properties, 0, sizeof(heap_properties)); + heap_properties.Type = heap_type; + + resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + resource_desc.Alignment = 0; + resource_desc.Width = size; + resource_desc.Height = 1; + resource_desc.DepthOrArraySize = 1; + resource_desc.MipLevels = 1; + resource_desc.Format = DXGI_FORMAT_UNKNOWN; + resource_desc.SampleDesc.Count = 1; + resource_desc.SampleDesc.Quality = 0; + resource_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + resource_desc.Flags = resource_flags; + + hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, + D3D12_HEAP_FLAG_NONE, &resource_desc, initial_resource_state, + NULL, &IID_ID3D12Resource, (void **)&buffer); + ok(hr == S_OK, "Failed to create buffer, hr %#x.\n", hr); + return buffer; +} + static void test_create_instance(void) { struct vkd3d_instance_create_info create_info; @@ -567,6 +603,45 @@ static void test_vkd3d_queue(void) ok(!refcount, "Device has %u references left.\n", refcount); }
+static void test_resource_internal_refcount(void) +{ + ID3D12Resource *resource; + ID3D12Device *device; + ULONG refcount; + + device = create_device(); + ok(device, "Failed to create device.\n"); + + resource = create_buffer(device, D3D12_HEAP_TYPE_UPLOAD, 1024, + D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_GENERIC_READ); + refcount = vkd3d_resource_incref(resource); + ok(refcount == 2, "Got refcount %u.\n", refcount); + refcount = ID3D12Resource_Release(resource); + ok(!refcount, "Got refcount %u.\n", refcount); + refcount = resource_get_internal_refcount(resource); + ok(refcount == 1, "Got refcount %u.\n", refcount); + refcount = vkd3d_resource_decref(resource); + ok(!refcount, "Got refcount %u.\n", refcount); + + resource = create_buffer(device, D3D12_HEAP_TYPE_UPLOAD, 1024, + D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_GENERIC_READ); + refcount = vkd3d_resource_incref(resource); + ok(refcount == 2, "Got refcount %u.\n", refcount); + refcount = ID3D12Resource_Release(resource); + ok(!refcount, "Got refcount %u.\n", refcount); + refcount = resource_get_internal_refcount(resource); + ok(refcount == 1, "Got refcount %u.\n", refcount); + refcount = ID3D12Resource_AddRef(resource); + ok(refcount == 1, "Got refcount %u.\n", refcount); + refcount = vkd3d_resource_decref(resource); + ok(refcount == 1, "Got refcount %u.\n", refcount); + refcount = ID3D12Resource_Release(resource); + ok(!refcount, "Got refcount %u.\n", refcount); + + refcount = ID3D12Device_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); +} + static bool have_d3d12_device(void) { ID3D12Device *device; @@ -592,4 +667,5 @@ START_TEST(vkd3d_api) run_test(test_physical_device); run_test(test_adapter_luid); run_test(test_vkd3d_queue); + run_test(test_resource_internal_refcount); }
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com