From 091ac41f798eeac6e887d7357908d964465ae5e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B3zef=20Kucia?= <jkucia@codeweavers.com>
Date: Mon, 17 Jul 2017 16:25:29 +0200
Subject: [PATCH] libs/vkd3d: Partially handle descriptor table root
 parameters.

---
 libs/vkd3d/state.c | 102 +++++++++++++++++++++++++++++++++++++++++----
 tests/d3d12.c      |  37 ++++++++--------
 2 files changed, 112 insertions(+), 27 deletions(-)

diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c
index 3e546a10b2..89f9104074 100644
--- a/libs/vkd3d/state.c
+++ b/libs/vkd3d/state.c
@@ -168,6 +168,50 @@ static VkShaderStageFlags stage_flags_from_visibility(D3D12_SHADER_VISIBILITY vi
     }
 }
 
+static VkDescriptorType vk_descriptor_type_from_d3d12(D3D12_DESCRIPTOR_RANGE_TYPE type)
+{
+    switch (type)
+    {
+        case D3D12_DESCRIPTOR_RANGE_TYPE_SRV:
+            return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+        case D3D12_DESCRIPTOR_RANGE_TYPE_UAV:
+            return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+        case D3D12_DESCRIPTOR_RANGE_TYPE_CBV:
+            return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+        case D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER:
+            return VK_DESCRIPTOR_TYPE_SAMPLER;
+        default:
+            FIXME("Unhandled descriptor type %#x.\n", type);
+            return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+    }
+}
+
+static bool vk_binding_from_d3d12_descriptor_range(struct VkDescriptorSetLayoutBinding *binding_desc,
+        const D3D12_DESCRIPTOR_RANGE *descriptor_range)
+{
+    binding_desc->binding = descriptor_range->BaseShaderRegister;
+    binding_desc->descriptorType = vk_descriptor_type_from_d3d12(descriptor_range->RangeType);
+    binding_desc->descriptorCount = 1;
+
+    if (descriptor_range->NumDescriptors != 1)
+    {
+        FIXME("Unhandled descriptor count %u.\n", descriptor_range->NumDescriptors);
+        return false;
+    }
+    if (descriptor_range->RegisterSpace)
+    {
+        FIXME("Unhandled register space %u.\n", descriptor_range->RegisterSpace);
+        return false;
+    }
+    if (descriptor_range->OffsetInDescriptorsFromTableStart)
+    {
+        FIXME("Unhandled offset %u.\n", descriptor_range->OffsetInDescriptorsFromTableStart);
+        return false;
+    }
+
+    return true;
+}
+
 static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signature,
         struct d3d12_device *device, const D3D12_ROOT_SIGNATURE_DESC *desc)
 {
@@ -175,7 +219,7 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa
     struct VkPipelineLayoutCreateInfo pipeline_layout_info;
     struct VkDescriptorSetLayoutBinding *binding_desc;
     struct VkDescriptorSetLayoutCreateInfo set_desc;
-    size_t cbv_count = 0;
+    size_t cbv_count = 0, srv_count = 0;
     unsigned int i;
     VkResult vr;
 
@@ -196,6 +240,23 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa
 
         switch (p->ParameterType)
         {
+            case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE:
+                if (p->u.DescriptorTable.NumDescriptorRanges != 1)
+                {
+                    FIXME("Unhandled %u descriptor ranges.\n", p->u.DescriptorTable.NumDescriptorRanges);
+                    vkd3d_free(binding_desc);
+                    return E_NOTIMPL;
+                }
+                if (!vk_binding_from_d3d12_descriptor_range(&binding_desc[i],
+                        p->u.DescriptorTable.pDescriptorRanges))
+                {
+                    vkd3d_free(binding_desc);
+                    return E_NOTIMPL;
+                }
+                binding_desc[i].stageFlags = stage_flags_from_visibility(p->ShaderVisibility);
+                binding_desc[i].pImmutableSamplers = NULL;
+                break;
+
             case D3D12_ROOT_PARAMETER_TYPE_CBV:
                 /* FIXME: Register spaces should map to set layouts. */
                 if (p->u.Descriptor.RegisterSpace)
@@ -209,7 +270,6 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa
                 binding_desc[i].descriptorCount = 1;
                 binding_desc[i].stageFlags = stage_flags_from_visibility(p->ShaderVisibility);
                 binding_desc[i].pImmutableSamplers = NULL;
-                ++cbv_count;
                 break;
 
             default:
@@ -217,6 +277,20 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa
                 vkd3d_free(binding_desc);
                 return E_NOTIMPL;
         }
+
+        switch (binding_desc[i].descriptorType)
+        {
+            case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+                cbv_count += binding_desc[i].descriptorCount;
+                break;
+            case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+                srv_count += binding_desc[i].descriptorCount;
+                break;
+            default:
+                FIXME("Unhandled descriptor type %#x.\n", binding_desc[i].descriptorType);
+                vkd3d_free(binding_desc);
+                return E_NOTIMPL;
+        }
     }
 
     set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
@@ -233,17 +307,31 @@ static HRESULT d3d12_root_signature_init(struct d3d12_root_signature *root_signa
         return hresult_from_vk_result(vr);
     }
 
-    if (cbv_count)
+    if (cbv_count || srv_count)
     {
-        if (!(root_signature->pool_sizes = vkd3d_calloc(1, sizeof(*root_signature->pool_sizes))))
+        root_signature->pool_size_count = 0;
+        if (cbv_count)
+            ++root_signature->pool_size_count;
+        if (srv_count)
+            ++root_signature->pool_size_count;
+        if (!(root_signature->pool_sizes = vkd3d_calloc(root_signature->pool_size_count,
+                sizeof(*root_signature->pool_sizes))))
         {
             VK_CALL(vkDestroyDescriptorSetLayout(device->vk_device, root_signature->vk_set_layout, NULL));
             return E_OUTOFMEMORY;
         }
-        root_signature->pool_size_count = 1;
 
-        root_signature->pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
-        root_signature->pool_sizes[0].descriptorCount = cbv_count;
+        i = 0;
+        if (cbv_count)
+        {
+            root_signature->pool_sizes[i].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+            root_signature->pool_sizes[i++].descriptorCount = cbv_count;
+        }
+        if (srv_count)
+        {
+            root_signature->pool_sizes[i].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+            root_signature->pool_sizes[i++].descriptorCount = srv_count;
+        }
     }
     else
     {
diff --git a/tests/d3d12.c b/tests/d3d12.c
index ab81e77c91..3f8b08871b 100644
--- a/tests/d3d12.c
+++ b/tests/d3d12.c
@@ -1633,27 +1633,24 @@ static void test_create_root_signature(void)
     root_signature_desc.pStaticSamplers = NULL;
     root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
     hr = create_root_signature(device, &root_signature_desc, &root_signature);
-    todo(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr);
+    ok(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr);
 
-    if (SUCCEEDED(hr))
-    {
-        refcount = get_refcount(device);
-        ok(refcount == 2, "Got unexpected refcount %u.\n", (unsigned int)refcount);
-        hr = ID3D12RootSignature_GetDevice(root_signature, &IID_ID3D12Device, (void **)&tmp_device);
-        ok(SUCCEEDED(hr), "GetDevice failed, hr %#x.\n", hr);
-        refcount = get_refcount(device);
-        ok(refcount == 3, "Got unexpected refcount %u.\n", (unsigned int)refcount);
-        refcount = ID3D12Device_Release(tmp_device);
-        ok(refcount == 2, "Got unexpected refcount %u.\n", (unsigned int)refcount);
-
-        check_interface(root_signature, &IID_ID3D12Object, TRUE);
-        check_interface(root_signature, &IID_ID3D12DeviceChild, TRUE);
-        check_interface(root_signature, &IID_ID3D12Pageable, FALSE);
-        check_interface(root_signature, &IID_ID3D12RootSignature, TRUE);
-
-        refcount = ID3D12RootSignature_Release(root_signature);
-        ok(!refcount, "ID3D12RootSignature has %u references left.\n", (unsigned int)refcount);
-    }
+    refcount = get_refcount(device);
+    ok(refcount == 2, "Got unexpected refcount %u.\n", (unsigned int)refcount);
+    hr = ID3D12RootSignature_GetDevice(root_signature, &IID_ID3D12Device, (void **)&tmp_device);
+    ok(SUCCEEDED(hr), "GetDevice failed, hr %#x.\n", hr);
+    refcount = get_refcount(device);
+    ok(refcount == 3, "Got unexpected refcount %u.\n", (unsigned int)refcount);
+    refcount = ID3D12Device_Release(tmp_device);
+    ok(refcount == 2, "Got unexpected refcount %u.\n", (unsigned int)refcount);
+
+    check_interface(root_signature, &IID_ID3D12Object, TRUE);
+    check_interface(root_signature, &IID_ID3D12DeviceChild, TRUE);
+    check_interface(root_signature, &IID_ID3D12Pageable, FALSE);
+    check_interface(root_signature, &IID_ID3D12RootSignature, TRUE);
+
+    refcount = ID3D12RootSignature_Release(root_signature);
+    ok(!refcount, "ID3D12RootSignature has %u references left.\n", (unsigned int)refcount);
 
     root_signature_desc.NumParameters = 0;
     root_signature_desc.pParameters = NULL;
-- 
GitLab