Signed-off-by: Derek Lesho dlesho@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-id3d12devi... */ + 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);