From: Stefan Dösinger stefan@codeweavers.com
--- libs/vkd3d/device.c | 9 ++++- libs/vkd3d/state.c | 69 +++++++++++++++++++++++++++++++++----- libs/vkd3d/vkd3d_private.h | 5 +++ tests/d3d12.c | 8 ++--- 4 files changed, 77 insertions(+), 14 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index d07bfa67f..93771d638 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -2632,6 +2632,7 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface) if (device->use_vk_heaps) device_worker_stop(device); vkd3d_free(device->heaps); + vkd3d_root_signature_cache_cleanup(device->root_signature_cache, device); vkd3d_shader_cache_close(device->persistent_cache); VK_CALL(vkDestroyDevice(device->vk_device, NULL)); if (device->parent) @@ -4477,9 +4478,13 @@ static HRESULT d3d12_device_init(struct d3d12_device *device, } vkd3d_free(cache_name);
- if (FAILED(hr = d3d12_device_init_pipeline_cache(device))) + device->root_signature_cache = vkd3d_root_signature_cache_init(device); + if (!device->root_signature_cache) goto out_free_cache;
+ if (FAILED(hr = d3d12_device_init_pipeline_cache(device))) + goto out_free_cache2; + if (FAILED(hr = vkd3d_private_store_init(&device->private_store))) goto out_free_pipeline_cache;
@@ -4533,6 +4538,8 @@ out_free_private_store: vkd3d_private_store_destroy(&device->private_store); out_free_pipeline_cache: d3d12_device_destroy_pipeline_cache(device); +out_free_cache2: + vkd3d_shader_cache_close(device->root_signature_cache); out_free_cache: vkd3d_shader_cache_close(device->persistent_cache); out_free_vk_resources: diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index fe0405ac2..417707088 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -55,6 +55,12 @@ static ULONG STDMETHODCALLTYPE d3d12_root_signature_AddRef(ID3D12RootSignature * ULONG refcount = InterlockedIncrement(&root_signature->refcount);
TRACE("%p increasing refcount to %u.\n", root_signature, refcount); + if (refcount == 1) + { + if (FAILED(vkd3d_private_store_init(&root_signature->private_store))) + ERR("mama!!!\n"); + d3d12_device_add_ref(root_signature->device); + }
return refcount; } @@ -117,10 +123,8 @@ static ULONG STDMETHODCALLTYPE d3d12_root_signature_Release(ID3D12RootSignature if (!refcount) { struct d3d12_device *device = root_signature->device; - vkd3d_private_store_destroy(&root_signature->private_store); - d3d12_root_signature_cleanup(root_signature, device); - vkd3d_free(root_signature); d3d12_device_release(device); + vkd3d_private_store_destroy(&root_signature->private_store); }
return refcount; @@ -1411,7 +1415,7 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa binding_desc = NULL;
root_signature->ID3D12RootSignature_iface.lpVtbl = &d3d12_root_signature_vtbl; - root_signature->refcount = 1; + root_signature->refcount = 0;
root_signature->vk_pipeline_layout = VK_NULL_HANDLE; root_signature->vk_set_count = 0; @@ -1511,11 +1515,6 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa root_signature->push_constant_ranges, &root_signature->vk_pipeline_layout))) goto fail;
- if (FAILED(hr = vkd3d_private_store_init(&root_signature->private_store))) - goto fail; - - d3d12_device_add_ref(device); - return S_OK;
fail: @@ -1534,9 +1533,20 @@ HRESULT d3d12_root_signature_create(struct d3d12_device *device, struct vkd3d_shader_versioned_root_signature_desc vkd3d; } root_signature_desc; struct d3d12_root_signature *object; + uint32_t size = sizeof(object); HRESULT hr; int ret;
+ ret = vkd3d_shader_cache_get(device->root_signature_cache, bytecode, bytecode_length, + &object, &size); + if (ret == VKD3D_OK) + { + ERR("found cached root sig\n"); + *root_signature = object; + d3d12_root_signature_AddRef(&object->ID3D12RootSignature_iface); + return S_OK; + } + if ((ret = vkd3d_parse_root_signature_v_1_0(&dxbc, &root_signature_desc.vkd3d)) < 0) { WARN("Failed to parse root signature, vkd3d result %d.\n", ret); @@ -1559,11 +1569,52 @@ HRESULT d3d12_root_signature_create(struct d3d12_device *device,
TRACE("Created root signature %p.\n", object);
+ ret = vkd3d_shader_cache_put(device->root_signature_cache, bytecode, bytecode_length, + &object, size); + if (ret) + ERR("papa!\n"); + *root_signature = object; + d3d12_root_signature_AddRef(&object->ID3D12RootSignature_iface);
return S_OK; }
+struct vkd3d_shader_cache *vkd3d_root_signature_cache_init(struct d3d12_device *device) +{ + struct vkd3d_shader_cache_desc cache_desc = {0}; + struct vkd3d_shader_cache *cache; + char cache_name[64]; + + cache_desc.mem_size = ~0u; + cache_desc.max_entries = ~0u; + cache_desc.flags = VKD3D_SHADER_CACHE_FLAGS_MEMORY_ONLY; + + sprintf(cache_name, "memory:%p:root signatures", device); + if (vkd3d_shader_cache_open(cache_name, &cache_desc, &cache)) + return NULL; + + return cache; +} + +static bool vkd3d_rs_cache_cleanup(struct vkd3d_shader_cache *cache, + const void *key, uint32_t key_size, const void *value, + uint32_t value_size, void *context) +{ + struct d3d12_root_signature *root_signature = *(struct d3d12_root_signature **)value; + struct d3d12_device *device = context; + + d3d12_root_signature_cleanup(root_signature, device); + vkd3d_free(root_signature); + return true; +} + +void vkd3d_root_signature_cache_cleanup(struct vkd3d_shader_cache *cache, struct d3d12_device *device) +{ + vkd3d_shader_cache_enumerate(cache, vkd3d_rs_cache_cleanup, device); + vkd3d_shader_cache_close(device->root_signature_cache); +} + /* vkd3d_render_pass_cache */ struct vkd3d_render_pass_entry { diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 542fa98a7..13b031789 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -579,6 +579,10 @@ struct vkd3d_render_pass_entry;
struct vkd3d_shader_cache *vkd3d_render_pass_cache_init(struct d3d12_device *device); void vkd3d_render_pass_cache_cleanup(struct vkd3d_shader_cache *cache, struct d3d12_device *device); +HRESULT vkd3d_render_pass_cache_find(struct vkd3d_shader_cache *cache, struct d3d12_device *device, + const struct vkd3d_render_pass_key *key, VkRenderPass *vk_render_pass); +struct vkd3d_shader_cache *vkd3d_root_signature_cache_init(struct d3d12_device *device); +void vkd3d_root_signature_cache_cleanup(struct vkd3d_shader_cache *cache, struct d3d12_device *device); HRESULT vkd3d_render_pass_cache_find(struct vkd3d_shader_cache *cache, struct d3d12_device *device, const struct vkd3d_render_pass_key *key, VkRenderPass *vk_render_pass);
@@ -1814,6 +1818,7 @@ struct d3d12_device struct vkd3d_mutex pipeline_cache_mutex; struct vkd3d_shader_cache *persistent_cache; struct vkd3d_shader_cache *render_pass_cache; + struct vkd3d_shader_cache *root_signature_cache; VkPipelineCache vk_pipeline_cache;
VkPhysicalDeviceMemoryProperties memory_properties; diff --git a/tests/d3d12.c b/tests/d3d12.c index 427e59c22..bb2a04974 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -2674,9 +2674,9 @@ static void test_create_root_signature(void) * heap manager reuses the allocation. */ hr = create_root_signature(device, &root_signature_desc, &root_signature2); ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr); - todo ok(root_signature == root_signature2, "Got different root signature pointers.\n"); + ok(root_signature == root_signature2, "Got different root signature pointers.\n"); refcount = ID3D12RootSignature_Release(root_signature2); - todo ok(refcount == 1, "ID3D12RootSignature has %u references left.\n", (unsigned int)refcount); + ok(refcount == 1, "ID3D12RootSignature has %u references left.\n", (unsigned int)refcount);
hr = 0xdeadbeef; hr = ID3D12RootSignature_SetPrivateData(root_signature, &test_guid, sizeof(hr), &hr); @@ -2728,9 +2728,9 @@ static void test_create_root_signature(void)
hr = create_root_signature(device, &root_signature_desc, &root_signature2); ok(hr == S_OK, "Failed to create root signature, hr %#x.\n", hr); - todo ok(root_signature == root_signature2, "Got different root signature pointers.\n"); + ok(root_signature == root_signature2, "Got different root signature pointers.\n"); refcount = ID3D12RootSignature_Release(root_signature2); - todo ok(refcount == 1, "ID3D12RootSignature has %u references left.\n", (unsigned int)refcount); + ok(refcount == 1, "ID3D12RootSignature has %u references left.\n", (unsigned int)refcount);
refcount = ID3D12RootSignature_Release(root_signature); ok(!refcount, "ID3D12RootSignature has %u references left.\n", (unsigned int)refcount);