Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- v3: Add D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE to interface definition. --- include/vkd3d_d3d12.idl | 1 + libs/vkd3d/resource.c | 64 ++++++++++++++++++++++++++++++----------- 2 files changed, 49 insertions(+), 16 deletions(-)
diff --git a/include/vkd3d_d3d12.idl b/include/vkd3d_d3d12.idl index 8489f56..ec8b83d 100644 --- a/include/vkd3d_d3d12.idl +++ b/include/vkd3d_d3d12.idl @@ -309,6 +309,7 @@ typedef enum D3D12_HEAP_TYPE typedef enum D3D12_CPU_PAGE_PROPERTY { D3D12_CPU_PAGE_PROPERTY_UNKNOWN = 0, + D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE = 1, D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE = 2, D3D12_CPU_PAGE_PROPERTY_WRITE_BACK = 3, } D3D12_CPU_PAGE_PROPERTY; diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 626772e..b63a578 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -34,8 +34,17 @@ static inline bool is_cpu_accessible_heap(const D3D12_HEAP_PROPERTIES *propertie return true; }
-static unsigned int vkd3d_select_memory_type(struct d3d12_device *device, uint32_t memory_type_mask, - const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags) +static bool is_numa_device(struct d3d12_device *device) +{ + 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)) + return true; + return false; +} + +static HRESULT vkd3d_select_memory_type(struct d3d12_device *device, uint32_t memory_type_mask, + const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags, unsigned int *type_index) { const VkPhysicalDeviceMemoryProperties *memory_info = &device->memory_properties; VkMemoryPropertyFlags flags[3]; @@ -58,16 +67,36 @@ static unsigned int vkd3d_select_memory_type(struct d3d12_device *device, uint32 break;
case D3D12_HEAP_TYPE_CUSTOM: - FIXME("Custom heaps not supported yet.\n"); - flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT - | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - flags[count++] = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + 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)))) + { + WARN("Invalid memory pool preference.\n"); + return E_INVALIDARG; + } + + switch (heap_properties->CPUPageProperty) + { + case D3D12_CPU_PAGE_PROPERTY_WRITE_BACK: + flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + /* Fall through. */ + case D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE: + flags[count++] = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + /* Fall through. */ + case D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE: + flags[count++] = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + break; + case D3D12_CPU_PAGE_PROPERTY_UNKNOWN: + default: + WARN("Invalid CPU page property.\n"); + return E_INVALIDARG; + } break;
default: WARN("Invalid heap type %#x.\n", heap_properties->Type); - return ~0u; + return E_INVALIDARG; }
for (j = 0; j < count; ++j) @@ -79,11 +108,14 @@ static unsigned int vkd3d_select_memory_type(struct d3d12_device *device, uint32 if (!(memory_type_mask & (1u << i))) continue; if ((memory_info->memoryTypes[i].propertyFlags & preferred_flags) == preferred_flags) - return i; + { + *type_index = i; + return S_OK; + } } }
- return ~0u; + return E_FAIL; }
static HRESULT vkd3d_allocate_device_memory(struct d3d12_device *device, @@ -95,6 +127,7 @@ static HRESULT vkd3d_allocate_device_memory(struct d3d12_device *device, const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; VkMemoryAllocateInfo allocate_info; VkResult vr; + HRESULT hr;
TRACE("Memory requirements: size %#"PRIx64", alignment %#"PRIx64".\n", memory_requirements->size, memory_requirements->alignment); @@ -102,14 +135,13 @@ static HRESULT vkd3d_allocate_device_memory(struct d3d12_device *device, allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocate_info.pNext = dedicated_allocate_info; allocate_info.allocationSize = memory_requirements->size; - allocate_info.memoryTypeIndex = vkd3d_select_memory_type(device, - memory_requirements->memoryTypeBits, heap_properties, heap_flags); - - if (allocate_info.memoryTypeIndex == ~0u) + if (FAILED(hr = vkd3d_select_memory_type(device, memory_requirements->memoryTypeBits, + heap_properties, heap_flags, &allocate_info.memoryTypeIndex))) { - FIXME("Failed to find suitable memory type (allowed types %#x).\n", memory_requirements->memoryTypeBits); + if (hr != E_INVALIDARG) + FIXME("Failed to find suitable memory type (allowed types %#x).\n", memory_requirements->memoryTypeBits); *vk_memory = VK_NULL_HANDLE; - return E_FAIL; + return hr; }
TRACE("Allocating memory type %u.\n", allocate_info.memoryTypeIndex);
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- tests/d3d12.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 9fe47c6..2ec74a1 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -697,6 +697,22 @@ static bool is_standard_swizzle_64kb_supported(ID3D12Device *device) return options.StandardSwizzle64KBSupported; }
+static bool is_memory_pool_L1_supported(ID3D12Device *device) +{ + D3D12_FEATURE_DATA_ARCHITECTURE architecture; + HRESULT hr; + + memset(&architecture, 0, sizeof(architecture)); + if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_ARCHITECTURE, + &architecture, sizeof(architecture)))) + { + trace("Failed to check feature support, hr %#x.\n", hr); + return false; + } + + return !architecture.UMA; +} + #define create_cb_root_signature(a, b, c, e) create_cb_root_signature_(__LINE__, a, b, c, e) static ID3D12RootSignature *create_cb_root_signature_(unsigned int line, ID3D12Device *device, unsigned int reg_idx, D3D12_SHADER_VISIBILITY shader_visibility, @@ -1962,10 +1978,11 @@ 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; + HRESULT hr, expected_hr; unsigned int i, j; ID3D12Heap *heap; ULONG refcount; - HRESULT hr;
static const struct { @@ -1991,6 +2008,27 @@ 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 + { + D3D12_CPU_PAGE_PROPERTY page_property; + D3D12_MEMORY_POOL pool_preference; + HRESULT expected_hr; + } + custom_tests[] = + { + {D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, E_INVALIDARG}, + {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}, + {D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_L0, E_INVALIDARG}, + {D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE, D3D12_MEMORY_POOL_L0, S_OK}, + {D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE, D3D12_MEMORY_POOL_L0, S_OK}, + {D3D12_CPU_PAGE_PROPERTY_WRITE_BACK, D3D12_MEMORY_POOL_L0, S_OK}, + {D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_L1, E_INVALIDARG}, + {D3D12_CPU_PAGE_PROPERTY_NOT_AVAILABLE, D3D12_MEMORY_POOL_L1, S_OK}, + {D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE, D3D12_MEMORY_POOL_L1, E_INVALIDARG}, + {D3D12_CPU_PAGE_PROPERTY_WRITE_BACK, D3D12_MEMORY_POOL_L1, E_INVALIDARG}, + };
if (!(device = create_device())) { @@ -2083,6 +2121,31 @@ static void test_create_heap(void) refcount = ID3D12Heap_Release(heap); ok(!refcount, "ID3D12Heap has %u references left.\n", (unsigned int)refcount);
+ is_pool_L1_supported = is_memory_pool_L1_supported(device); + desc.Properties.Type = D3D12_HEAP_TYPE_CUSTOM; + desc.Properties.CreationNodeMask = 1; + desc.Properties.VisibleNodeMask = 1; + for (i = 0; i < ARRAY_SIZE(custom_tests); ++i) + { + vkd3d_test_set_context("Test %u", i); + + 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); + expected_hr = (custom_tests[i].pool_preference != D3D12_MEMORY_POOL_L1 || is_pool_L1_supported) ? custom_tests[i].expected_hr : E_INVALIDARG; + ok(hr == expected_hr, "Test %u, page_property %u, pool_preference %u: Got hr %#x, expected %#x.\n", + i, custom_tests[i].page_property, custom_tests[i].pool_preference, hr, expected_hr); + if (FAILED(hr)) + continue; + + result_desc = ID3D12Heap_GetDesc(heap); + check_heap_desc(&result_desc, &desc); + + refcount = ID3D12Heap_Release(heap); + ok(!refcount, "ID3D12Heap has %u references left.\n", (unsigned int)refcount); + } + vkd3d_test_set_context(NULL); + done: refcount = ID3D12Device_Release(device); ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com