/* * Copyright 2016 Józef Kucia for CodeWeavers * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /* Hack for MinGW-w64 headers. * * We want to use WIDL C inline wrappers because some methods * in D3D12 interfaces return aggregate objects. Unfortunately, * WIDL C inline wrappers are broken when used with MinGW-w64 * headers because FORCEINLINE expands to extern inline * which leads to the "multiple storage classes in declaration * specifiers" compiler error. */ #ifdef __MINGW32__ # include <_mingw.h> # ifdef __MINGW64_VERSION_MAJOR # undef __forceinline # define __forceinline __inline__ __attribute__((__always_inline__,__gnu_inline__)) # endif # define _HRESULT_DEFINED typedef int HRESULT; #endif #define INITGUID #define COBJMACROS #include "vkd3d_test.h" #include "vkd3d_windows.h" #define WIDL_C_INLINE_WRAPPERS #include "d3d12.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) #define get_refcount(a) get_refcount_((IUnknown *)a) static ULONG get_refcount_(IUnknown *iface) { IUnknown_AddRef(iface); return IUnknown_Release(iface); } #define check_interface(a, b, c) check_interface_(__LINE__, (IUnknown *)a, b, c) static void check_interface_(unsigned int line, IUnknown *iface, REFIID riid, BOOL supported) { HRESULT hr, expected_hr; IUnknown *unk; expected_hr = supported ? S_OK : E_NOINTERFACE; hr = IUnknown_QueryInterface(iface, riid, (void **)&unk); ok_(line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr); if (SUCCEEDED(hr)) IUnknown_Release(unk); } #define create_root_signature(a, b, c) create_root_signature_(__LINE__, a, b, c) #if _WIN32 static HRESULT create_root_signature_(unsigned int line, ID3D12Device *device, const D3D12_ROOT_SIGNATURE_DESC *desc, ID3D12RootSignature **root_signature) { ID3DBlob *blob; HRESULT hr; if (FAILED(hr = D3D12SerializeRootSignature(desc, D3D_ROOT_SIGNATURE_VERSION_1_0, &blob, NULL))) return hr; hr = ID3D12Device_CreateRootSignature(device, 0, ID3D10Blob_GetBufferPointer(blob), ID3D10Blob_GetBufferSize(blob), &IID_ID3D12RootSignature, (void **)root_signature); ID3D10Blob_Release(blob); return hr; } #else /* XXX: Root signature byte code is not supported yet. We allow to pass D3D12_ROOT_SIGNATURE_DESC * directly to CreateRootSignature(). */ static HRESULT create_root_signature_(unsigned int line, ID3D12Device *device, const D3D12_ROOT_SIGNATURE_DESC *desc, ID3D12RootSignature **root_signature) { return ID3D12Device_CreateRootSignature(device, 0, desc, ~0u, &IID_ID3D12RootSignature, (void **)root_signature); } #endif static D3D12_SHADER_BYTECODE shader_bytecode(const DWORD *code, size_t size) { D3D12_SHADER_BYTECODE shader_bytecode = { code, size }; return shader_bytecode; } #if _WIN32 # define SHADER_BYTECODE(dxbc, spirv) ((void)spirv, shader_bytecode(dxbc, sizeof(dxbc))) #else # define SHADER_BYTECODE(dxbc, spirv) ((void)dxbc, shader_bytecode(spirv, sizeof(spirv))) #endif static ID3D12Device *create_device(void) { ID3D12Device *device; HRESULT hr; if (FAILED(hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, (void **)&device))) return NULL; return device; } static 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, "D3D12CreateDevice failed, hr %#x.\n", hr); ID3D12Device_Release(device); 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, "D3D12CreateDevice failed, hr %#x.\n", hr); hr = D3D12CreateDevice(NULL, ~0u, &IID_ID3D12Device, (void **)&device); ok(hr == E_INVALIDARG, "D3D12CreateDevice failed, hr %#x.\n", hr); } static 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); } static void test_check_feature_support(void) { D3D12_FEATURE_DATA_FEATURE_LEVELS feature_levels; D3D_FEATURE_LEVEL max_supported_feature_level; ID3D12Device *device; ULONG refcount; 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; } /* 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(SUCCEEDED(hr), "CheckFeatureSupport failed, 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(SUCCEEDED(hr), "CheckFeatureSupport failed, 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(SUCCEEDED(hr), "CheckFeatureSupport failed, 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(SUCCEEDED(hr), "CheckFeatureSupport failed, hr %#x.\n", hr); ok(feature_levels.MaxSupportedFeatureLevel == 0x3000, "Got unexpected max feature level %#x.\n", feature_levels.MaxSupportedFeatureLevel); refcount = ID3D12Device_Release(device); ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount); } static 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), "CreateCommandAllocator failed, 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), "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(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), "CreateCommandAllocator failed, 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), "CreateCommandAllocator failed, 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), "CreateCommandAllocator failed, 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, "CreateCommandAllocator failed, hr %#x.\n", hr); refcount = ID3D12Device_Release(device); ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount); } static 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), "CreateCommandAllocator failed, 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), "CreateCommandList failed, 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), "GetDevice failed, 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), "CreateCommandAllocator failed, 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), "CreateCommandList failed, 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), "CreateCommandAllocator failed, 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), "CreateCommandList failed, 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), "CreateCommandAllocator failed, 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), "CreateCommandList failed, 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); } static void test_create_command_queue(void) { D3D12_COMMAND_QUEUE_DESC desc, result_desc; ID3D12Device *device, *tmp_device; ID3D12CommandQueue *queue; 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), "CreateCommandQueue failed, 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), "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(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); refcount = ID3D12Device_Release(device); ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount); } static void test_create_committed_resource(void) { D3D12_HEAP_PROPERTIES heap_properties; D3D12_RESOURCE_DESC resource_desc; ID3D12Device *device, *tmp_device; D3D12_CLEAR_VALUE clear_value; ID3D12Resource *resource; ULONG refcount; HRESULT hr; if (!(device = create_device())) { skip("Failed to create device.\n"); return; } memset(&heap_properties, 0, sizeof(heap_properties)); heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; resource_desc.Alignment = 0; resource_desc.Width = 32; resource_desc.Height = 32; resource_desc.DepthOrArraySize = 1; resource_desc.MipLevels = 1; resource_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; resource_desc.SampleDesc.Count = 1; resource_desc.SampleDesc.Quality = 0; resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; clear_value.Format = DXGI_FORMAT_R8G8B8A8_UNORM; clear_value.Color[0] = 1.0f; clear_value.Color[1] = 0.0f; clear_value.Color[2] = 0.0f; clear_value.Color[3] = 1.0f; hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_RENDER_TARGET, &clear_value, &IID_ID3D12Resource, (void **)&resource); ok(SUCCEEDED(hr), "CreateCommittedResource failed, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount == 2, "Got unexpected refcount %u.\n", (unsigned int)refcount); hr = ID3D12Resource_GetDevice(resource, &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(resource, &IID_ID3D12Object, TRUE); check_interface(resource, &IID_ID3D12DeviceChild, TRUE); check_interface(resource, &IID_ID3D12Pageable, TRUE); check_interface(resource, &IID_ID3D12Resource, TRUE); refcount = ID3D12Resource_Release(resource); ok(!refcount, "ID3D12Resource has %u references left.\n", (unsigned int)refcount); heap_properties.Type = D3D12_HEAP_TYPE_UPLOAD; resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; resource_desc.Alignment = 0; resource_desc.Width = 32; resource_desc.Height = 1; resource_desc.DepthOrArraySize = 1; resource_desc.MipLevels = 1; resource_desc.Format = DXGI_FORMAT_UNKNOWN; resource_desc.SampleDesc.Count = 1; resource_desc.SampleDesc.Quality = 0; resource_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE; hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, &resource_desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, &IID_ID3D12Resource, (void **)&resource); ok(SUCCEEDED(hr), "CreateCommittedResource failed, hr %#x.\n", hr); check_interface(resource, &IID_ID3D12Object, TRUE); check_interface(resource, &IID_ID3D12DeviceChild, TRUE); check_interface(resource, &IID_ID3D12Pageable, TRUE); check_interface(resource, &IID_ID3D12Resource, TRUE); refcount = ID3D12Resource_Release(resource); ok(!refcount, "ID3D12Resource has %u references left.\n", (unsigned int)refcount); refcount = ID3D12Device_Release(device); ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount); } static void test_create_descriptor_heap(void) { D3D12_DESCRIPTOR_HEAP_DESC heap_desc; ID3D12Device *device, *tmp_device; ID3D12DescriptorHeap *heap; ULONG refcount; HRESULT hr; if (!(device = create_device())) { skip("Failed to create device.\n"); return; } heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; heap_desc.NumDescriptors = 16; heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; heap_desc.NodeMask = 0; hr = ID3D12Device_CreateDescriptorHeap(device, &heap_desc, &IID_ID3D12DescriptorHeap, (void **)&heap); ok(SUCCEEDED(hr), "CreateDescriptorHeap failed, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount == 2, "Got unexpected refcount %u.\n", (unsigned int)refcount); hr = ID3D12DescriptorHeap_GetDevice(heap, &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(heap, &IID_ID3D12Object, TRUE); check_interface(heap, &IID_ID3D12DeviceChild, TRUE); check_interface(heap, &IID_ID3D12Pageable, TRUE); check_interface(heap, &IID_ID3D12DescriptorHeap, TRUE); refcount = ID3D12DescriptorHeap_Release(heap); ok(!refcount, "ID3D12DescriptorHeap has %u references left.\n", (unsigned int)refcount); heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; hr = ID3D12Device_CreateDescriptorHeap(device, &heap_desc, &IID_ID3D12DescriptorHeap, (void **)&heap); ok(SUCCEEDED(hr), "CreateDescriptorHeap failed, hr %#x.\n", hr); refcount = ID3D12DescriptorHeap_Release(heap); ok(!refcount, "ID3D12DescriptorHeap has %u references left.\n", (unsigned int)refcount); heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; hr = ID3D12Device_CreateDescriptorHeap(device, &heap_desc, &IID_ID3D12DescriptorHeap, (void **)&heap); ok(SUCCEEDED(hr), "CreateDescriptorHeap failed, hr %#x.\n", hr); refcount = ID3D12DescriptorHeap_Release(heap); ok(!refcount, "ID3D12DescriptorHeap has %u references left.\n", (unsigned int)refcount); heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; hr = ID3D12Device_CreateDescriptorHeap(device, &heap_desc, &IID_ID3D12DescriptorHeap, (void **)&heap); ok(SUCCEEDED(hr), "CreateDescriptorHeap failed, hr %#x.\n", hr); refcount = ID3D12DescriptorHeap_Release(heap); ok(!refcount, "ID3D12DescriptorHeap has %u references left.\n", (unsigned int)refcount); heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; hr = ID3D12Device_CreateDescriptorHeap(device, &heap_desc, &IID_ID3D12DescriptorHeap, (void **)&heap); ok(SUCCEEDED(hr), "CreateDescriptorHeap failed, hr %#x.\n", hr); refcount = ID3D12DescriptorHeap_Release(heap); ok(!refcount, "ID3D12DescriptorHeap has %u references left.\n", (unsigned int)refcount); refcount = ID3D12Device_Release(device); ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount); } static void test_create_root_signature(void) { D3D12_ROOT_SIGNATURE_DESC root_signature_desc; D3D12_DESCRIPTOR_RANGE descriptor_ranges[1]; D3D12_ROOT_PARAMETER root_parameters[1]; ID3D12RootSignature *root_signature; ID3D12Device *device, *tmp_device; ULONG refcount; HRESULT hr; if (!(device = create_device())) { skip("Failed to create device.\n"); return; } descriptor_ranges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; descriptor_ranges[0].NumDescriptors = 1; descriptor_ranges[0].BaseShaderRegister = 0; descriptor_ranges[0].RegisterSpace = 0; descriptor_ranges[0].OffsetInDescriptorsFromTableStart = 0; root_parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; root_parameters[0].DescriptorTable.NumDescriptorRanges = 1; root_parameters[0].DescriptorTable.pDescriptorRanges = descriptor_ranges; root_parameters[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; root_signature_desc.NumParameters = 1; root_signature_desc.pParameters = root_parameters; root_signature_desc.NumStaticSamplers = 0; root_signature_desc.pStaticSamplers = NULL; root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; hr = create_root_signature(device, &root_signature_desc, &root_signature); ok(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", 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); root_signature_desc.NumParameters = 0; root_signature_desc.pParameters = NULL; root_signature_desc.NumStaticSamplers = 0; root_signature_desc.pStaticSamplers = NULL; root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; hr = create_root_signature(device, &root_signature_desc, &root_signature); ok(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr); refcount = ID3D12RootSignature_Release(root_signature); ok(!refcount, "ID3D12RootSignature has %u references left.\n", (unsigned int)refcount); refcount = ID3D12Device_Release(device); ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount); } static void test_create_pipeline_state(void) { D3D12_COMPUTE_PIPELINE_STATE_DESC pipeline_state_desc; D3D12_ROOT_SIGNATURE_DESC root_signature_desc; ID3D12RootSignature *root_signature; ID3D12PipelineState *pipeline_state; ID3D12Device *device, *tmp_device; ULONG refcount; HRESULT hr; static const DWORD dxbc_code[] = { #if 0 [numthreads(1, 1, 1)] void main() { } #endif 0x43425844, 0x1acc3ad0, 0x71c7b057, 0xc72c4306, 0xf432cb57, 0x00000001, 0x00000074, 0x00000003, 0x0000002c, 0x0000003c, 0x0000004c, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000020, 0x00050050, 0x00000008, 0x0100086a, 0x0400009b, 0x00000001, 0x00000001, 0x00000001, 0x0100003e, }; static const DWORD spv_code[] = { #if 0 #version 450 core void main() { } #endif 0x07230203, 0x00010000, 0x00080001, 0x00003ee8, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, 0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0005000f, 0x00000005, 0x0000161f, 0x6e69616d, 0x00000000, 0x00060010, 0x0000161f, 0x00000011, 0x00000001, 0x00000001, 0x00000001, 0x00020013, 0x00000008, 0x00030021, 0x00000502, 0x00000008, 0x00050036, 0x00000008, 0x0000161f, 0x00000000, 0x00000502, 0x000200f8, 0x00003ee7, 0x000100fd, 0x00010038, }; if (!(device = create_device())) { skip("Failed to create device.\n"); return; } root_signature_desc.NumParameters = 0; root_signature_desc.pParameters = NULL; root_signature_desc.NumStaticSamplers = 0; root_signature_desc.pStaticSamplers = NULL; root_signature_desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; hr = create_root_signature(device, &root_signature_desc, &root_signature); ok(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr); refcount = get_refcount(device); ok(refcount == 2, "Got unexpected refcount %u.\n", (unsigned int)refcount); memset(&pipeline_state_desc, 0, sizeof(pipeline_state_desc)); pipeline_state_desc.pRootSignature = root_signature; pipeline_state_desc.CS = SHADER_BYTECODE(dxbc_code, spv_code); pipeline_state_desc.NodeMask = 0; pipeline_state_desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; hr = ID3D12Device_CreateComputePipelineState(device, &pipeline_state_desc, &IID_ID3D12PipelineState, (void **)&pipeline_state); ok(SUCCEEDED(hr), "CreateComputePipelineState failed, hr %#x.\n", hr); refcount = get_refcount(root_signature); 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 = ID3D12PipelineState_GetDevice(pipeline_state, &IID_ID3D12Device, (void **)&tmp_device); ok(SUCCEEDED(hr), "GetDevice failed, 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(pipeline_state, &IID_ID3D12Object, TRUE); check_interface(pipeline_state, &IID_ID3D12DeviceChild, TRUE); check_interface(pipeline_state, &IID_ID3D12Pageable, TRUE); check_interface(pipeline_state, &IID_ID3D12PipelineState, TRUE); refcount = ID3D12PipelineState_Release(pipeline_state); ok(!refcount, "ID3D12PipelineState has %u references left.\n", (unsigned int)refcount); refcount = ID3D12RootSignature_Release(root_signature); ok(!refcount, "ID3D12RootSignature has %u references left.\n", (unsigned int)refcount); refcount = ID3D12Device_Release(device); ok(!refcount, "ID3D12Device has %u references left.\n", (unsigned int)refcount); } START_TEST(d3d12) { ID3D12Debug *debug; if (SUCCEEDED(D3D12GetDebugInterface(&IID_ID3D12Debug, (void **)&debug))) { ID3D12Debug_EnableDebugLayer(debug); ID3D12Debug_Release(debug); } test_create_device(); test_node_count(); test_check_feature_support(); test_create_command_allocator(); test_create_command_list(); test_create_command_queue(); test_create_committed_resource(); test_create_descriptor_heap(); test_create_root_signature(); test_create_pipeline_state(); }