diff --git a/include/private/vkd3d_test.h b/include/private/vkd3d_test.h index 1c53e79c..7d8f9b1d 100644 --- a/include/private/vkd3d_test.h +++ b/include/private/vkd3d_test.h @@ -29,7 +29,10 @@ #include #include +#ifdef VKD3D_TEST_DECLARE_MAIN static void vkd3d_test_main(int argc, char **argv); +#endif + static const char *vkd3d_test_name; static const char *vkd3d_test_platform = "other"; @@ -266,6 +269,7 @@ vkd3d_test_debug(const char *fmt, ...) } } +#ifdef VKD3D_TEST_DECLARE_MAIN int main(int argc, char **argv) { const char *exclude_list = getenv("VKD3D_TEST_EXCLUDE"); @@ -355,6 +359,7 @@ int wmain(int argc, WCHAR **wargv) return ret; } #endif /* _WIN32 */ +#endif /* VKD3D_TEST_DECLARE_MAIN */ typedef void (*vkd3d_test_pfn)(void); diff --git a/tests/d3d12.c b/tests/d3d12.c index 3297333d..a56025aa 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -18,956 +18,10 @@ #define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API +#define INITGUID +#define VKD3D_TEST_DECLARE_MAIN #include "d3d12_crosstest.h" -PFN_D3D12_CREATE_VERSIONED_ROOT_SIGNATURE_DESERIALIZER pfn_D3D12CreateVersionedRootSignatureDeserializer; -PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE pfn_D3D12SerializeVersionedRootSignature; -PFN_D3D12_CREATE_DEVICE pfn_D3D12CreateDevice; -PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES pfn_D3D12EnableExperimentalFeatures; -PFN_D3D12_GET_DEBUG_INTERFACE pfn_D3D12GetDebugInterface; - -bool compare_float(float f, float g, int ulps) -{ - int x, y; - union - { - float f; - int i; - } u; - - u.f = f; - x = u.i; - u.f = g; - y = u.i; - - if (x < 0) - x = INT_MIN - x; - if (y < 0) - y = INT_MIN - y; - - if (abs(x - y) > ulps) - return false; - - return true; -} - -bool compare_vec4(const struct vec4 *v1, const struct vec4 *v2, unsigned int ulps) -{ - return compare_float(v1->x, v2->x, ulps) - && compare_float(v1->y, v2->y, ulps) - && compare_float(v1->z, v2->z, ulps) - && compare_float(v1->w, v2->w, ulps); -} - -bool compare_uvec4(const struct uvec4* v1, const struct uvec4 *v2) -{ - return v1->x == v2->x && v1->y == v2->y && v1->z == v2->z && v1->w == v2->w; -} - -bool compare_uint8(uint8_t a, uint8_t b, unsigned int max_diff) -{ - return delta_uint8(a, b) <= max_diff; -} - -bool compare_uint16(uint16_t a, uint16_t b, unsigned int max_diff) -{ - return delta_uint16(a, b) <= max_diff; -} - -bool compare_uint64(uint64_t a, uint64_t b, unsigned int max_diff) -{ - return delta_uint64(a, b) <= max_diff; -} - -ULONG get_refcount(void *iface) -{ - IUnknown *unk = iface; - IUnknown_AddRef(unk); - return IUnknown_Release(unk); -} - -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); -} - -void check_heap_properties_(unsigned int line, - const D3D12_HEAP_PROPERTIES *properties, const D3D12_HEAP_PROPERTIES *expected_properties) -{ - D3D12_HEAP_PROPERTIES expected = *expected_properties; - - if (!expected.CreationNodeMask) - expected.CreationNodeMask = 0x1; - if (!expected.VisibleNodeMask) - expected.VisibleNodeMask = 0x1; - - ok_(line)(properties->Type == expected.Type, - "Got type %#x, expected %#x.\n", properties->Type, expected.Type); - ok_(line)(properties->CPUPageProperty == expected.CPUPageProperty, - "Got CPU page properties %#x, expected %#x.\n", - properties->CPUPageProperty, expected.CPUPageProperty); - ok_(line)(properties->MemoryPoolPreference == expected.MemoryPoolPreference, - "Got memory pool %#x, expected %#x.\n", - properties->MemoryPoolPreference, expected.MemoryPoolPreference); - ok_(line)(properties->CreationNodeMask == expected.CreationNodeMask, - "Got creation node mask %#x, expected %#x.\n", - properties->CreationNodeMask, expected.CreationNodeMask); - ok_(line)(properties->VisibleNodeMask == expected.VisibleNodeMask, - "Got visible node mask %#x, expected %#x.\n", - properties->VisibleNodeMask, expected.VisibleNodeMask); -} - -void check_heap_desc_(unsigned int line, const D3D12_HEAP_DESC *desc, - const D3D12_HEAP_DESC *expected_desc) -{ - D3D12_HEAP_DESC expected = *expected_desc; - - if (!expected.Alignment) - expected.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; - - ok_(line)(desc->SizeInBytes == expected.SizeInBytes, - "Got size %"PRIu64", expected %"PRIu64".\n", - desc->SizeInBytes, expected.SizeInBytes); - check_heap_properties_(line, &desc->Properties, &expected.Properties); - ok_(line)(desc->Alignment == expected.Alignment, - "Got alignment %"PRIu64", expected %"PRIu64".\n", - desc->Alignment, expected.Alignment); - ok_(line)(desc->Flags == expected.Flags, - "Got flags %#x, expected %#x.\n", desc->Flags, expected.Flags); -} - -void check_alignment_(unsigned int line, uint64_t size, uint64_t alignment) -{ - uint64_t aligned_size = align(size, alignment); - ok_(line)(aligned_size == size, "Got unaligned size %"PRIu64", expected %"PRIu64".\n", - size, aligned_size); -} - -void uav_barrier(ID3D12GraphicsCommandList *list, ID3D12Resource *resource) -{ - D3D12_RESOURCE_BARRIER barrier; - - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.UAV.pResource = resource; - - ID3D12GraphicsCommandList_ResourceBarrier(list, 1, &barrier); -} - -void copy_sub_resource_data(const D3D12_MEMCPY_DEST *dst, const D3D12_SUBRESOURCE_DATA *src, - unsigned int row_count, unsigned int slice_count, size_t row_size) -{ - const BYTE *src_slice_ptr; - BYTE *dst_slice_ptr; - unsigned int z, y; - - for (z = 0; z < slice_count; ++z) - { - dst_slice_ptr = (BYTE *)dst->pData + z * dst->SlicePitch; - src_slice_ptr = (const BYTE*)src->pData + z * src->SlicePitch; - for (y = 0; y < row_count; ++y) - memcpy(dst_slice_ptr + y * dst->RowPitch, src_slice_ptr + y * src->RowPitch, row_size); - } -} - -void upload_buffer_data_(unsigned int line, ID3D12Resource *buffer, size_t offset, - size_t size, const void *data, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list) -{ - ID3D12Resource *upload_buffer; - ID3D12Device *device; - HRESULT hr; - - hr = ID3D12Resource_GetDevice(buffer, &IID_ID3D12Device, (void **)&device); - ok_(line)(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr); - - upload_buffer = create_upload_buffer_(line, device, size, data); - - ID3D12GraphicsCommandList_CopyBufferRegion(command_list, buffer, offset, - upload_buffer, 0, size); - - hr = ID3D12GraphicsCommandList_Close(command_list); - ok_(line)(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr); - exec_command_list(queue, command_list); - wait_queue_idle(device, queue); - - ID3D12Resource_Release(upload_buffer); - ID3D12Device_Release(device); -} - -void upload_texture_data_(unsigned int line, ID3D12Resource *texture, - const D3D12_SUBRESOURCE_DATA *data, unsigned int sub_resource_count, - ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list) -{ - D3D12_TEXTURE_COPY_LOCATION dst_location, src_location; - D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts; - uint64_t *row_sizes, required_size; - D3D12_RESOURCE_DESC resource_desc; - ID3D12Resource *upload_buffer; - D3D12_MEMCPY_DEST dst_data; - ID3D12Device *device; - UINT *row_counts; - unsigned int i; - HRESULT hr; - void *ptr; - - layouts = calloc(sub_resource_count, sizeof(*layouts)); - ok(layouts, "Failed to allocate memory.\n"); - row_counts = calloc(sub_resource_count, sizeof(*row_counts)); - ok(row_counts, "Failed to allocate memory.\n"); - row_sizes = calloc(sub_resource_count, sizeof(*row_sizes)); - ok(row_sizes, "Failed to allocate memory.\n"); - - resource_desc = ID3D12Resource_GetDesc(texture); - hr = ID3D12Resource_GetDevice(texture, &IID_ID3D12Device, (void **)&device); - ok_(line)(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr); - - ID3D12Device_GetCopyableFootprints(device, &resource_desc, 0, sub_resource_count, - 0, layouts, row_counts, row_sizes, &required_size); - - upload_buffer = create_upload_buffer_(line, device, required_size, NULL); - - hr = ID3D12Resource_Map(upload_buffer, 0, NULL, (void **)&ptr); - ok_(line)(SUCCEEDED(hr), "Failed to map upload buffer, hr %#x.\n", hr); - for (i = 0; i < sub_resource_count; ++i) - { - dst_data.pData = (BYTE *)ptr + layouts[i].Offset; - dst_data.RowPitch = layouts[i].Footprint.RowPitch; - dst_data.SlicePitch = layouts[i].Footprint.RowPitch * row_counts[i]; - copy_sub_resource_data(&dst_data, &data[i], - row_counts[i], layouts[i].Footprint.Depth, row_sizes[i]); - } - ID3D12Resource_Unmap(upload_buffer, 0, NULL); - - for (i = 0; i < sub_resource_count; ++i) - { - dst_location.pResource = texture; - dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - dst_location.SubresourceIndex = i; - - src_location.pResource = upload_buffer; - src_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - src_location.PlacedFootprint = layouts[i]; - - ID3D12GraphicsCommandList_CopyTextureRegion(command_list, - &dst_location, 0, 0, 0, &src_location, NULL); - } - - hr = ID3D12GraphicsCommandList_Close(command_list); - ok_(line)(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr); - - exec_command_list(queue, command_list); - wait_queue_idle(device, queue); - - ID3D12Resource_Release(upload_buffer); - ID3D12Device_Release(device); - - free(layouts); - free(row_counts); - free(row_sizes); -} - -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 init_readback(struct resource_readback *rb, ID3D12Resource *buffer, - uint64_t buffer_size, uint64_t width, uint64_t height, unsigned int depth, uint64_t row_pitch) -{ - D3D12_RANGE read_range; - HRESULT hr; - - rb->width = width; - rb->height = height; - rb->depth = depth; - rb->resource = buffer; - rb->row_pitch = row_pitch; - rb->data = NULL; - - ID3D12Resource_AddRef(rb->resource); - - read_range.Begin = 0; - read_range.End = buffer_size; - hr = ID3D12Resource_Map(rb->resource, 0, &read_range, &rb->data); - ok(hr == S_OK, "Failed to map readback buffer, hr %#x.\n", hr); -} - -void get_buffer_readback_with_command_list(ID3D12Resource *buffer, DXGI_FORMAT format, - struct resource_readback *rb, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list) -{ - D3D12_HEAP_PROPERTIES heap_properties; - D3D12_RESOURCE_DESC resource_desc; - ID3D12Resource *rb_buffer; - D3D12_RANGE read_range; - ID3D12Device *device; - HRESULT hr; - - hr = ID3D12Resource_GetDevice(buffer, &IID_ID3D12Device, (void **)&device); - ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr); - - resource_desc = ID3D12Resource_GetDesc(buffer); - assert(resource_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER); - resource_desc.Flags = D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE; - - hr = ID3D12Resource_GetHeapProperties(buffer, &heap_properties, NULL); - if (SUCCEEDED(hr) && heap_properties.Type == D3D12_HEAP_TYPE_READBACK) - { - rb_buffer = buffer; - ID3D12Resource_AddRef(rb_buffer); - } - else - { - rb_buffer = create_readback_buffer(device, resource_desc.Width); - ID3D12GraphicsCommandList_CopyBufferRegion(command_list, rb_buffer, 0, - buffer, 0, resource_desc.Width); - } - - hr = ID3D12GraphicsCommandList_Close(command_list); - ok(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr); - - exec_command_list(queue, command_list); - wait_queue_idle(device, queue); - ID3D12Device_Release(device); - - rb->width = resource_desc.Width / format_size(format); - rb->height = 1; - rb->depth = 1; - rb->resource = rb_buffer; - rb->row_pitch = resource_desc.Width; - rb->data = NULL; - - read_range.Begin = 0; - read_range.End = resource_desc.Width; - hr = ID3D12Resource_Map(rb_buffer, 0, &read_range, &rb->data); - ok(SUCCEEDED(hr), "Failed to map readback buffer, hr %#x.\n", hr); -} - -uint8_t get_readback_uint8(struct resource_readback *rb, unsigned int x, unsigned int y) -{ - return *(uint8_t *)get_readback_data(rb, x, y, 0, sizeof(uint8_t)); -} - -uint16_t get_readback_uint16(struct resource_readback *rb, unsigned int x, unsigned int y) -{ - return *(uint16_t *)get_readback_data(rb, x, y, 0, sizeof(uint16_t)); -} - -uint64_t get_readback_uint64(struct resource_readback *rb, unsigned int x, unsigned int y) -{ - return *(uint64_t *)get_readback_data(rb, x, y, 0, sizeof(uint64_t)); -} - -float get_readback_float(struct resource_readback *rb, unsigned int x, unsigned int y) -{ - return *(float *)get_readback_data(rb, x, y, 0, sizeof(float)); -} - -const struct vec4 *get_readback_vec4(struct resource_readback *rb, unsigned int x, unsigned int y) -{ - return get_readback_data(rb, x, y, 0, sizeof(struct vec4)); -} - -const struct uvec4 *get_readback_uvec4(struct resource_readback *rb, unsigned int x, unsigned int y) -{ - return get_readback_data(rb, x, y, 0, sizeof(struct uvec4)); -} - -void check_readback_data_float_(unsigned int line, struct resource_readback *rb, - const RECT *rect, float expected, unsigned int max_diff) -{ - RECT r = {0, 0, rb->width, rb->height}; - int x = 0, y; - bool all_match = true; - float got = 0; - - if (rect) - r = *rect; - - for (y = r.top; y < r.bottom; ++y) - { - for (x = r.left; x < r.right; ++x) - { - got = get_readback_float(rb, x, y); - if (!compare_float(got, expected, max_diff)) - { - all_match = false; - break; - } - } - if (!all_match) - break; - } - ok_(line)(all_match, "Got %.8e, expected %.8e at (%u, %u).\n", got, expected, x, y); -} - -void check_sub_resource_float_(unsigned int line, ID3D12Resource *texture, - unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, - float expected, unsigned int max_diff) -{ - struct resource_readback rb; - - get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); - check_readback_data_float_(line, &rb, NULL, expected, max_diff); - release_resource_readback(&rb); -} - -void check_readback_data_uint8_(unsigned int line, struct resource_readback *rb, - const RECT *rect, uint8_t expected, unsigned int max_diff) -{ - RECT r = {0, 0, rb->width, rb->height}; - int x = 0, y; - bool all_match = true; - uint8_t got = 0; - - if (rect) - r = *rect; - - for (y = r.top; y < r.bottom; ++y) - { - for (x = r.left; x < r.right; ++x) - { - got = get_readback_uint8(rb, x, y); - if (!compare_uint8(got, expected, max_diff)) - { - all_match = false; - break; - } - } - if (!all_match) - break; - } - ok_(line)(all_match, "Got 0x%02x, expected 0x%02x at (%u, %u).\n", got, expected, x, y); -} - -void check_sub_resource_uint8_(unsigned int line, ID3D12Resource *texture, - unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, - uint8_t expected, unsigned int max_diff) -{ - struct resource_readback rb; - - get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); - check_readback_data_uint8_(line, &rb, NULL, expected, max_diff); - release_resource_readback(&rb); -} - -void check_readback_data_uint16_(unsigned int line, struct resource_readback *rb, - const RECT *rect, uint16_t expected, unsigned int max_diff) -{ - RECT r = {0, 0, rb->width, rb->height}; - int x = 0, y; - bool all_match = true; - uint16_t got = 0; - - if (rect) - r = *rect; - - for (y = r.top; y < r.bottom; ++y) - { - for (x = r.left; x < r.right; ++x) - { - got = get_readback_uint16(rb, x, y); - if (!compare_uint16(got, expected, max_diff)) - { - all_match = false; - break; - } - } - if (!all_match) - break; - } - ok_(line)(all_match, "Got 0x%04x, expected 0x%04x at (%u, %u).\n", got, expected, x, y); -} - -void check_sub_resource_uint16_(unsigned int line, ID3D12Resource *texture, - unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, - uint16_t expected, unsigned int max_diff) -{ - struct resource_readback rb; - - get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); - check_readback_data_uint16_(line, &rb, NULL, expected, max_diff); - release_resource_readback(&rb); -} - -void check_readback_data_uint64_(unsigned int line, struct resource_readback *rb, - const RECT *rect, uint64_t expected, unsigned int max_diff) -{ - RECT r = {0, 0, rb->width, rb->height}; - int x = 0, y; - bool all_match = true; - uint64_t got = 0; - - if (rect) - r = *rect; - - for (y = r.top; y < r.bottom; ++y) - { - for (x = r.left; x < r.right; ++x) - { - got = get_readback_uint64(rb, x, y); - if (!compare_uint64(got, expected, max_diff)) - { - all_match = false; - break; - } - } - if (!all_match) - break; - } - ok_(line)(all_match, "Got %#"PRIx64", expected %#"PRIx64" at (%u, %u).\n", got, expected, x, y); -} - -void check_sub_resource_uint64_(unsigned int line, ID3D12Resource *texture, - unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, - uint64_t expected, unsigned int max_diff) -{ - struct resource_readback rb; - - get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); - check_readback_data_uint64_(line, &rb, NULL, expected, max_diff); - release_resource_readback(&rb); -} - -void check_sub_resource_vec4_(unsigned int line, ID3D12Resource *texture, - unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, - const struct vec4 *expected, unsigned int max_diff) -{ - struct resource_readback rb; - unsigned int x = 0, y; - bool all_match = true; - struct vec4 got = {0}; - - get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); - for (y = 0; y < rb.height; ++y) - { - for (x = 0; x < rb.width; ++x) - { - got = *get_readback_vec4(&rb, x, y); - if (!compare_vec4(&got, expected, max_diff)) - { - all_match = false; - break; - } - } - if (!all_match) - break; - } - release_resource_readback(&rb); - - ok_(line)(all_match, "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e} at (%u, %u).\n", - got.x, got.y, got.z, got.w, expected->x, expected->y, expected->z, expected->w, x, y); -} - -void check_sub_resource_uvec4_(unsigned int line, ID3D12Resource *texture, - unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, - const struct uvec4 *expected_value) -{ - struct resource_readback rb; - struct uvec4 value = {0}; - unsigned int x = 0, y; - bool all_match = true; - - get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); - for (y = 0; y < rb.height; ++y) - { - for (x = 0; x < rb.width; ++x) - { - value = *get_readback_uvec4(&rb, x, y); - if (!compare_uvec4(&value, expected_value)) - { - all_match = false; - break; - } - } - if (!all_match) - break; - } - release_resource_readback(&rb); - - ok_(line)(all_match, - "Got {0x%08x, 0x%08x, 0x%08x, 0x%08x}, expected {0x%08x, 0x%08x, 0x%08x, 0x%08x} at (%u, %u).\n", - value.x, value.y, value.z, value.w, - expected_value->x, expected_value->y, expected_value->z, expected_value->w, x, y); -} - -bool broken_on_warp(bool condition) -{ - return broken(use_warp_device && condition); -} - -bool is_min_max_filtering_supported(ID3D12Device *device) -{ - D3D12_FEATURE_DATA_D3D12_OPTIONS options; - HRESULT hr; - - if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, - D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)))) - { - trace("Failed to check feature support, hr %#x.\n", hr); - return false; - } - - /* D3D12 validation layer says tiled resource tier 2+ support implies min/max filtering support. */ - return options.TiledResourcesTier >= D3D12_TILED_RESOURCES_TIER_2; -} - -D3D12_TILED_RESOURCES_TIER get_tiled_resources_tier(ID3D12Device *device) -{ - D3D12_FEATURE_DATA_D3D12_OPTIONS options; - HRESULT hr; - - if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, - D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)))) - { - trace("Failed to check feature support, hr %#x.\n", hr); - return D3D12_TILED_RESOURCES_TIER_NOT_SUPPORTED; - } - - return options.TiledResourcesTier; -} - -bool is_standard_swizzle_64kb_supported(ID3D12Device *device) -{ - D3D12_FEATURE_DATA_D3D12_OPTIONS options; - HRESULT hr; - - if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, - D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)))) - { - trace("Failed to check feature support, hr %#x.\n", hr); - return false; - } - - return options.StandardSwizzle64KBSupported; -} - -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; -} - -bool is_vrs_tier1_supported(ID3D12Device *device, bool *additional_shading_rates) -{ - D3D12_FEATURE_DATA_D3D12_OPTIONS6 options; - HRESULT hr; - - if (additional_shading_rates) - *additional_shading_rates = false; - - if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, - D3D12_FEATURE_D3D12_OPTIONS6, &options, sizeof(options)))) - { - trace("Failed to check feature support, hr %#x.\n", hr); - return false; - } - - if (additional_shading_rates) - *additional_shading_rates = options.AdditionalShadingRatesSupported; - - return options.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_1; -} - -bool is_vrs_tier2_supported(ID3D12Device *device) -{ - D3D12_FEATURE_DATA_D3D12_OPTIONS6 options; - HRESULT hr; - - if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, - D3D12_FEATURE_D3D12_OPTIONS6, &options, sizeof(options)))) - { - trace("Failed to check feature support, hr %#x.\n", hr); - return false; - } - return options.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_2; -} - -ID3D12RootSignature *create_cb_root_signature_(unsigned int line, - ID3D12Device *device, unsigned int reg_idx, D3D12_SHADER_VISIBILITY shader_visibility, - D3D12_ROOT_SIGNATURE_FLAGS flags) -{ - D3D12_ROOT_SIGNATURE_DESC root_signature_desc; - ID3D12RootSignature *root_signature = NULL; - D3D12_ROOT_PARAMETER root_parameter; - HRESULT hr; - - root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; - root_parameter.Descriptor.ShaderRegister = reg_idx; - root_parameter.Descriptor.RegisterSpace = 0; - root_parameter.ShaderVisibility = shader_visibility; - - memset(&root_signature_desc, 0, sizeof(root_signature_desc)); - root_signature_desc.NumParameters = 1; - root_signature_desc.pParameters = &root_parameter; - root_signature_desc.Flags = flags; - hr = create_root_signature(device, &root_signature_desc, &root_signature); - ok_(line)(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr); - - return root_signature; -} - -ID3D12RootSignature *create_32bit_constants_root_signature_(unsigned int line, - ID3D12Device *device, unsigned int reg_idx, unsigned int element_count, - D3D12_SHADER_VISIBILITY shader_visibility, D3D12_ROOT_SIGNATURE_FLAGS flags) -{ - D3D12_ROOT_SIGNATURE_DESC root_signature_desc; - ID3D12RootSignature *root_signature = NULL; - D3D12_ROOT_PARAMETER root_parameter; - HRESULT hr; - - root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; - root_parameter.Constants.ShaderRegister = reg_idx; - root_parameter.Constants.RegisterSpace = 0; - root_parameter.Constants.Num32BitValues = element_count; - root_parameter.ShaderVisibility = shader_visibility; - - memset(&root_signature_desc, 0, sizeof(root_signature_desc)); - root_signature_desc.NumParameters = 1; - root_signature_desc.pParameters = &root_parameter; - root_signature_desc.Flags = flags; - hr = create_root_signature(device, &root_signature_desc, &root_signature); - ok_(line)(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr); - - return root_signature; -} - -ID3D12RootSignature *create_texture_root_signature_(unsigned int line, - ID3D12Device *device, D3D12_SHADER_VISIBILITY shader_visibility, - unsigned int constant_count, D3D12_ROOT_SIGNATURE_FLAGS flags, - const D3D12_STATIC_SAMPLER_DESC *sampler_desc) -{ - D3D12_ROOT_SIGNATURE_DESC root_signature_desc; - ID3D12RootSignature *root_signature = NULL; - D3D12_STATIC_SAMPLER_DESC static_sampler; - D3D12_DESCRIPTOR_RANGE descriptor_range; - D3D12_ROOT_PARAMETER root_parameters[2]; - HRESULT hr; - - if (sampler_desc) - { - static_sampler = *sampler_desc; - } - else - { - memset(&static_sampler, 0, sizeof(static_sampler)); - static_sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; - static_sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - static_sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - static_sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - static_sampler.MaxLOD = D3D12_FLOAT32_MAX; - static_sampler.ShaderRegister = 0; - static_sampler.RegisterSpace = 0; - static_sampler.ShaderVisibility = shader_visibility; - } - - descriptor_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - descriptor_range.NumDescriptors = 1; - descriptor_range.BaseShaderRegister = 0; - descriptor_range.RegisterSpace = 0; - descriptor_range.OffsetInDescriptorsFromTableStart = 0; - root_parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - root_parameters[0].DescriptorTable.NumDescriptorRanges = 1; - root_parameters[0].DescriptorTable.pDescriptorRanges = &descriptor_range; - root_parameters[0].ShaderVisibility = shader_visibility; - - root_parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; - root_parameters[1].Constants.ShaderRegister = 0; - root_parameters[1].Constants.RegisterSpace = 0; - root_parameters[1].Constants.Num32BitValues = constant_count; - root_parameters[1].ShaderVisibility = shader_visibility; - - memset(&root_signature_desc, 0, sizeof(root_signature_desc)); - root_signature_desc.NumParameters = constant_count ? 2 : 1; - root_signature_desc.pParameters = root_parameters; - root_signature_desc.NumStaticSamplers = 1; - root_signature_desc.pStaticSamplers = &static_sampler; - root_signature_desc.Flags = flags; - - hr = create_root_signature(device, &root_signature_desc, &root_signature); - ok_(line)(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr); - - return root_signature; -} - -ID3D12PipelineState *create_compute_pipeline_state_(unsigned int line, ID3D12Device *device, - ID3D12RootSignature *root_signature, const D3D12_SHADER_BYTECODE cs) -{ - D3D12_COMPUTE_PIPELINE_STATE_DESC pipeline_state_desc; - ID3D12PipelineState *pipeline_state = NULL; - HRESULT hr; - - memset(&pipeline_state_desc, 0, sizeof(pipeline_state_desc)); - pipeline_state_desc.pRootSignature = root_signature; - pipeline_state_desc.CS = cs; - 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_(line)(SUCCEEDED(hr), "Failed to create compute pipeline state, hr %#x.\n", hr); - return pipeline_state; -} - -ID3D12CommandSignature *create_command_signature_(unsigned int line, - ID3D12Device *device, D3D12_INDIRECT_ARGUMENT_TYPE argument_type) -{ - ID3D12CommandSignature *command_signature = NULL; - D3D12_COMMAND_SIGNATURE_DESC signature_desc; - D3D12_INDIRECT_ARGUMENT_DESC argument_desc; - HRESULT hr; - - argument_desc.Type = argument_type; - - switch (argument_type) - { - case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW: - signature_desc.ByteStride = sizeof(D3D12_DRAW_ARGUMENTS); - break; - case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED: - signature_desc.ByteStride = sizeof(D3D12_DRAW_INDEXED_ARGUMENTS); - break; - case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH: - signature_desc.ByteStride = sizeof(D3D12_DISPATCH_ARGUMENTS); - break; - default: - return NULL; - } - - signature_desc.NumArgumentDescs = 1; - signature_desc.pArgumentDescs = &argument_desc; - signature_desc.NodeMask = 0; - hr = ID3D12Device_CreateCommandSignature(device, &signature_desc, - NULL, &IID_ID3D12CommandSignature, (void **)&command_signature); - ok_(line)(hr == S_OK, "Failed to create command signature, hr %#x.\n", hr); - - return command_signature; -} - -bool init_compute_test_context_(unsigned int line, struct test_context *context) -{ - ID3D12Device *device; - HRESULT hr; - - memset(context, 0, sizeof(*context)); - - if (!(context->device = create_device())) - { - skip_(line)("Failed to create device.\n"); - return false; - } - device = context->device; - - context->queue = create_command_queue_(line, device, - D3D12_COMMAND_LIST_TYPE_COMPUTE, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL); - - hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_COMPUTE, - &IID_ID3D12CommandAllocator, (void **)&context->allocator); - ok_(line)(hr == S_OK, "Failed to create command allocator, hr %#x.\n", hr); - - hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_COMPUTE, - context->allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&context->list); - ok_(line)(hr == S_OK, "Failed to create command list, hr %#x.\n", hr); - - return true; -} - -bool context_supports_dxil_(unsigned int line, struct test_context *context) -{ - D3D12_FEATURE_DATA_SHADER_MODEL model; - HRESULT hr; - model.HighestShaderModel = D3D_SHADER_MODEL_6_0; - hr = ID3D12Device_CheckFeatureSupport(context->device, D3D12_FEATURE_SHADER_MODEL, &model, sizeof(model)); - ok_(line)(hr == S_OK, "Failed to query shader model support, hr %#x.\n", hr); - - if (hr != S_OK) - return false; - - if (model.HighestShaderModel < D3D_SHADER_MODEL_6_0) - { - skip_(line)("Device does not support shader model 6.0, skipping DXIL tests.\n"); - return false; - } - else - return true; -} - -void init_depth_stencil_(unsigned int line, struct depth_stencil_resource *ds, - ID3D12Device *device, unsigned int width, unsigned int height, unsigned int array_size, unsigned int level_count, - DXGI_FORMAT format, DXGI_FORMAT view_format, const D3D12_CLEAR_VALUE *clear_value) -{ - D3D12_DEPTH_STENCIL_VIEW_DESC dsv_desc, *view_desc; - D3D12_HEAP_PROPERTIES heap_properties; - D3D12_RESOURCE_DESC resource_desc; - HRESULT hr; - - memset(ds, 0, sizeof(*ds)); - - ds->heap = create_cpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1); - - 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 = width; - resource_desc.Height = height; - resource_desc.DepthOrArraySize = array_size; - resource_desc.MipLevels = level_count; - resource_desc.Format = format; - resource_desc.SampleDesc.Count = 1; - resource_desc.SampleDesc.Quality = 0; - resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; - hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, - &resource_desc, D3D12_RESOURCE_STATE_DEPTH_WRITE, clear_value, - &IID_ID3D12Resource, (void **)&ds->texture); - ok_(line)(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); - - view_desc = NULL; - if (view_format) - { - memset(&dsv_desc, 0, sizeof(dsv_desc)); - dsv_desc.Format = view_format; - dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; - view_desc = &dsv_desc; - } - ds->dsv_handle = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(ds->heap); - ID3D12Device_CreateDepthStencilView(device, ds->texture, view_desc, ds->dsv_handle); -} - -void destroy_depth_stencil_(unsigned int line, struct depth_stencil_resource *ds) -{ - ID3D12DescriptorHeap_Release(ds->heap); - ID3D12Resource_Release(ds->texture); -} - static void test_create_device(void) { ID3D12Device *device; @@ -1249,6 +303,22 @@ static void test_check_feature_support(void) 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, +}; + static void test_format_support(void) { D3D12_FEATURE_DATA_FORMAT_SUPPORT format_support; diff --git a/tests/d3d12_crosstest.h b/tests/d3d12_crosstest.h index e6769b1f..5a709783 100644 --- a/tests/d3d12_crosstest.h +++ b/tests/d3d12_crosstest.h @@ -29,7 +29,6 @@ #endif #define COBJMACROS -#define INITGUID #include "vkd3d_test.h" #include "vkd3d_windows.h" #define WIDL_C_INLINE_WRAPPERS @@ -341,7 +340,7 @@ static ID3D12Device *create_device(void) return SUCCEEDED(hr) ? device : NULL; } -static void init_adapter_info(void) +static inline void init_adapter_info(void) { char name[MEMBER_SIZE(DXGI_ADAPTER_DESC, Description)]; IDXGIAdapter *dxgi_adapter; @@ -638,7 +637,7 @@ static bool get_driver_properties(ID3D12Device *device, VkPhysicalDeviceDriverPr return false; } -static void init_adapter_info(void) +static inline void init_adapter_info(void) { VkPhysicalDeviceDriverPropertiesKHR driver_properties; struct vkd3d_instance *instance; @@ -711,7 +710,7 @@ static inline bool is_depth_clip_enable_supported(ID3D12Device *device) } #endif -static void parse_args(int argc, char **argv) +static inline void parse_args(int argc, char **argv) { int i; @@ -724,7 +723,7 @@ static void parse_args(int argc, char **argv) } } -static void enable_d3d12_debug_layer(int argc, char **argv) +static inline void enable_d3d12_debug_layer(int argc, char **argv) { bool enable_debug_layer = false, enable_gpu_based_validation = false; ID3D12Debug1 *debug1; diff --git a/tests/d3d12_test_utils.c b/tests/d3d12_test_utils.c new file mode 100644 index 00000000..5485e860 --- /dev/null +++ b/tests/d3d12_test_utils.c @@ -0,0 +1,952 @@ +/* + * Copyright 2016-2017 Józef Kucia for CodeWeavers + * + * 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" + +PFN_D3D12_CREATE_VERSIONED_ROOT_SIGNATURE_DESERIALIZER pfn_D3D12CreateVersionedRootSignatureDeserializer; +PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE pfn_D3D12SerializeVersionedRootSignature; +PFN_D3D12_CREATE_DEVICE pfn_D3D12CreateDevice; +PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES pfn_D3D12EnableExperimentalFeatures; +PFN_D3D12_GET_DEBUG_INTERFACE pfn_D3D12GetDebugInterface; + +bool compare_float(float f, float g, int ulps) +{ + int x, y; + union + { + float f; + int i; + } u; + + u.f = f; + x = u.i; + u.f = g; + y = u.i; + + if (x < 0) + x = INT_MIN - x; + if (y < 0) + y = INT_MIN - y; + + if (abs(x - y) > ulps) + return false; + + return true; +} + +bool compare_vec4(const struct vec4 *v1, const struct vec4 *v2, unsigned int ulps) +{ + return compare_float(v1->x, v2->x, ulps) + && compare_float(v1->y, v2->y, ulps) + && compare_float(v1->z, v2->z, ulps) + && compare_float(v1->w, v2->w, ulps); +} + +bool compare_uvec4(const struct uvec4* v1, const struct uvec4 *v2) +{ + return v1->x == v2->x && v1->y == v2->y && v1->z == v2->z && v1->w == v2->w; +} + +bool compare_uint8(uint8_t a, uint8_t b, unsigned int max_diff) +{ + return delta_uint8(a, b) <= max_diff; +} + +bool compare_uint16(uint16_t a, uint16_t b, unsigned int max_diff) +{ + return delta_uint16(a, b) <= max_diff; +} + +bool compare_uint64(uint64_t a, uint64_t b, unsigned int max_diff) +{ + return delta_uint64(a, b) <= max_diff; +} + +ULONG get_refcount(void *iface) +{ + IUnknown *unk = iface; + IUnknown_AddRef(unk); + return IUnknown_Release(unk); +} + +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); +} + +void check_heap_properties_(unsigned int line, + const D3D12_HEAP_PROPERTIES *properties, const D3D12_HEAP_PROPERTIES *expected_properties) +{ + D3D12_HEAP_PROPERTIES expected = *expected_properties; + + if (!expected.CreationNodeMask) + expected.CreationNodeMask = 0x1; + if (!expected.VisibleNodeMask) + expected.VisibleNodeMask = 0x1; + + ok_(line)(properties->Type == expected.Type, + "Got type %#x, expected %#x.\n", properties->Type, expected.Type); + ok_(line)(properties->CPUPageProperty == expected.CPUPageProperty, + "Got CPU page properties %#x, expected %#x.\n", + properties->CPUPageProperty, expected.CPUPageProperty); + ok_(line)(properties->MemoryPoolPreference == expected.MemoryPoolPreference, + "Got memory pool %#x, expected %#x.\n", + properties->MemoryPoolPreference, expected.MemoryPoolPreference); + ok_(line)(properties->CreationNodeMask == expected.CreationNodeMask, + "Got creation node mask %#x, expected %#x.\n", + properties->CreationNodeMask, expected.CreationNodeMask); + ok_(line)(properties->VisibleNodeMask == expected.VisibleNodeMask, + "Got visible node mask %#x, expected %#x.\n", + properties->VisibleNodeMask, expected.VisibleNodeMask); +} + +void check_heap_desc_(unsigned int line, const D3D12_HEAP_DESC *desc, + const D3D12_HEAP_DESC *expected_desc) +{ + D3D12_HEAP_DESC expected = *expected_desc; + + if (!expected.Alignment) + expected.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; + + ok_(line)(desc->SizeInBytes == expected.SizeInBytes, + "Got size %"PRIu64", expected %"PRIu64".\n", + desc->SizeInBytes, expected.SizeInBytes); + check_heap_properties_(line, &desc->Properties, &expected.Properties); + ok_(line)(desc->Alignment == expected.Alignment, + "Got alignment %"PRIu64", expected %"PRIu64".\n", + desc->Alignment, expected.Alignment); + ok_(line)(desc->Flags == expected.Flags, + "Got flags %#x, expected %#x.\n", desc->Flags, expected.Flags); +} + +void check_alignment_(unsigned int line, uint64_t size, uint64_t alignment) +{ + uint64_t aligned_size = align(size, alignment); + ok_(line)(aligned_size == size, "Got unaligned size %"PRIu64", expected %"PRIu64".\n", + size, aligned_size); +} + +void uav_barrier(ID3D12GraphicsCommandList *list, ID3D12Resource *resource) +{ + D3D12_RESOURCE_BARRIER barrier; + + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.UAV.pResource = resource; + + ID3D12GraphicsCommandList_ResourceBarrier(list, 1, &barrier); +} + +void copy_sub_resource_data(const D3D12_MEMCPY_DEST *dst, const D3D12_SUBRESOURCE_DATA *src, + unsigned int row_count, unsigned int slice_count, size_t row_size) +{ + const BYTE *src_slice_ptr; + BYTE *dst_slice_ptr; + unsigned int z, y; + + for (z = 0; z < slice_count; ++z) + { + dst_slice_ptr = (BYTE *)dst->pData + z * dst->SlicePitch; + src_slice_ptr = (const BYTE*)src->pData + z * src->SlicePitch; + for (y = 0; y < row_count; ++y) + memcpy(dst_slice_ptr + y * dst->RowPitch, src_slice_ptr + y * src->RowPitch, row_size); + } +} + +void upload_buffer_data_(unsigned int line, ID3D12Resource *buffer, size_t offset, + size_t size, const void *data, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list) +{ + ID3D12Resource *upload_buffer; + ID3D12Device *device; + HRESULT hr; + + hr = ID3D12Resource_GetDevice(buffer, &IID_ID3D12Device, (void **)&device); + ok_(line)(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr); + + upload_buffer = create_upload_buffer_(line, device, size, data); + + ID3D12GraphicsCommandList_CopyBufferRegion(command_list, buffer, offset, + upload_buffer, 0, size); + + hr = ID3D12GraphicsCommandList_Close(command_list); + ok_(line)(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr); + exec_command_list(queue, command_list); + wait_queue_idle(device, queue); + + ID3D12Resource_Release(upload_buffer); + ID3D12Device_Release(device); +} + +void upload_texture_data_(unsigned int line, ID3D12Resource *texture, + const D3D12_SUBRESOURCE_DATA *data, unsigned int sub_resource_count, + ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list) +{ + D3D12_TEXTURE_COPY_LOCATION dst_location, src_location; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts; + uint64_t *row_sizes, required_size; + D3D12_RESOURCE_DESC resource_desc; + ID3D12Resource *upload_buffer; + D3D12_MEMCPY_DEST dst_data; + ID3D12Device *device; + UINT *row_counts; + unsigned int i; + HRESULT hr; + void *ptr; + + layouts = calloc(sub_resource_count, sizeof(*layouts)); + ok(layouts, "Failed to allocate memory.\n"); + row_counts = calloc(sub_resource_count, sizeof(*row_counts)); + ok(row_counts, "Failed to allocate memory.\n"); + row_sizes = calloc(sub_resource_count, sizeof(*row_sizes)); + ok(row_sizes, "Failed to allocate memory.\n"); + + resource_desc = ID3D12Resource_GetDesc(texture); + hr = ID3D12Resource_GetDevice(texture, &IID_ID3D12Device, (void **)&device); + ok_(line)(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr); + + ID3D12Device_GetCopyableFootprints(device, &resource_desc, 0, sub_resource_count, + 0, layouts, row_counts, row_sizes, &required_size); + + upload_buffer = create_upload_buffer_(line, device, required_size, NULL); + + hr = ID3D12Resource_Map(upload_buffer, 0, NULL, (void **)&ptr); + ok_(line)(SUCCEEDED(hr), "Failed to map upload buffer, hr %#x.\n", hr); + for (i = 0; i < sub_resource_count; ++i) + { + dst_data.pData = (BYTE *)ptr + layouts[i].Offset; + dst_data.RowPitch = layouts[i].Footprint.RowPitch; + dst_data.SlicePitch = layouts[i].Footprint.RowPitch * row_counts[i]; + copy_sub_resource_data(&dst_data, &data[i], + row_counts[i], layouts[i].Footprint.Depth, row_sizes[i]); + } + ID3D12Resource_Unmap(upload_buffer, 0, NULL); + + for (i = 0; i < sub_resource_count; ++i) + { + dst_location.pResource = texture; + dst_location.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dst_location.SubresourceIndex = i; + + src_location.pResource = upload_buffer; + src_location.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + src_location.PlacedFootprint = layouts[i]; + + ID3D12GraphicsCommandList_CopyTextureRegion(command_list, + &dst_location, 0, 0, 0, &src_location, NULL); + } + + hr = ID3D12GraphicsCommandList_Close(command_list); + ok_(line)(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr); + + exec_command_list(queue, command_list); + wait_queue_idle(device, queue); + + ID3D12Resource_Release(upload_buffer); + ID3D12Device_Release(device); + + free(layouts); + free(row_counts); + free(row_sizes); +} + +void init_readback(struct resource_readback *rb, ID3D12Resource *buffer, + uint64_t buffer_size, uint64_t width, uint64_t height, unsigned int depth, uint64_t row_pitch) +{ + D3D12_RANGE read_range; + HRESULT hr; + + rb->width = width; + rb->height = height; + rb->depth = depth; + rb->resource = buffer; + rb->row_pitch = row_pitch; + rb->data = NULL; + + ID3D12Resource_AddRef(rb->resource); + + read_range.Begin = 0; + read_range.End = buffer_size; + hr = ID3D12Resource_Map(rb->resource, 0, &read_range, &rb->data); + ok(hr == S_OK, "Failed to map readback buffer, hr %#x.\n", hr); +} + +void get_buffer_readback_with_command_list(ID3D12Resource *buffer, DXGI_FORMAT format, + struct resource_readback *rb, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list) +{ + D3D12_HEAP_PROPERTIES heap_properties; + D3D12_RESOURCE_DESC resource_desc; + ID3D12Resource *rb_buffer; + D3D12_RANGE read_range; + ID3D12Device *device; + HRESULT hr; + + hr = ID3D12Resource_GetDevice(buffer, &IID_ID3D12Device, (void **)&device); + ok(SUCCEEDED(hr), "Failed to get device, hr %#x.\n", hr); + + resource_desc = ID3D12Resource_GetDesc(buffer); + assert(resource_desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER); + resource_desc.Flags = D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE; + + hr = ID3D12Resource_GetHeapProperties(buffer, &heap_properties, NULL); + if (SUCCEEDED(hr) && heap_properties.Type == D3D12_HEAP_TYPE_READBACK) + { + rb_buffer = buffer; + ID3D12Resource_AddRef(rb_buffer); + } + else + { + rb_buffer = create_readback_buffer(device, resource_desc.Width); + ID3D12GraphicsCommandList_CopyBufferRegion(command_list, rb_buffer, 0, + buffer, 0, resource_desc.Width); + } + + hr = ID3D12GraphicsCommandList_Close(command_list); + ok(SUCCEEDED(hr), "Failed to close command list, hr %#x.\n", hr); + + exec_command_list(queue, command_list); + wait_queue_idle(device, queue); + ID3D12Device_Release(device); + + rb->width = resource_desc.Width / format_size(format); + rb->height = 1; + rb->depth = 1; + rb->resource = rb_buffer; + rb->row_pitch = resource_desc.Width; + rb->data = NULL; + + read_range.Begin = 0; + read_range.End = resource_desc.Width; + hr = ID3D12Resource_Map(rb_buffer, 0, &read_range, &rb->data); + ok(SUCCEEDED(hr), "Failed to map readback buffer, hr %#x.\n", hr); +} + +uint8_t get_readback_uint8(struct resource_readback *rb, unsigned int x, unsigned int y) +{ + return *(uint8_t *)get_readback_data(rb, x, y, 0, sizeof(uint8_t)); +} + +uint16_t get_readback_uint16(struct resource_readback *rb, unsigned int x, unsigned int y) +{ + return *(uint16_t *)get_readback_data(rb, x, y, 0, sizeof(uint16_t)); +} + +uint64_t get_readback_uint64(struct resource_readback *rb, unsigned int x, unsigned int y) +{ + return *(uint64_t *)get_readback_data(rb, x, y, 0, sizeof(uint64_t)); +} + +float get_readback_float(struct resource_readback *rb, unsigned int x, unsigned int y) +{ + return *(float *)get_readback_data(rb, x, y, 0, sizeof(float)); +} + +const struct vec4 *get_readback_vec4(struct resource_readback *rb, unsigned int x, unsigned int y) +{ + return get_readback_data(rb, x, y, 0, sizeof(struct vec4)); +} + +const struct uvec4 *get_readback_uvec4(struct resource_readback *rb, unsigned int x, unsigned int y) +{ + return get_readback_data(rb, x, y, 0, sizeof(struct uvec4)); +} + +void check_readback_data_float_(unsigned int line, struct resource_readback *rb, + const RECT *rect, float expected, unsigned int max_diff) +{ + RECT r = {0, 0, rb->width, rb->height}; + int x = 0, y; + bool all_match = true; + float got = 0; + + if (rect) + r = *rect; + + for (y = r.top; y < r.bottom; ++y) + { + for (x = r.left; x < r.right; ++x) + { + got = get_readback_float(rb, x, y); + if (!compare_float(got, expected, max_diff)) + { + all_match = false; + break; + } + } + if (!all_match) + break; + } + ok_(line)(all_match, "Got %.8e, expected %.8e at (%u, %u).\n", got, expected, x, y); +} + +void check_sub_resource_float_(unsigned int line, ID3D12Resource *texture, + unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, + float expected, unsigned int max_diff) +{ + struct resource_readback rb; + + get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); + check_readback_data_float_(line, &rb, NULL, expected, max_diff); + release_resource_readback(&rb); +} + +void check_readback_data_uint8_(unsigned int line, struct resource_readback *rb, + const RECT *rect, uint8_t expected, unsigned int max_diff) +{ + RECT r = {0, 0, rb->width, rb->height}; + int x = 0, y; + bool all_match = true; + uint8_t got = 0; + + if (rect) + r = *rect; + + for (y = r.top; y < r.bottom; ++y) + { + for (x = r.left; x < r.right; ++x) + { + got = get_readback_uint8(rb, x, y); + if (!compare_uint8(got, expected, max_diff)) + { + all_match = false; + break; + } + } + if (!all_match) + break; + } + ok_(line)(all_match, "Got 0x%02x, expected 0x%02x at (%u, %u).\n", got, expected, x, y); +} + +void check_sub_resource_uint8_(unsigned int line, ID3D12Resource *texture, + unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, + uint8_t expected, unsigned int max_diff) +{ + struct resource_readback rb; + + get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); + check_readback_data_uint8_(line, &rb, NULL, expected, max_diff); + release_resource_readback(&rb); +} + +void check_readback_data_uint16_(unsigned int line, struct resource_readback *rb, + const RECT *rect, uint16_t expected, unsigned int max_diff) +{ + RECT r = {0, 0, rb->width, rb->height}; + int x = 0, y; + bool all_match = true; + uint16_t got = 0; + + if (rect) + r = *rect; + + for (y = r.top; y < r.bottom; ++y) + { + for (x = r.left; x < r.right; ++x) + { + got = get_readback_uint16(rb, x, y); + if (!compare_uint16(got, expected, max_diff)) + { + all_match = false; + break; + } + } + if (!all_match) + break; + } + ok_(line)(all_match, "Got 0x%04x, expected 0x%04x at (%u, %u).\n", got, expected, x, y); +} + +void check_sub_resource_uint16_(unsigned int line, ID3D12Resource *texture, + unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, + uint16_t expected, unsigned int max_diff) +{ + struct resource_readback rb; + + get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); + check_readback_data_uint16_(line, &rb, NULL, expected, max_diff); + release_resource_readback(&rb); +} + +void check_readback_data_uint64_(unsigned int line, struct resource_readback *rb, + const RECT *rect, uint64_t expected, unsigned int max_diff) +{ + RECT r = {0, 0, rb->width, rb->height}; + int x = 0, y; + bool all_match = true; + uint64_t got = 0; + + if (rect) + r = *rect; + + for (y = r.top; y < r.bottom; ++y) + { + for (x = r.left; x < r.right; ++x) + { + got = get_readback_uint64(rb, x, y); + if (!compare_uint64(got, expected, max_diff)) + { + all_match = false; + break; + } + } + if (!all_match) + break; + } + ok_(line)(all_match, "Got %#"PRIx64", expected %#"PRIx64" at (%u, %u).\n", got, expected, x, y); +} + +void check_sub_resource_uint64_(unsigned int line, ID3D12Resource *texture, + unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, + uint64_t expected, unsigned int max_diff) +{ + struct resource_readback rb; + + get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); + check_readback_data_uint64_(line, &rb, NULL, expected, max_diff); + release_resource_readback(&rb); +} + +void check_sub_resource_vec4_(unsigned int line, ID3D12Resource *texture, + unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, + const struct vec4 *expected, unsigned int max_diff) +{ + struct resource_readback rb; + unsigned int x = 0, y; + bool all_match = true; + struct vec4 got = {0}; + + get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); + for (y = 0; y < rb.height; ++y) + { + for (x = 0; x < rb.width; ++x) + { + got = *get_readback_vec4(&rb, x, y); + if (!compare_vec4(&got, expected, max_diff)) + { + all_match = false; + break; + } + } + if (!all_match) + break; + } + release_resource_readback(&rb); + + ok_(line)(all_match, "Got {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e} at (%u, %u).\n", + got.x, got.y, got.z, got.w, expected->x, expected->y, expected->z, expected->w, x, y); +} + +void check_sub_resource_uvec4_(unsigned int line, ID3D12Resource *texture, + unsigned int sub_resource_idx, ID3D12CommandQueue *queue, ID3D12GraphicsCommandList *command_list, + const struct uvec4 *expected_value) +{ + struct resource_readback rb; + struct uvec4 value = {0}; + unsigned int x = 0, y; + bool all_match = true; + + get_texture_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); + for (y = 0; y < rb.height; ++y) + { + for (x = 0; x < rb.width; ++x) + { + value = *get_readback_uvec4(&rb, x, y); + if (!compare_uvec4(&value, expected_value)) + { + all_match = false; + break; + } + } + if (!all_match) + break; + } + release_resource_readback(&rb); + + ok_(line)(all_match, + "Got {0x%08x, 0x%08x, 0x%08x, 0x%08x}, expected {0x%08x, 0x%08x, 0x%08x, 0x%08x} at (%u, %u).\n", + value.x, value.y, value.z, value.w, + expected_value->x, expected_value->y, expected_value->z, expected_value->w, x, y); +} + +bool broken_on_warp(bool condition) +{ + return broken(use_warp_device && condition); +} + +bool is_min_max_filtering_supported(ID3D12Device *device) +{ + D3D12_FEATURE_DATA_D3D12_OPTIONS options; + HRESULT hr; + + if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, + D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)))) + { + trace("Failed to check feature support, hr %#x.\n", hr); + return false; + } + + /* D3D12 validation layer says tiled resource tier 2+ support implies min/max filtering support. */ + return options.TiledResourcesTier >= D3D12_TILED_RESOURCES_TIER_2; +} + +D3D12_TILED_RESOURCES_TIER get_tiled_resources_tier(ID3D12Device *device) +{ + D3D12_FEATURE_DATA_D3D12_OPTIONS options; + HRESULT hr; + + if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, + D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)))) + { + trace("Failed to check feature support, hr %#x.\n", hr); + return D3D12_TILED_RESOURCES_TIER_NOT_SUPPORTED; + } + + return options.TiledResourcesTier; +} + +bool is_standard_swizzle_64kb_supported(ID3D12Device *device) +{ + D3D12_FEATURE_DATA_D3D12_OPTIONS options; + HRESULT hr; + + if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, + D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)))) + { + trace("Failed to check feature support, hr %#x.\n", hr); + return false; + } + + return options.StandardSwizzle64KBSupported; +} + +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; +} + +bool is_vrs_tier1_supported(ID3D12Device *device, bool *additional_shading_rates) +{ + D3D12_FEATURE_DATA_D3D12_OPTIONS6 options; + HRESULT hr; + + if (additional_shading_rates) + *additional_shading_rates = false; + + if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, + D3D12_FEATURE_D3D12_OPTIONS6, &options, sizeof(options)))) + { + trace("Failed to check feature support, hr %#x.\n", hr); + return false; + } + + if (additional_shading_rates) + *additional_shading_rates = options.AdditionalShadingRatesSupported; + + return options.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_1; +} + +bool is_vrs_tier2_supported(ID3D12Device *device) +{ + D3D12_FEATURE_DATA_D3D12_OPTIONS6 options; + HRESULT hr; + + if (FAILED(hr = ID3D12Device_CheckFeatureSupport(device, + D3D12_FEATURE_D3D12_OPTIONS6, &options, sizeof(options)))) + { + trace("Failed to check feature support, hr %#x.\n", hr); + return false; + } + return options.VariableShadingRateTier >= D3D12_VARIABLE_SHADING_RATE_TIER_2; +} + +ID3D12RootSignature *create_cb_root_signature_(unsigned int line, + ID3D12Device *device, unsigned int reg_idx, D3D12_SHADER_VISIBILITY shader_visibility, + D3D12_ROOT_SIGNATURE_FLAGS flags) +{ + D3D12_ROOT_SIGNATURE_DESC root_signature_desc; + ID3D12RootSignature *root_signature = NULL; + D3D12_ROOT_PARAMETER root_parameter; + HRESULT hr; + + root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + root_parameter.Descriptor.ShaderRegister = reg_idx; + root_parameter.Descriptor.RegisterSpace = 0; + root_parameter.ShaderVisibility = shader_visibility; + + memset(&root_signature_desc, 0, sizeof(root_signature_desc)); + root_signature_desc.NumParameters = 1; + root_signature_desc.pParameters = &root_parameter; + root_signature_desc.Flags = flags; + hr = create_root_signature(device, &root_signature_desc, &root_signature); + ok_(line)(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr); + + return root_signature; +} + +ID3D12RootSignature *create_32bit_constants_root_signature_(unsigned int line, + ID3D12Device *device, unsigned int reg_idx, unsigned int element_count, + D3D12_SHADER_VISIBILITY shader_visibility, D3D12_ROOT_SIGNATURE_FLAGS flags) +{ + D3D12_ROOT_SIGNATURE_DESC root_signature_desc; + ID3D12RootSignature *root_signature = NULL; + D3D12_ROOT_PARAMETER root_parameter; + HRESULT hr; + + root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + root_parameter.Constants.ShaderRegister = reg_idx; + root_parameter.Constants.RegisterSpace = 0; + root_parameter.Constants.Num32BitValues = element_count; + root_parameter.ShaderVisibility = shader_visibility; + + memset(&root_signature_desc, 0, sizeof(root_signature_desc)); + root_signature_desc.NumParameters = 1; + root_signature_desc.pParameters = &root_parameter; + root_signature_desc.Flags = flags; + hr = create_root_signature(device, &root_signature_desc, &root_signature); + ok_(line)(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr); + + return root_signature; +} + +ID3D12RootSignature *create_texture_root_signature_(unsigned int line, + ID3D12Device *device, D3D12_SHADER_VISIBILITY shader_visibility, + unsigned int constant_count, D3D12_ROOT_SIGNATURE_FLAGS flags, + const D3D12_STATIC_SAMPLER_DESC *sampler_desc) +{ + D3D12_ROOT_SIGNATURE_DESC root_signature_desc; + ID3D12RootSignature *root_signature = NULL; + D3D12_STATIC_SAMPLER_DESC static_sampler; + D3D12_DESCRIPTOR_RANGE descriptor_range; + D3D12_ROOT_PARAMETER root_parameters[2]; + HRESULT hr; + + if (sampler_desc) + { + static_sampler = *sampler_desc; + } + else + { + memset(&static_sampler, 0, sizeof(static_sampler)); + static_sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; + static_sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + static_sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + static_sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + static_sampler.MaxLOD = D3D12_FLOAT32_MAX; + static_sampler.ShaderRegister = 0; + static_sampler.RegisterSpace = 0; + static_sampler.ShaderVisibility = shader_visibility; + } + + descriptor_range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + descriptor_range.NumDescriptors = 1; + descriptor_range.BaseShaderRegister = 0; + descriptor_range.RegisterSpace = 0; + descriptor_range.OffsetInDescriptorsFromTableStart = 0; + root_parameters[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + root_parameters[0].DescriptorTable.NumDescriptorRanges = 1; + root_parameters[0].DescriptorTable.pDescriptorRanges = &descriptor_range; + root_parameters[0].ShaderVisibility = shader_visibility; + + root_parameters[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + root_parameters[1].Constants.ShaderRegister = 0; + root_parameters[1].Constants.RegisterSpace = 0; + root_parameters[1].Constants.Num32BitValues = constant_count; + root_parameters[1].ShaderVisibility = shader_visibility; + + memset(&root_signature_desc, 0, sizeof(root_signature_desc)); + root_signature_desc.NumParameters = constant_count ? 2 : 1; + root_signature_desc.pParameters = root_parameters; + root_signature_desc.NumStaticSamplers = 1; + root_signature_desc.pStaticSamplers = &static_sampler; + root_signature_desc.Flags = flags; + + hr = create_root_signature(device, &root_signature_desc, &root_signature); + ok_(line)(SUCCEEDED(hr), "Failed to create root signature, hr %#x.\n", hr); + + return root_signature; +} + +ID3D12PipelineState *create_compute_pipeline_state_(unsigned int line, ID3D12Device *device, + ID3D12RootSignature *root_signature, const D3D12_SHADER_BYTECODE cs) +{ + D3D12_COMPUTE_PIPELINE_STATE_DESC pipeline_state_desc; + ID3D12PipelineState *pipeline_state = NULL; + HRESULT hr; + + memset(&pipeline_state_desc, 0, sizeof(pipeline_state_desc)); + pipeline_state_desc.pRootSignature = root_signature; + pipeline_state_desc.CS = cs; + 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_(line)(SUCCEEDED(hr), "Failed to create compute pipeline state, hr %#x.\n", hr); + return pipeline_state; +} + +ID3D12CommandSignature *create_command_signature_(unsigned int line, + ID3D12Device *device, D3D12_INDIRECT_ARGUMENT_TYPE argument_type) +{ + ID3D12CommandSignature *command_signature = NULL; + D3D12_COMMAND_SIGNATURE_DESC signature_desc; + D3D12_INDIRECT_ARGUMENT_DESC argument_desc; + HRESULT hr; + + argument_desc.Type = argument_type; + + switch (argument_type) + { + case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW: + signature_desc.ByteStride = sizeof(D3D12_DRAW_ARGUMENTS); + break; + case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED: + signature_desc.ByteStride = sizeof(D3D12_DRAW_INDEXED_ARGUMENTS); + break; + case D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH: + signature_desc.ByteStride = sizeof(D3D12_DISPATCH_ARGUMENTS); + break; + default: + return NULL; + } + + signature_desc.NumArgumentDescs = 1; + signature_desc.pArgumentDescs = &argument_desc; + signature_desc.NodeMask = 0; + hr = ID3D12Device_CreateCommandSignature(device, &signature_desc, + NULL, &IID_ID3D12CommandSignature, (void **)&command_signature); + ok_(line)(hr == S_OK, "Failed to create command signature, hr %#x.\n", hr); + + return command_signature; +} + +bool init_compute_test_context_(unsigned int line, struct test_context *context) +{ + ID3D12Device *device; + HRESULT hr; + + memset(context, 0, sizeof(*context)); + + if (!(context->device = create_device())) + { + skip_(line)("Failed to create device.\n"); + return false; + } + device = context->device; + + context->queue = create_command_queue_(line, device, + D3D12_COMMAND_LIST_TYPE_COMPUTE, D3D12_COMMAND_QUEUE_PRIORITY_NORMAL); + + hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_COMPUTE, + &IID_ID3D12CommandAllocator, (void **)&context->allocator); + ok_(line)(hr == S_OK, "Failed to create command allocator, hr %#x.\n", hr); + + hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_COMPUTE, + context->allocator, NULL, &IID_ID3D12GraphicsCommandList, (void **)&context->list); + ok_(line)(hr == S_OK, "Failed to create command list, hr %#x.\n", hr); + + return true; +} + +bool context_supports_dxil_(unsigned int line, struct test_context *context) +{ + D3D12_FEATURE_DATA_SHADER_MODEL model; + HRESULT hr; + model.HighestShaderModel = D3D_SHADER_MODEL_6_0; + hr = ID3D12Device_CheckFeatureSupport(context->device, D3D12_FEATURE_SHADER_MODEL, &model, sizeof(model)); + ok_(line)(hr == S_OK, "Failed to query shader model support, hr %#x.\n", hr); + + if (hr != S_OK) + return false; + + if (model.HighestShaderModel < D3D_SHADER_MODEL_6_0) + { + skip_(line)("Device does not support shader model 6.0, skipping DXIL tests.\n"); + return false; + } + else + return true; +} + +void init_depth_stencil_(unsigned int line, struct depth_stencil_resource *ds, + ID3D12Device *device, unsigned int width, unsigned int height, unsigned int array_size, unsigned int level_count, + DXGI_FORMAT format, DXGI_FORMAT view_format, const D3D12_CLEAR_VALUE *clear_value) +{ + D3D12_DEPTH_STENCIL_VIEW_DESC dsv_desc, *view_desc; + D3D12_HEAP_PROPERTIES heap_properties; + D3D12_RESOURCE_DESC resource_desc; + HRESULT hr; + + memset(ds, 0, sizeof(*ds)); + + ds->heap = create_cpu_descriptor_heap(device, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1); + + 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 = width; + resource_desc.Height = height; + resource_desc.DepthOrArraySize = array_size; + resource_desc.MipLevels = level_count; + resource_desc.Format = format; + resource_desc.SampleDesc.Count = 1; + resource_desc.SampleDesc.Quality = 0; + resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + resource_desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; + hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE, + &resource_desc, D3D12_RESOURCE_STATE_DEPTH_WRITE, clear_value, + &IID_ID3D12Resource, (void **)&ds->texture); + ok_(line)(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); + + view_desc = NULL; + if (view_format) + { + memset(&dsv_desc, 0, sizeof(dsv_desc)); + dsv_desc.Format = view_format; + dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; + view_desc = &dsv_desc; + } + ds->dsv_handle = ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(ds->heap); + ID3D12Device_CreateDepthStencilView(device, ds->texture, view_desc, ds->dsv_handle); +} + +void destroy_depth_stencil_(unsigned int line, struct depth_stencil_resource *ds) +{ + ID3D12DescriptorHeap_Release(ds->heap); + ID3D12Resource_Release(ds->texture); +} diff --git a/tests/descriptor_performance.c b/tests/descriptor_performance.c index c92885a0..b548cc81 100644 --- a/tests/descriptor_performance.c +++ b/tests/descriptor_performance.c @@ -18,14 +18,10 @@ #define VKD3D_DBG_CHANNEL VKD3D_DBG_CHANNEL_API +#define INITGUID +#define VKD3D_TEST_DECLARE_MAIN #include "d3d12_crosstest.h" -PFN_D3D12_CREATE_VERSIONED_ROOT_SIGNATURE_DESERIALIZER pfn_D3D12CreateVersionedRootSignatureDeserializer; -PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE pfn_D3D12SerializeVersionedRootSignature; -PFN_D3D12_CREATE_DEVICE pfn_D3D12CreateDevice; -PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES pfn_D3D12EnableExperimentalFeatures; -PFN_D3D12_GET_DEBUG_INTERFACE pfn_D3D12GetDebugInterface; - static void setup(int argc, char **argv) { pfn_D3D12CreateDevice = get_d3d12_pfn(D3D12CreateDevice); diff --git a/tests/meson.build b/tests/meson.build index 816e2034..be135bde 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -11,16 +11,23 @@ else vkd3d_test_deps = [ vkd3d_dep, vkd3d_utils_dep ] endif +d3d12_test_utils_lib = static_library('d3d12-test-utils', 'd3d12_test_utils.c', + dependencies : vkd3d_test_deps, + include_directories : vkd3d_private_includes, + override_options : [ 'c_std='+vkd3d_c_std ]) + executable('d3d12', 'd3d12.c', dependencies : vkd3d_test_deps, include_directories : vkd3d_private_includes, install : false, c_args : vkd3d_test_flags, - override_options : [ 'c_std='+vkd3d_c_std ]) + override_options : [ 'c_std='+vkd3d_c_std ], + link_with : [ d3d12_test_utils_lib ]) executable('descriptor-performance', 'descriptor_performance.c', dependencies : vkd3d_test_deps, include_directories : vkd3d_private_includes, install : false, c_args : vkd3d_test_flags, - override_options : [ 'c_std='+vkd3d_c_std ]) + override_options : [ 'c_std='+vkd3d_c_std ], + link_with : [ d3d12_test_utils_lib ])