vkd3d-proton/tests/d3d12_device.c

1447 lines
64 KiB
C

/*
* Copyright 2016-2017 Józef Kucia for CodeWeavers
* Copyright 2020-2021 Philip Rebohle for Valve Corporation
* Copyright 2020-2021 Joshua Ashton for Valve Corporation
* Copyright 2020-2021 Hans-Kristian Arntzen for Valve Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API
#include "d3d12_crosstest.h"
void test_create_device(void)
{
ID3D12Device *device;
ULONG refcount;
HRESULT hr;
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
check_interface(device, &IID_ID3D12Object, true);
check_interface(device, &IID_ID3D12DeviceChild, false);
check_interface(device, &IID_ID3D12Pageable, false);
check_interface(device, &IID_ID3D12Device, true);
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, (void **)&device);
ok(hr == S_OK, "Failed to create device, hr %#x.\n", hr);
ID3D12Device_Release(device);
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, NULL);
ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, NULL, NULL);
ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12DeviceChild, NULL);
ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_9_1, &IID_ID3D12Device, (void **)&device);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_9_2, &IID_ID3D12Device, (void **)&device);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_9_3, &IID_ID3D12Device, (void **)&device);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_10_0, &IID_ID3D12Device, (void **)&device);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_10_1, &IID_ID3D12Device, (void **)&device);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = D3D12CreateDevice(NULL, 0, &IID_ID3D12Device, (void **)&device);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = D3D12CreateDevice(NULL, ~0u, &IID_ID3D12Device, (void **)&device);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
}
void test_node_count(void)
{
ID3D12Device *device;
UINT node_count;
ULONG refcount;
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
node_count = ID3D12Device_GetNodeCount(device);
trace("Node count: %u.\n", node_count);
ok(1 <= node_count && node_count <= 32, "Got unexpected node count %u.\n", node_count);
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}
void test_check_feature_support(void)
{
D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT gpu_virtual_address;
D3D12_FEATURE_DATA_FEATURE_LEVELS feature_levels;
D3D12_FEATURE_DATA_ROOT_SIGNATURE root_signature;
D3D_FEATURE_LEVEL max_supported_feature_level;
D3D12_FEATURE_DATA_ARCHITECTURE architecture;
D3D12_FEATURE_DATA_FORMAT_INFO format_info;
unsigned int expected_plane_count;
ID3D12Device *device;
DXGI_FORMAT format;
ULONG refcount;
bool is_todo;
HRESULT hr;
static const D3D_FEATURE_LEVEL all_feature_levels[] =
{
D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1,
};
static const D3D_FEATURE_LEVEL d3d12_feature_levels[] =
{
D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
};
static const D3D_FEATURE_LEVEL d3d_9_x_feature_levels[] =
{
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1,
};
static const D3D_FEATURE_LEVEL invalid_feature_levels[] =
{
0x0000,
0x3000,
};
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
/* Architecture. */
memset(&architecture, 0, sizeof(architecture));
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_ARCHITECTURE,
&architecture, sizeof(architecture));
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(!architecture.NodeIndex, "Got unexpected node %u.\n", architecture.NodeIndex);
ok(!architecture.CacheCoherentUMA || architecture.UMA,
"Got unexpected cache coherent UMA %#x (UMA %#x).\n",
architecture.CacheCoherentUMA, architecture.UMA);
trace("UMA %#x, cache coherent UMA %#x, tile based renderer %#x.\n",
architecture.UMA, architecture.CacheCoherentUMA, architecture.TileBasedRenderer);
if (ID3D12Device_GetNodeCount(device) == 1)
{
memset(&architecture, 0, sizeof(architecture));
architecture.NodeIndex = 1;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_ARCHITECTURE,
&architecture, sizeof(architecture));
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
}
/* Feature levels */
memset(&feature_levels, 0, sizeof(feature_levels));
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FEATURE_LEVELS,
&feature_levels, sizeof(feature_levels));
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
feature_levels.NumFeatureLevels = ARRAY_SIZE(all_feature_levels);
feature_levels.pFeatureLevelsRequested = all_feature_levels;
feature_levels.MaxSupportedFeatureLevel = 0;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FEATURE_LEVELS,
&feature_levels, sizeof(feature_levels));
ok(hr == S_OK, "Failed to check feature support, hr %#x.\n", hr);
trace("Max supported feature level %#x.\n", feature_levels.MaxSupportedFeatureLevel);
max_supported_feature_level = feature_levels.MaxSupportedFeatureLevel;
feature_levels.NumFeatureLevels = ARRAY_SIZE(d3d12_feature_levels);
feature_levels.pFeatureLevelsRequested = d3d12_feature_levels;
feature_levels.MaxSupportedFeatureLevel = 0;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FEATURE_LEVELS,
&feature_levels, sizeof(feature_levels));
ok(hr == S_OK, "Failed to check feature support, hr %#x.\n", hr);
ok(feature_levels.MaxSupportedFeatureLevel == max_supported_feature_level,
"Got unexpected feature level %#x, expected %#x.\n",
feature_levels.MaxSupportedFeatureLevel, max_supported_feature_level);
/* Check invalid size. */
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FEATURE_LEVELS,
&feature_levels, sizeof(feature_levels) + 1);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FEATURE_LEVELS,
&feature_levels, sizeof(feature_levels) - 1);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
feature_levels.NumFeatureLevels = ARRAY_SIZE(d3d_9_x_feature_levels);
feature_levels.pFeatureLevelsRequested = d3d_9_x_feature_levels;
feature_levels.MaxSupportedFeatureLevel = 0;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FEATURE_LEVELS,
&feature_levels, sizeof(feature_levels));
ok(hr == S_OK, "Failed to check feature support, hr %#x.\n", hr);
ok(feature_levels.MaxSupportedFeatureLevel == D3D_FEATURE_LEVEL_9_3,
"Got unexpected max feature level %#x.\n", feature_levels.MaxSupportedFeatureLevel);
feature_levels.NumFeatureLevels = ARRAY_SIZE(invalid_feature_levels);
feature_levels.pFeatureLevelsRequested = invalid_feature_levels;
feature_levels.MaxSupportedFeatureLevel = 0;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FEATURE_LEVELS,
&feature_levels, sizeof(feature_levels));
ok(hr == S_OK, "Failed to check feature support, hr %#x.\n", hr);
ok(feature_levels.MaxSupportedFeatureLevel == 0x3000,
"Got unexpected max feature level %#x.\n", feature_levels.MaxSupportedFeatureLevel);
/* Format info. */
memset(&format_info, 0, sizeof(format_info));
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FORMAT_INFO,
&format_info, sizeof(format_info));
ok(hr == S_OK, "Failed to get format info, hr %#x.\n", hr);
ok(format_info.Format == DXGI_FORMAT_UNKNOWN, "Got unexpected format %#x.\n", format_info.Format);
ok(format_info.PlaneCount == 1, "Got unexpected plane count %u.\n", format_info.PlaneCount);
for (format = DXGI_FORMAT_UNKNOWN; format <= DXGI_FORMAT_B4G4R4A4_UNORM; ++format)
{
vkd3d_test_set_context("format %#x", format);
switch (format)
{
case DXGI_FORMAT_R32G8X24_TYPELESS:
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
case DXGI_FORMAT_D24_UNORM_S8_UINT:
case DXGI_FORMAT_R24G8_TYPELESS:
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_P010:
case DXGI_FORMAT_P016:
case DXGI_FORMAT_NV11:
expected_plane_count = 2;
break;
default:
expected_plane_count = 1;
break;
}
is_todo = format == DXGI_FORMAT_R8G8_B8G8_UNORM
|| format == DXGI_FORMAT_G8R8_G8B8_UNORM
|| format == DXGI_FORMAT_B5G6R5_UNORM
|| format == DXGI_FORMAT_B5G5R5A1_UNORM
|| format == DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
|| (DXGI_FORMAT_AYUV <= format && format <= DXGI_FORMAT_B4G4R4A4_UNORM);
memset(&format_info, 0, sizeof(format_info));
format_info.Format = format;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FORMAT_INFO,
&format_info, sizeof(format_info));
if (format == DXGI_FORMAT_R1_UNORM)
{
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
continue;
}
todo_if(is_todo)
ok(hr == S_OK, "Failed to get format info, hr %#x.\n", hr);
ok(format_info.Format == format, "Got unexpected format %#x.\n", format_info.Format);
todo_if(is_todo)
ok(format_info.PlaneCount == expected_plane_count,
"Got plane count %u, expected %u.\n", format_info.PlaneCount, expected_plane_count);
}
vkd3d_test_set_context(NULL);
/* GPU virtual address */
memset(&gpu_virtual_address, 0, sizeof(gpu_virtual_address));
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_GPU_VIRTUAL_ADDRESS_SUPPORT,
&gpu_virtual_address, sizeof(gpu_virtual_address));
ok(hr == S_OK, "Failed to check GPU virtual address support, hr %#x.\n", hr);
trace("GPU virtual address bits per resource: %u.\n",
gpu_virtual_address.MaxGPUVirtualAddressBitsPerResource);
trace("GPU virtual address bits per process: %u.\n",
gpu_virtual_address.MaxGPUVirtualAddressBitsPerProcess);
root_signature.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_ROOT_SIGNATURE,
&root_signature, sizeof(root_signature));
ok(hr == S_OK, "Failed to get root signature feature support, hr %#x.\n", hr);
ok(root_signature.HighestVersion == D3D_ROOT_SIGNATURE_VERSION_1_0,
"Got unexpected root signature feature version %#x.\n", root_signature.HighestVersion);
root_signature.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_ROOT_SIGNATURE,
&root_signature, sizeof(root_signature));
ok(hr == S_OK, "Failed to get root signature feature support, hr %#x.\n", hr);
ok(root_signature.HighestVersion == D3D_ROOT_SIGNATURE_VERSION_1_0
|| root_signature.HighestVersion == D3D_ROOT_SIGNATURE_VERSION_1_1,
"Got unexpected root signature feature version %#x.\n", root_signature.HighestVersion);
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}
static const DXGI_FORMAT depth_stencil_formats[] =
{
DXGI_FORMAT_R32G8X24_TYPELESS,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT,
DXGI_FORMAT_R32_TYPELESS,
DXGI_FORMAT_D32_FLOAT,
DXGI_FORMAT_R24G8_TYPELESS,
DXGI_FORMAT_D24_UNORM_S8_UINT,
DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
DXGI_FORMAT_X24_TYPELESS_G8_UINT,
DXGI_FORMAT_R16_TYPELESS,
DXGI_FORMAT_D16_UNORM,
};
void test_format_support(void)
{
D3D12_FEATURE_DATA_FORMAT_SUPPORT format_support;
ID3D12Device *device;
ULONG refcount;
unsigned int i;
HRESULT hr;
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
memset(&format_support, 0, sizeof(format_support));
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FORMAT_SUPPORT,
&format_support, sizeof(format_support));
todo ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
todo ok(format_support.Support1 == D3D12_FORMAT_SUPPORT1_BUFFER,
"Got unexpected support1 %#x.\n", format_support.Support1);
ok(!format_support.Support2 || format_support.Support2 == D3D12_FORMAT_SUPPORT2_TILED,
"Got unexpected support2 %#x.\n", format_support.Support2);
for (i = 0; i < ARRAY_SIZE(depth_stencil_formats); ++i)
{
memset(&format_support, 0, sizeof(format_support));
format_support.Format = depth_stencil_formats[i];
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_FORMAT_SUPPORT,
&format_support, sizeof(format_support));
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
}
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}
void test_multisample_quality_levels(void)
{
static const unsigned int sample_counts[] = {1, 2, 4, 8, 16, 32};
D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS format_support;
ID3D12Device *device;
DXGI_FORMAT format;
unsigned int i, j;
ULONG refcount;
HRESULT hr;
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
memset(&format_support, 0, sizeof(format_support));
format_support.NumQualityLevels = 0xdeadbeef;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
&format_support, sizeof(format_support));
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
ok(!format_support.Flags, "Got unexpected flags %#x.\n", format_support.Flags);
ok(!format_support.NumQualityLevels, "Got unexpected quality levels %u.\n", format_support.NumQualityLevels);
format_support.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
format_support.NumQualityLevels = 0xdeadbeef;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
&format_support, sizeof(format_support));
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
ok(!format_support.Flags, "Got unexpected flags %#x.\n", format_support.Flags);
ok(!format_support.NumQualityLevels, "Got unexpected quality levels %u.\n", format_support.NumQualityLevels);
/* 1 sample */
for (format = DXGI_FORMAT_UNKNOWN; format <= DXGI_FORMAT_B4G4R4A4_UNORM; ++format)
{
if (format == DXGI_FORMAT_R1_UNORM)
continue;
vkd3d_test_set_context("format %#x", format);
memset(&format_support, 0, sizeof(format_support));
format_support.Format = format;
format_support.SampleCount = 1;
format_support.NumQualityLevels = 0xdeadbeef;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
&format_support, sizeof(format_support));
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(format_support.NumQualityLevels == 1, "Got unexpected quality levels %u.\n", format_support.NumQualityLevels);
}
vkd3d_test_set_context(NULL);
/* DXGI_FORMAT_UNKNOWN */
for (i = 1; i < ARRAY_SIZE(sample_counts); ++i)
{
vkd3d_test_set_context("samples %#x", sample_counts[i]);
memset(&format_support, 0, sizeof(format_support));
format_support.SampleCount = sample_counts[i];
format_support.NumQualityLevels = 0xdeadbeef;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
&format_support, sizeof(format_support));
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(!format_support.Flags, "Got unexpected flags %#x.\n", format_support.Flags);
ok(!format_support.NumQualityLevels, "Got unexpected quality levels %u.\n", format_support.NumQualityLevels);
format_support.Flags = D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_TILED_RESOURCE;
format_support.NumQualityLevels = 0xdeadbeef;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
&format_support, sizeof(format_support));
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(format_support.Flags == D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_TILED_RESOURCE,
"Got unexpected flags %#x.\n", format_support.Flags);
ok(!format_support.NumQualityLevels, "Got unexpected quality levels %u.\n", format_support.NumQualityLevels);
}
vkd3d_test_set_context(NULL);
/* invalid sample counts */
for (i = 1; i <= 32; ++i)
{
bool valid_sample_count = false;
for (j = 0; j < ARRAY_SIZE(sample_counts); ++j)
{
if (sample_counts[j] == i)
{
valid_sample_count = true;
break;
}
}
if (valid_sample_count)
continue;
vkd3d_test_set_context("samples %#x", i);
memset(&format_support, 0, sizeof(format_support));
format_support.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
format_support.SampleCount = i;
format_support.NumQualityLevels = 0xdeadbeef;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
&format_support, sizeof(format_support));
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(!format_support.Flags, "Got unexpected flags %#x.\n", format_support.Flags);
ok(!format_support.NumQualityLevels, "Got unexpected quality levels %u.\n", format_support.NumQualityLevels);
}
vkd3d_test_set_context(NULL);
/* DXGI_FORMAT_R8G8B8A8_UNORM */
memset(&format_support, 0, sizeof(format_support));
format_support.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
format_support.SampleCount = 4;
format_support.NumQualityLevels = 0xdeadbeef;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
&format_support, sizeof(format_support));
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(!format_support.Flags, "Got unexpected flags %#x.\n", format_support.Flags);
ok(format_support.NumQualityLevels >= 1, "Got unexpected quality levels %u.\n", format_support.NumQualityLevels);
for (i = 0; i < ARRAY_SIZE(depth_stencil_formats); ++i)
{
memset(&format_support, 0, sizeof(format_support));
format_support.Format = depth_stencil_formats[i];
format_support.SampleCount = 4;
format_support.NumQualityLevels = 0xdeadbeef;
hr = ID3D12Device_CheckFeatureSupport(device, D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
&format_support, sizeof(format_support));
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
}
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}
void test_create_command_allocator(void)
{
ID3D12CommandAllocator *command_allocator;
ID3D12Device *device, *tmp_device;
ULONG refcount;
HRESULT hr;
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT,
&IID_ID3D12CommandAllocator, (void **)&command_allocator);
ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr);
refcount = get_refcount(device);
ok(refcount == 2, "Got unexpected refcount %u.\n", (unsigned int)refcount);
hr = ID3D12CommandAllocator_GetDevice(command_allocator, &IID_ID3D12Device, (void **)&tmp_device);
ok(SUCCEEDED(hr), "Failed to get device, 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(command_allocator, &IID_ID3D12Object, true);
check_interface(command_allocator, &IID_ID3D12DeviceChild, true);
check_interface(command_allocator, &IID_ID3D12Pageable, true);
check_interface(command_allocator, &IID_ID3D12CommandAllocator, true);
refcount = ID3D12CommandAllocator_Release(command_allocator);
ok(!refcount, "ID3D12CommandAllocator has %u references left.\n", (unsigned int)refcount);
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_BUNDLE,
&IID_ID3D12CommandAllocator, (void **)&command_allocator);
ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr);
refcount = ID3D12CommandAllocator_Release(command_allocator);
ok(!refcount, "ID3D12CommandAllocator has %u references left.\n", (unsigned int)refcount);
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_COMPUTE,
&IID_ID3D12CommandAllocator, (void **)&command_allocator);
ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr);
refcount = ID3D12CommandAllocator_Release(command_allocator);
ok(!refcount, "ID3D12CommandAllocator has %u references left.\n", (unsigned int)refcount);
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_COPY,
&IID_ID3D12CommandAllocator, (void **)&command_allocator);
ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr);
refcount = ID3D12CommandAllocator_Release(command_allocator);
ok(!refcount, "ID3D12CommandAllocator has %u references left.\n", (unsigned int)refcount);
hr = ID3D12Device_CreateCommandAllocator(device, ~0u,
&IID_ID3D12CommandAllocator, (void **)&command_allocator);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}
void test_create_command_list(void)
{
ID3D12CommandAllocator *command_allocator;
ID3D12Device *device, *tmp_device;
ID3D12CommandList *command_list;
ULONG refcount;
HRESULT hr;
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
NULL, NULL, &IID_ID3D12CommandList, (void **)&command_list);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT,
&IID_ID3D12CommandAllocator, (void **)&command_allocator);
ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr);
refcount = get_refcount(device);
ok(refcount == 2, "Got unexpected refcount %u.\n", (unsigned int)refcount);
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
command_allocator, NULL, &IID_ID3D12CommandList, (void **)&command_list);
ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr);
refcount = get_refcount(command_allocator);
ok(refcount == 1, "Got unexpected refcount %u.\n", (unsigned int)refcount);
refcount = get_refcount(device);
ok(refcount == 3, "Got unexpected refcount %u.\n", (unsigned int)refcount);
hr = ID3D12CommandList_GetDevice(command_list, &IID_ID3D12Device, (void **)&tmp_device);
ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr);
refcount = get_refcount(device);
ok(refcount == 4, "Got unexpected refcount %u.\n", (unsigned int)refcount);
refcount = ID3D12Device_Release(tmp_device);
ok(refcount == 3, "Got unexpected refcount %u.\n", (unsigned int)refcount);
check_interface(command_list, &IID_ID3D12Object, true);
check_interface(command_list, &IID_ID3D12DeviceChild, true);
check_interface(command_list, &IID_ID3D12Pageable, false);
check_interface(command_list, &IID_ID3D12CommandList, true);
check_interface(command_list, &IID_ID3D12GraphicsCommandList, true);
check_interface(command_list, &IID_ID3D12CommandAllocator, false);
refcount = ID3D12CommandList_Release(command_list);
ok(!refcount, "ID3D12CommandList has %u references left.\n", (unsigned int)refcount);
refcount = ID3D12CommandAllocator_Release(command_allocator);
ok(!refcount, "ID3D12CommandAllocator has %u references left.\n", (unsigned int)refcount);
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_BUNDLE,
&IID_ID3D12CommandAllocator, (void **)&command_allocator);
ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
command_allocator, NULL, &IID_ID3D12CommandList, (void **)&command_list);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_BUNDLE,
command_allocator, NULL, &IID_ID3D12CommandList, (void **)&command_list);
ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr);
check_interface(command_list, &IID_ID3D12GraphicsCommandList, true);
refcount = ID3D12CommandList_Release(command_list);
ok(!refcount, "ID3D12CommandList has %u references left.\n", (unsigned int)refcount);
refcount = ID3D12CommandAllocator_Release(command_allocator);
ok(!refcount, "ID3D12CommandAllocator has %u references left.\n", (unsigned int)refcount);
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_COMPUTE,
&IID_ID3D12CommandAllocator, (void **)&command_allocator);
ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_BUNDLE,
command_allocator, NULL, &IID_ID3D12CommandList, (void **)&command_list);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_COMPUTE,
command_allocator, NULL, &IID_ID3D12CommandList, (void **)&command_list);
ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr);
check_interface(command_list, &IID_ID3D12GraphicsCommandList, true);
refcount = ID3D12CommandList_Release(command_list);
ok(!refcount, "ID3D12CommandList has %u references left.\n", (unsigned int)refcount);
refcount = ID3D12CommandAllocator_Release(command_allocator);
ok(!refcount, "ID3D12CommandAllocator has %u references left.\n", (unsigned int)refcount);
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_COPY,
&IID_ID3D12CommandAllocator, (void **)&command_allocator);
ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
command_allocator, NULL, &IID_ID3D12CommandList, (void **)&command_list);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_COMPUTE,
command_allocator, NULL, &IID_ID3D12CommandList, (void **)&command_list);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_COPY,
command_allocator, NULL, &IID_ID3D12CommandList, (void **)&command_list);
ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr);
check_interface(command_list, &IID_ID3D12GraphicsCommandList, true);
refcount = ID3D12CommandList_Release(command_list);
ok(!refcount, "ID3D12CommandList has %u references left.\n", (unsigned int)refcount);
refcount = ID3D12CommandAllocator_Release(command_allocator);
ok(!refcount, "ID3D12CommandAllocator has %u references left.\n", (unsigned int)refcount);
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}
void test_create_command_queue(void)
{
ID3D12CommandQueue* direct_queues[8], *compute_queues[8];
D3D12_COMMAND_QUEUE_DESC desc, result_desc;
ID3D12Device *device, *tmp_device;
ID3D12CommandQueue *queue;
unsigned int i;
ULONG refcount;
HRESULT hr;
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
desc.NodeMask = 0;
hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&queue);
ok(SUCCEEDED(hr), "Failed to create command queue, hr %#x.\n", hr);
refcount = get_refcount(device);
ok(refcount == 2, "Got unexpected refcount %u.\n", (unsigned int)refcount);
hr = ID3D12CommandQueue_GetDevice(queue, &IID_ID3D12Device, (void **)&tmp_device);
ok(SUCCEEDED(hr), "Failed to get device, 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(queue, &IID_ID3D12Object, true);
check_interface(queue, &IID_ID3D12DeviceChild, true);
check_interface(queue, &IID_ID3D12Pageable, true);
check_interface(queue, &IID_ID3D12CommandQueue, true);
result_desc = ID3D12CommandQueue_GetDesc(queue);
ok(result_desc.Type == desc.Type, "Got unexpected type %#x.\n", result_desc.Type);
ok(result_desc.Priority == desc.Priority, "Got unexpected priority %#x.\n", result_desc.Priority);
ok(result_desc.Flags == desc.Flags, "Got unexpected flags %#x.\n", result_desc.Flags);
ok(result_desc.NodeMask == 0x1, "Got unexpected node mask 0x%08x.\n", result_desc.NodeMask);
refcount = ID3D12CommandQueue_Release(queue);
ok(!refcount, "ID3D12CommandQueue has %u references left.\n", (unsigned int)refcount);
desc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE;
hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&queue);
ok(SUCCEEDED(hr), "Failed to create command queue, hr %#x.\n", hr);
result_desc = ID3D12CommandQueue_GetDesc(queue);
ok(result_desc.Type == desc.Type, "Got unexpected type %#x.\n", result_desc.Type);
ok(result_desc.Priority == desc.Priority, "Got unexpected priority %#x.\n", result_desc.Priority);
ok(result_desc.Flags == desc.Flags, "Got unexpected flags %#x.\n", result_desc.Flags);
ok(result_desc.NodeMask == 0x1, "Got unexpected node mask 0x%08x.\n", result_desc.NodeMask);
refcount = ID3D12CommandQueue_Release(queue);
ok(!refcount, "ID3D12CommandQueue has %u references left.\n", (unsigned int)refcount);
desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
for (i = 0; i < ARRAY_SIZE(direct_queues); ++i)
{
hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&direct_queues[i]);
ok(hr == S_OK, "Failed to create direct command queue %u, hr %#x.\n", hr, i);
}
desc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE;
for (i = 0; i < ARRAY_SIZE(compute_queues); ++i)
{
hr = ID3D12Device_CreateCommandQueue(device, &desc, &IID_ID3D12CommandQueue, (void **)&compute_queues[i]);
ok(hr == S_OK, "Failed to create compute command queue %u, hr %#x.\n", hr, i);
}
for (i = 0; i < ARRAY_SIZE(direct_queues); ++i)
ID3D12CommandQueue_Release(direct_queues[i]);
for (i = 0; i < ARRAY_SIZE(compute_queues); ++i)
ID3D12CommandQueue_Release(compute_queues[i]);
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}
void test_create_command_signature(void)
{
D3D12_INDIRECT_ARGUMENT_DESC argument_desc[3];
D3D12_COMMAND_SIGNATURE_DESC signature_desc;
ID3D12CommandSignature *command_signature;
ID3D12Device *device;
unsigned int i;
ULONG refcount;
HRESULT hr;
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
signature_desc.ByteStride = 1024;
signature_desc.NumArgumentDescs = ARRAY_SIZE(argument_desc);
signature_desc.pArgumentDescs = argument_desc;
signature_desc.NodeMask = 0;
for (i = 0; i < ARRAY_SIZE(argument_desc); ++i)
argument_desc[i].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;
hr = ID3D12Device_CreateCommandSignature(device, &signature_desc,
NULL, &IID_ID3D12CommandSignature, (void **)&command_signature);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
for (i = 0; i < ARRAY_SIZE(argument_desc); ++i)
argument_desc[i].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;
hr = ID3D12Device_CreateCommandSignature(device, &signature_desc,
NULL, &IID_ID3D12CommandSignature, (void **)&command_signature);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
for (i = 0; i < ARRAY_SIZE(argument_desc); ++i)
argument_desc[i].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH;
hr = ID3D12Device_CreateCommandSignature(device, &signature_desc,
NULL, &IID_ID3D12CommandSignature, (void **)&command_signature);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
argument_desc[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH;
argument_desc[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;
signature_desc.NumArgumentDescs = 2;
hr = ID3D12Device_CreateCommandSignature(device, &signature_desc,
NULL, &IID_ID3D12CommandSignature, (void **)&command_signature);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}
struct private_data
{
ID3D12Object *object;
GUID guid;
unsigned int value;
};
static void private_data_thread_main(void *untyped_data)
{
struct private_data *data = untyped_data;
unsigned int i;
HRESULT hr;
hr = ID3D12Object_SetPrivateData(data->object, &data->guid, sizeof(data->value), &data->value);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
for (i = 0; i < 100000; ++i)
{
hr = ID3D12Object_SetPrivateData(data->object, &data->guid, 0, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateData(data->object, &data->guid, sizeof(data->value), &data->value);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
}
}
struct private_data_interface
{
ID3D12Object *object;
GUID guid;
IUnknown *iface;
};
static void private_data_interface_thread_main(void *untyped_data)
{
struct private_data_interface *data = untyped_data;
unsigned int i;
HRESULT hr;
for (i = 0; i < 100000; ++i)
{
hr = ID3D12Object_SetPrivateDataInterface(data->object, &data->guid, data->iface);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateDataInterface(data->object, &data->guid, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateDataInterface(data->object, &data->guid, data->iface);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
}
}
void test_multithread_private_data(void)
{
static const GUID guid = {0xfdb37466, 0x428f, 0x4edf, {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0x00}};
struct private_data_interface private_data_interface[4];
HANDLE private_data_interface_thread[4];
struct private_data private_data[4];
ID3D12RootSignature *root_signature;
HANDLE private_data_thread[4];
IUnknown *test_object, *unk;
ID3D12Device *device;
ID3D12Object *object;
unsigned int value;
unsigned int size;
unsigned int id;
unsigned int i;
ULONG refcount;
HRESULT hr;
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
root_signature = create_empty_root_signature(device,
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
hr = ID3D12RootSignature_QueryInterface(root_signature, &IID_ID3D12Object, (void **)&object);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ID3D12RootSignature_Release(root_signature);
hr = ID3D12Device_CreateFence(device, 0, D3D12_FENCE_FLAG_NONE,
&IID_ID3D12Fence, (void **)&test_object);
ok(hr == S_OK, "Failed to create fence, hr %#x.\n", hr);
for (i = 0, id = 1; i < ARRAY_SIZE(private_data_interface); ++i, ++id)
{
private_data_interface[i].object = object;
private_data_interface[i].guid = guid;
private_data_interface[i].guid.Data4[7] = id;
hr = ID3D12Device_CreateFence(device, 0, D3D12_FENCE_FLAG_NONE,
&IID_ID3D12Fence, (void **)&private_data_interface[i].iface);
ok(hr == S_OK, "Failed to create fence %u, hr %#x.\n", i, hr);
}
for (i = 0; i < ARRAY_SIZE(private_data); ++i, ++id)
{
private_data[i].object = object;
private_data[i].guid = guid;
private_data[i].guid.Data4[7] = id;
private_data[i].value = id;
}
for (i = 0; i < 4; ++i)
{
private_data_interface_thread[i] = create_thread(private_data_interface_thread_main, &private_data_interface[i]);
private_data_thread[i] = create_thread(private_data_thread_main, &private_data[i]);
}
for (i = 0; i < 100000; ++i)
{
hr = ID3D12Object_SetPrivateDataInterface(object, &guid, test_object);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateDataInterface(object, &guid, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateDataInterface(object, &guid, test_object);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
}
for (i = 0; i < 4; ++i)
{
ok(join_thread(private_data_interface_thread[i]), "Failed to join thread %u.\n", i);
ok(join_thread(private_data_thread[i]), "Failed to join thread %u.\n", i);
}
for (i = 0; i < ARRAY_SIZE(private_data_interface); ++i)
{
size = sizeof(unk);
hr = ID3D12Object_GetPrivateData(object, &private_data_interface[i].guid, &size, &unk);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(unk == private_data_interface[i].iface, "Got %p, expected %p.\n", unk, private_data_interface[i].iface);
IUnknown_Release(unk);
refcount = IUnknown_Release(private_data_interface[i].iface);
ok(refcount == 1, "Got unexpected refcount %u.\n", (unsigned int)refcount);
}
for (i = 0; i < ARRAY_SIZE(private_data); ++i)
{
size = sizeof(value);
hr = ID3D12Object_GetPrivateData(object, &private_data[i].guid, &size, &value);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(value == private_data[i].value, "Got %u, expected %u.\n", value, private_data[i].value);
}
hr = ID3D12Object_SetPrivateDataInterface(object, &guid, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
refcount = IUnknown_Release(test_object);
ok(!refcount, "Test object has %u references left.\n", (unsigned int)refcount);
refcount = ID3D12Object_Release(object);
ok(!refcount, "Object has %u references left.\n", (unsigned int)refcount);
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}
void test_reset_command_allocator(void)
{
ID3D12CommandAllocator *command_allocator, *command_allocator2;
ID3D12GraphicsCommandList *command_list, *command_list2;
D3D12_COMMAND_QUEUE_DESC command_queue_desc;
ID3D12CommandQueue *queue;
ID3D12Device *device;
unsigned int i;
ULONG refcount;
HRESULT hr;
static const D3D12_COMMAND_LIST_TYPE tests[] =
{
D3D12_COMMAND_LIST_TYPE_DIRECT,
D3D12_COMMAND_LIST_TYPE_BUNDLE,
};
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
for (i = 0; i < ARRAY_SIZE(tests); i++)
{
const D3D12_COMMAND_LIST_TYPE type = tests[i];
hr = ID3D12Device_CreateCommandAllocator(device, type,
&IID_ID3D12CommandAllocator, (void **)&command_allocator);
ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr);
hr = ID3D12CommandAllocator_Reset(command_allocator);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12CommandAllocator_Reset(command_allocator);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, type,
command_allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&command_list);
ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr);
hr = ID3D12CommandAllocator_Reset(command_allocator);
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
hr = ID3D12CommandAllocator_Reset(command_allocator);
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
hr = ID3D12GraphicsCommandList_Close(command_list);
ok(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
hr = ID3D12CommandAllocator_Reset(command_allocator);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12CommandAllocator_Reset(command_allocator);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12GraphicsCommandList_Reset(command_list, command_allocator, NULL);
ok(SUCCEEDED(hr), "Failed to reset command list, hr %#x.\n", hr);
hr = ID3D12CommandAllocator_Reset(command_allocator);
ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
hr = ID3D12GraphicsCommandList_Close(command_list);
ok(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
hr = ID3D12GraphicsCommandList_Reset(command_list, command_allocator, NULL);
ok(SUCCEEDED(hr), "Failed to reset command list, hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandAllocator(device, type,
&IID_ID3D12CommandAllocator, (void **)&command_allocator2);
ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr);
if (type != D3D12_COMMAND_LIST_TYPE_BUNDLE)
{
command_queue_desc.Type = type;
command_queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
command_queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
command_queue_desc.NodeMask = 0;
hr = ID3D12Device_CreateCommandQueue(device, &command_queue_desc,
&IID_ID3D12CommandQueue, (void **)&queue);
ok(SUCCEEDED(hr), "Failed to create command queue, hr %#x.\n", hr);
uav_barrier(command_list, NULL);
hr = ID3D12GraphicsCommandList_Close(command_list);
ok(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
exec_command_list(queue, command_list);
/* A command list can be reset when it is in use. */
hr = ID3D12GraphicsCommandList_Reset(command_list, command_allocator2, NULL);
ok(SUCCEEDED(hr), "Failed to reset command list, hr %#x.\n", hr);
hr = ID3D12GraphicsCommandList_Close(command_list);
ok(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
wait_queue_idle(device, queue);
hr = ID3D12CommandAllocator_Reset(command_allocator);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12GraphicsCommandList_Reset(command_list, command_allocator, NULL);
ok(SUCCEEDED(hr), "Failed to reset command list, hr %#x.\n", hr);
uav_barrier(command_list, NULL);
hr = ID3D12GraphicsCommandList_Close(command_list);
ok(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
exec_command_list(queue, command_list);
hr = ID3D12GraphicsCommandList_Reset(command_list, command_allocator, NULL);
ok(SUCCEEDED(hr), "Failed to reset command list, hr %#x.\n", hr);
hr = ID3D12GraphicsCommandList_Close(command_list);
ok(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
wait_queue_idle(device, queue);
hr = ID3D12CommandAllocator_Reset(command_allocator);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12GraphicsCommandList_Reset(command_list, command_allocator, NULL);
ok(SUCCEEDED(hr), "Failed to reset command list, hr %#x.\n", hr);
ID3D12CommandQueue_Release(queue);
}
/* A command allocator can be used with one command list at a time. */
hr = ID3D12Device_CreateCommandList(device, 0, type,
command_allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&command_list2);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, type,
command_allocator2, NULL, &IID_ID3D12GraphicsCommandList, (void **)&command_list2);
ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
hr = ID3D12GraphicsCommandList_Close(command_list2);
ok(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
hr = ID3D12GraphicsCommandList_Reset(command_list2, command_allocator, NULL);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
ID3D12GraphicsCommandList_Release(command_list2);
/* A command allocator can be re-used after closing the command list. */
hr = ID3D12Device_CreateCommandList(device, 0, type,
command_allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&command_list2);
ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
hr = ID3D12GraphicsCommandList_Close(command_list);
ok(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, type,
command_allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&command_list2);
ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
ID3D12GraphicsCommandList_Release(command_list);
ID3D12GraphicsCommandList_Release(command_list2);
ID3D12CommandAllocator_Release(command_allocator);
ID3D12CommandAllocator_Release(command_allocator2);
}
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}
void test_object_interface(void)
{
D3D12_DESCRIPTOR_HEAP_DESC descriptor_heap_desc;
D3D12_QUERY_HEAP_DESC query_heap_desc;
ID3D12RootSignature *root_signature;
ULONG refcount, expected_refcount;
ID3D12CommandAllocator *allocator;
D3D12_HEAP_DESC heap_desc;
IUnknown *test_object;
ID3D12Device *device;
ID3D12Object *object;
IUnknown *unknown;
unsigned int size;
unsigned int i;
IUnknown *ptr;
HRESULT hr;
static const GUID test_guid
= {0xfdb37466, 0x428f, 0x4edf, {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0xfc}};
static const GUID test_guid2
= {0x2e5afac2, 0x87b5, 0x4c10, {0x9b, 0x4b, 0x89, 0xd7, 0xd1, 0x12, 0xe7, 0x2b}};
static const DWORD data[] = {1, 2, 3, 4};
static const char terminated_name_a[] = { 'T', 'e', 's', 't', 'A', '\0' };
static const char non_terminated_name_a[] = { 'T', 'e', 's', 't' };
static const WCHAR non_terminated_name_w[] = { L'T', L'e', L's', L't', L'w' };
WCHAR temp_name_buffer[1024];
static const GUID *tests[] =
{
&IID_ID3D12CommandAllocator,
&IID_ID3D12CommandList,
&IID_ID3D12CommandQueue,
&IID_ID3D12CommandSignature,
&IID_ID3D12DescriptorHeap,
&IID_ID3D12Device,
&IID_ID3D12Fence,
&IID_ID3D12Heap,
&IID_ID3D12PipelineState,
&IID_ID3D12QueryHeap,
&IID_ID3D12Resource,
&IID_ID3D12RootSignature,
};
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
for (i = 0; i < ARRAY_SIZE(tests); ++i)
{
if (IsEqualGUID(tests[i], &IID_ID3D12CommandAllocator))
{
vkd3d_test_set_context("command allocator");
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT,
&IID_IUnknown, (void **)&unknown);
ok(hr == S_OK, "Failed to create command allocator, hr %#x.\n", hr);
}
else if (IsEqualGUID(tests[i], &IID_ID3D12CommandList))
{
vkd3d_test_set_context("command list");
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT,
&IID_ID3D12CommandAllocator, (void **)&allocator);
ok(hr == S_OK, "Failed to create command allocator, hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
allocator, NULL, &IID_IUnknown, (void **)&unknown);
ok(hr == S_OK, "Failed to create command list, hr %#x.\n", hr);
ID3D12CommandAllocator_Release(allocator);
}
else if (IsEqualGUID(tests[i], &IID_ID3D12CommandQueue))
{
vkd3d_test_set_context("command queue");
unknown = (IUnknown *)create_command_queue(device,
D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL);
}
else if (IsEqualGUID(tests[i], &IID_ID3D12CommandSignature))
{
vkd3d_test_set_context("command signature");
unknown = (IUnknown *)create_command_signature(device, D3D12_INDIRECT_ARGUMENT_TYPE_DRAW);
}
else if (IsEqualGUID(tests[i], &IID_ID3D12DescriptorHeap))
{
vkd3d_test_set_context("descriptor heap");
descriptor_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
descriptor_heap_desc.NumDescriptors = 16;
descriptor_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
descriptor_heap_desc.NodeMask = 0;
hr = ID3D12Device_CreateDescriptorHeap(device, &descriptor_heap_desc,
&IID_ID3D12DescriptorHeap, (void **)&unknown);
ok(hr == S_OK, "Failed to create descriptor heap, hr %#x.\n", hr);
}
else if (IsEqualGUID(tests[i], &IID_ID3D12Device))
{
vkd3d_test_set_context("device");
unknown = (IUnknown *)create_device();
}
else if (IsEqualGUID(tests[i], &IID_ID3D12Fence))
{
vkd3d_test_set_context("fence");
hr = ID3D12Device_CreateFence(device, 0, D3D12_FENCE_FLAG_NONE,
&IID_IUnknown, (void **)&unknown);
ok(hr == S_OK, "Failed to create fence, hr %#x.\n", hr);
}
else if (IsEqualGUID(tests[i], &IID_ID3D12Heap))
{
vkd3d_test_set_context("heap");
heap_desc.SizeInBytes = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
memset(&heap_desc.Properties, 0, sizeof(heap_desc.Properties));
heap_desc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT;
heap_desc.Alignment = 0;
heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES;
hr = ID3D12Device_CreateHeap(device, &heap_desc, &IID_ID3D12Heap, (void **)&unknown);
ok(hr == S_OK, "Failed to create heap, hr %#x.\n", hr);
}
else if (IsEqualGUID(tests[i], &IID_ID3D12PipelineState))
{
vkd3d_test_set_context("pipeline state");
root_signature = create_empty_root_signature(device, 0);
unknown = (IUnknown *)create_pipeline_state(device,
root_signature, DXGI_FORMAT_R8G8B8A8_UNORM, NULL, NULL, NULL);
ID3D12RootSignature_Release(root_signature);
}
else if (IsEqualGUID(tests[i], &IID_ID3D12QueryHeap))
{
vkd3d_test_set_context("query heap");
query_heap_desc.Type = D3D12_QUERY_HEAP_TYPE_OCCLUSION;
query_heap_desc.Count = 8;
query_heap_desc.NodeMask = 0;
hr = ID3D12Device_CreateQueryHeap(device, &query_heap_desc,
&IID_ID3D12QueryHeap, (void **)&unknown);
ok(hr == S_OK, "Failed to create query heap, hr %#x.\n", hr);
}
else if (IsEqualGUID(tests[i], &IID_ID3D12Resource))
{
vkd3d_test_set_context("resource");
unknown = (IUnknown *)create_readback_buffer(device, 512);
}
else if (IsEqualGUID(tests[i], &IID_ID3D12RootSignature))
{
vkd3d_test_set_context("root signature");
unknown = (IUnknown *)create_empty_root_signature(device, 0);
}
else
{
unknown = NULL;
}
ok(unknown, "Unhandled object type %u.\n", i);
object = NULL;
hr = IUnknown_QueryInterface(unknown, &IID_ID3D12Object, (void **)&object);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
IUnknown_Release(unknown);
hr = ID3D12Object_SetPrivateData(object, &test_guid, 0, NULL);
ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateDataInterface(object, &test_guid, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateData(object, &test_guid, ~0u, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateData(object, &test_guid, ~0u, NULL);
ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateDataInterface(object, &test_guid, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
size = sizeof(ptr) * 2;
ptr = (IUnknown *)(uintptr_t)0xdeadbeef;
hr = ID3D12Object_GetPrivateData(object, &test_guid, &size, &ptr);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(!ptr, "Got unexpected pointer %p.\n", ptr);
ok(size == sizeof(IUnknown *), "Got unexpected size %u.\n", size);
hr = ID3D12Device_CreateFence(device, 0, D3D12_FENCE_FLAG_NONE,
&IID_ID3D12Fence, (void **)&test_object);
ok(hr == S_OK, "Failed to create fence, hr %#x.\n", hr);
refcount = get_refcount(test_object);
hr = ID3D12Object_SetPrivateDataInterface(object, &test_guid, (IUnknown *)test_object);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
expected_refcount = refcount + 1;
refcount = get_refcount(test_object);
ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n",
(unsigned int)refcount, (unsigned int)expected_refcount);
hr = ID3D12Object_SetPrivateDataInterface(object, &test_guid, (IUnknown *)test_object);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
refcount = get_refcount(test_object);
ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n",
(unsigned int)refcount, (unsigned int)expected_refcount);
hr = ID3D12Object_SetPrivateDataInterface(object, &test_guid, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
--expected_refcount;
refcount = get_refcount(test_object);
ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n",
(unsigned int)refcount, (unsigned int)expected_refcount);
hr = ID3D12Object_SetPrivateDataInterface(object, &test_guid, (IUnknown *)test_object);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
size = sizeof(data);
hr = ID3D12Object_SetPrivateData(object, &test_guid, size, data);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
refcount = get_refcount(test_object);
ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n",
(unsigned int)refcount, (unsigned int)expected_refcount);
hr = ID3D12Object_SetPrivateData(object, &test_guid, 42, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateData(object, &test_guid, 42, NULL);
ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateDataInterface(object, &test_guid, (IUnknown *)test_object);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
++expected_refcount;
size = 2 * sizeof(ptr);
ptr = NULL;
hr = ID3D12Object_GetPrivateData(object, &test_guid, &size, &ptr);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(size == sizeof(test_object), "Got unexpected size %u.\n", size);
++expected_refcount;
refcount = get_refcount(test_object);
ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n",
(unsigned int)refcount, (unsigned int)expected_refcount);
IUnknown_Release(ptr);
--expected_refcount;
ptr = (IUnknown *)(uintptr_t)0xdeadbeef;
size = 1;
hr = ID3D12Object_GetPrivateData(object, &test_guid, &size, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(size == sizeof(ptr), "Got unexpected size %u.\n", size);
size = 2 * sizeof(ptr);
hr = ID3D12Object_GetPrivateData(object, &test_guid, &size, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(size == sizeof(ptr), "Got unexpected size %u.\n", size);
refcount = get_refcount(test_object);
ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n",
(unsigned int)refcount, (unsigned int)expected_refcount);
size = 1;
hr = ID3D12Object_GetPrivateData(object, &test_guid, &size, &ptr);
ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
ok(size == sizeof(object), "Got unexpected size %u.\n", size);
ok(ptr == (IUnknown *)(uintptr_t)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
size = 1;
hr = ID3D12Object_GetPrivateData(object, &test_guid2, &size, &ptr);
ok(hr == DXGI_ERROR_NOT_FOUND, "Got unexpected hr %#x.\n", hr);
ok(!size, "Got unexpected size %u.\n", size);
ok(ptr == (IUnknown *)(uintptr_t)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
if (IsEqualGUID(tests[i], &IID_ID3D12Device))
{
hr = ID3D12Object_SetPrivateDataInterface(object, &test_guid, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
}
hr = ID3D12Object_SetName(object, u"");
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetName(object, u"deadbeef");
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
size = 1;
hr = ID3D12Object_GetPrivateData(object, &WKPDID_D3DDebugObjectNameW, &size, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(size == 18, "Got unexpected size %u.\n", size);
hr = ID3D12Object_GetPrivateData(object, &WKPDID_D3DDebugObjectNameW, &size, temp_name_buffer);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(size == 18, "Got unexpected size %u.\n", size);
ok(temp_name_buffer[1] == L'e', "Got unexpected name");
size = 1;
hr = ID3D12Object_GetPrivateData(object, &WKPDID_D3DDebugObjectName, &size, NULL);
ok(hr == DXGI_ERROR_NOT_FOUND, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetName(object, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_GetPrivateData(object, &WKPDID_D3DDebugObjectNameW, &size, NULL);
ok(hr == DXGI_ERROR_NOT_FOUND, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateData(object, &WKPDID_D3DDebugObjectName, sizeof(terminated_name_a), terminated_name_a);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateData(object, &WKPDID_D3DDebugObjectName, sizeof(non_terminated_name_a), non_terminated_name_a);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateData(object, &WKPDID_D3DDebugObjectNameW, sizeof(non_terminated_name_w), non_terminated_name_w);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateData(object, &WKPDID_D3DDebugObjectNameW, 0, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Object_SetPrivateData(object, &WKPDID_D3DDebugObjectName, 0, NULL);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ID3D12Object_Release(object);
refcount = IUnknown_Release(test_object);
ok(!refcount, "Test object has %u references left.\n", (unsigned int)refcount);
vkd3d_test_set_context(NULL);
}
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}
void test_device_removed_reason(void)
{
D3D12_COMMAND_QUEUE_DESC command_queue_desc;
ID3D12CommandAllocator *command_allocator;
ID3D12GraphicsCommandList *command_list;
ID3D12CommandQueue *queue, *tmp_queue;
ID3D12Device *device;
ULONG refcount;
HRESULT hr;
if (!(device = create_device()))
{
skip("Failed to create device.\n");
return;
}
hr = ID3D12Device_GetDeviceRemovedReason(device);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
command_queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
command_queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
command_queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
command_queue_desc.NodeMask = 0;
hr = ID3D12Device_CreateCommandQueue(device, &command_queue_desc,
&IID_ID3D12CommandQueue, (void **)&queue);
ok(SUCCEEDED(hr), "Failed to create command queue, hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT,
&IID_ID3D12CommandAllocator, (void **)&command_allocator);
ok(SUCCEEDED(hr), "Failed to create command allocator, hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT,
command_allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&command_list);
ok(SUCCEEDED(hr), "Failed to create command list, hr %#x.\n", hr);
/* Execute a command list in the recording state. */
exec_command_list(queue, command_list);
hr = ID3D12Device_GetDeviceRemovedReason(device);
ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
hr = ID3D12Device_CreateCommandQueue(device, &command_queue_desc,
&IID_ID3D12CommandQueue, (void **)&tmp_queue);
todo ok(hr == DXGI_ERROR_DEVICE_REMOVED, "Got unexpected hr %#x.\n", hr);
if (SUCCEEDED(hr))
ID3D12CommandQueue_Release(tmp_queue);
hr = ID3D12Device_GetDeviceRemovedReason(device);
ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
ID3D12GraphicsCommandList_Release(command_list);
ID3D12CommandAllocator_Release(command_allocator);
ID3D12CommandQueue_Release(queue);
refcount = ID3D12Device_Release(device);
ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount);
}