[PATCH v3] vkd3d: Implement ID3D12Device::GetCustomHeapProperties

Derek Lesho dlesho at codeweavers.com
Wed Nov 6 11:50:12 CST 2019


Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
v3:
- Add tests
- Extend and use is_numa_device, per Henri's request.
---
 libs/vkd3d/device.c        | 29 +++++++++++++++++-
 libs/vkd3d/resource.c      |  9 ++++--
 libs/vkd3d/vkd3d_private.h |  2 ++
 tests/d3d12.c              | 62 ++++++++++++++++++++++++++++++++++++--
 4 files changed, 96 insertions(+), 6 deletions(-)

diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 4d6f7c9..6165d7e 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -2974,10 +2974,37 @@ invalid:
 static D3D12_HEAP_PROPERTIES * STDMETHODCALLTYPE d3d12_device_GetCustomHeapProperties(ID3D12Device *iface,
         D3D12_HEAP_PROPERTIES *heap_properties, UINT node_mask, D3D12_HEAP_TYPE heap_type)
 {
-    FIXME("iface %p, heap_properties %p, node_mask 0x%08x, heap_type %#x stub!\n",
+    struct d3d12_device *device = impl_from_ID3D12Device(iface);
+    bool uma = is_numa_device(device, false);
+    bool uma_cache_coherent = is_numa_device(device, true);
+
+    TRACE("iface %p, heap_properties %p, node_mask 0x%08x, heap_type %#x.\n",
             iface, heap_properties, node_mask, heap_type);
 
     debug_ignored_node_mask(node_mask);
+    heap_properties->CreationNodeMask = 1;
+    heap_properties->VisibleNodeMask = 1;
+    heap_properties->Type = heap_type;
+
+    switch (heap_type)
+    {
+        case D3D12_HEAP_TYPE_UPLOAD:
+            heap_properties->CPUPageProperty = uma_cache_coherent ?
+                D3D12_CPU_PAGE_PROPERTY_WRITE_BACK : D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE;
+            heap_properties->MemoryPoolPreference = D3D12_MEMORY_POOL_L0;
+            break;
+        case D3D12_HEAP_TYPE_DEFAULT:
+            heap_properties->CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE;
+            heap_properties->MemoryPoolPreference = uma ?
+                D3D12_MEMORY_POOL_L0 : D3D12_MEMORY_POOL_L1;
+            break;
+        case D3D12_HEAP_TYPE_READBACK:
+            heap_properties->CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_BACK;
+            heap_properties->MemoryPoolPreference = D3D12_MEMORY_POOL_L0;
+            break;
+        default:
+            FIXME("Unhandled heap type: %#x.\n", heap_type);    
+    };
 
     return heap_properties;
 }
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index d6e999e..32ad7d6 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -34,12 +34,15 @@ static inline bool is_cpu_accessible_heap(const D3D12_HEAP_PROPERTIES *propertie
     return true;
 }
 
-static bool is_numa_device(struct d3d12_device *device)
+bool is_numa_device(struct d3d12_device *device, bool coherent)
 {
     unsigned int i;
     for (i = 0; i < device->memory_properties.memoryTypeCount; ++i)
-        if (!(device->memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))
+        if (!(device->memory_properties.memoryTypes[i].propertyFlags &
+                (coherent ? VK_MEMORY_PROPERTY_HOST_COHERENT_BIT : VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)))
+        {
             return true;
+        }
     return false;
 }
 
@@ -69,7 +72,7 @@ static HRESULT vkd3d_select_memory_type(struct d3d12_device *device, uint32_t me
         case D3D12_HEAP_TYPE_CUSTOM:
             if (heap_properties->MemoryPoolPreference == D3D12_MEMORY_POOL_UNKNOWN
                     || (heap_properties->MemoryPoolPreference == D3D12_MEMORY_POOL_L1
-                    && (is_cpu_accessible_heap(heap_properties) || !is_numa_device(device))))
+                    && (is_cpu_accessible_heap(heap_properties) || !is_numa_device(device, false))))
             {
                 WARN("Invalid memory pool preference.\n");
                 return E_INVALIDARG;
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 1cb40f2..98bcfb6 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -434,6 +434,8 @@ static inline bool d3d12_resource_is_texture(const struct d3d12_resource *resour
     return resource->desc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER;
 }
 
+bool is_numa_device(struct d3d12_device *device, bool coherent) DECLSPEC_HIDDEN;
+
 bool d3d12_resource_is_cpu_accessible(const struct d3d12_resource *resource) DECLSPEC_HIDDEN;
 HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc) DECLSPEC_HIDDEN;
 
diff --git a/tests/d3d12.c b/tests/d3d12.c
index 2ec74a1..cb25eaf 100644
--- a/tests/d3d12.c
+++ b/tests/d3d12.c
@@ -1978,7 +1978,8 @@ static void test_create_heap(void)
     D3D12_FEATURE_DATA_D3D12_OPTIONS options;
     D3D12_HEAP_DESC desc, result_desc;
     ID3D12Device *device, *tmp_device;
-    bool is_pool_L1_supported;
+    D3D12_FEATURE_DATA_ARCHITECTURE architecture;
+    bool is_pool_L1_supported, uma, uma_cache_coherent;
     HRESULT hr, expected_hr;
     unsigned int i, j;
     ID3D12Heap *heap;
@@ -2008,7 +2009,7 @@ static void test_create_heap(void)
         {D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES, "textures"},
         {D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES, "rt_ds_textures"},
     };
-    static const struct
+    static struct
     {
         D3D12_CPU_PAGE_PROPERTY page_property;
         D3D12_MEMORY_POOL pool_preference;
@@ -2017,6 +2018,12 @@ static void test_create_heap(void)
     custom_tests[] =
     {
         {D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, E_INVALIDARG},
+        /* slot for custom D3D12_HEAP_TYPE_DEFAULT(1) */
+        {0, 0, 0},
+        /* slot for custom D3D12_HEAP_TYPE_UPLOAD(2) */
+        {0, 0, 0},
+        /* slot for custom D3D12_HEAP_TYPE_READBACK(3) */
+        {0, 0, 0},
         {D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE, D3D12_MEMORY_POOL_UNKNOWN, E_INVALIDARG},
         {D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE, D3D12_MEMORY_POOL_UNKNOWN, E_INVALIDARG},
         {D3D12_CPU_PAGE_PROPERTY_WRITE_BACK, D3D12_MEMORY_POOL_UNKNOWN, E_INVALIDARG},
@@ -2121,6 +2128,54 @@ static void test_create_heap(void)
     refcount = ID3D12Heap_Release(heap);
     ok(!refcount, "ID3D12Heap has %u references left.\n", (unsigned int)refcount);
 
+    hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_ARCHITECTURE,
+        &architecture, sizeof(architecture));
+    ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+    uma = architecture.UMA;
+    uma_cache_coherent = architecture.CacheCoherentUMA;
+    for (i = D3D12_HEAP_TYPE_DEFAULT; i < D3D12_HEAP_TYPE_CUSTOM; i++)
+    {
+        D3D12_HEAP_PROPERTIES props;
+
+        vkd3d_test_set_context("Test %u\n", i);
+        props = ID3D12Device_GetCustomHeapProperties(device, 1, i);
+        if(props.Type != i)
+        {
+            ok(false, "Got unexpected type %u.\n", props.Type);
+            continue;
+        }
+        
+        /* check values against MSDN: https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-getcustomheapproperties#return-value */
+        switch (i)
+        {
+            case D3D12_HEAP_TYPE_DEFAULT:
+                ok(props.CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE,
+                        "Unexpected CPUPageProperty %u, type=%u.\n", props.CPUPageProperty, i);
+                ok(props.MemoryPoolPreference == (uma ? D3D12_MEMORY_POOL_L0 : D3D12_MEMORY_POOL_L1),
+                        "Unexpected MemoryPoolPreference %u, type=%u.\n", props.MemoryPoolPreference, i);
+                break;
+            case D3D12_HEAP_TYPE_UPLOAD:
+                ok(props.CPUPageProperty == (uma_cache_coherent ? D3D12_CPU_PAGE_PROPERTY_WRITE_BACK : D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE),
+                        "Unexpected CPUPageProperty %u, type=%u.\n", props.CPUPageProperty, i);
+                ok(props.MemoryPoolPreference == D3D12_MEMORY_POOL_L0,
+                        "Unexpected MemoryPoolPreference %u, type=%u.\n", props.MemoryPoolPreference, i);
+                break;
+            case D3D12_HEAP_TYPE_READBACK:
+                ok(props.CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK,
+                        "Unexpected CPUPageProperty %u, type=%u.\n", props.CPUPageProperty, i);
+                ok(props.MemoryPoolPreference == D3D12_MEMORY_POOL_L0,
+                        "Unexpected MemoryPoolPreference %u, type=%u.\n", props.MemoryPoolPreference, i);
+                break;
+            default:
+              ok(false, "Unhandled page type, did the D3D12_HEAP_TYPE enum change?\n");
+              continue;
+        }
+        custom_tests[i].page_property = props.CPUPageProperty;
+        custom_tests[i].pool_preference = props.MemoryPoolPreference;
+        custom_tests[i].expected_hr = S_OK;
+    }
+    vkd3d_test_set_context(NULL);
+
     is_pool_L1_supported = is_memory_pool_L1_supported(device);
     desc.Properties.Type = D3D12_HEAP_TYPE_CUSTOM;
     desc.Properties.CreationNodeMask = 1;
@@ -2129,6 +2184,9 @@ static void test_create_heap(void)
     {
         vkd3d_test_set_context("Test %u", i);
 
+        if (custom_tests[i].page_property == 0)
+            continue;
+
         desc.Properties.CPUPageProperty = custom_tests[i].page_property;
         desc.Properties.MemoryPoolPreference = custom_tests[i].pool_preference;
         hr = ID3D12Device_CreateHeap(device, &desc, &IID_ID3D12Heap, (void **)&heap);
-- 
2.23.0




More information about the wine-devel mailing list