vkd3d: Add support for VK_KHR_image_format_list.

Signed-off-by: Józef Kucia <jkucia@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Józef Kucia 2019-08-05 18:03:37 +02:00 committed by Alexandre Julliard
parent 740db732fc
commit 0184917520
4 changed files with 280 additions and 13 deletions

View File

@ -124,6 +124,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] =
VK_EXTENSION(KHR_DEDICATED_ALLOCATION, KHR_dedicated_allocation),
VK_EXTENSION(KHR_DRAW_INDIRECT_COUNT, KHR_draw_indirect_count),
VK_EXTENSION(KHR_GET_MEMORY_REQUIREMENTS_2, KHR_get_memory_requirements2),
VK_EXTENSION(KHR_IMAGE_FORMAT_LIST, KHR_image_format_list),
VK_EXTENSION(KHR_MAINTENANCE3, KHR_maintenance3),
VK_EXTENSION(KHR_PUSH_DESCRIPTOR, KHR_push_descriptor),
/* EXT extensions */
@ -1989,7 +1990,7 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device *iface)
vkd3d_private_store_destroy(&device->private_store);
vkd3d_cleanup_depth_stencil_formats(device);
vkd3d_cleanup_format_info(device);
vkd3d_destroy_null_resources(&device->null_resources, device);
vkd3d_gpu_va_allocator_cleanup(&device->gpu_va_allocator);
vkd3d_render_pass_cache_cleanup(&device->render_pass_cache, device);
@ -3218,11 +3219,11 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
if (FAILED(hr = vkd3d_fence_worker_start(&device->fence_worker, device)))
goto out_free_private_store;
if (FAILED(hr = vkd3d_init_depth_stencil_formats(device)))
if (FAILED(hr = vkd3d_init_format_info(device)))
goto out_stop_fence_worker;
if (FAILED(hr = vkd3d_init_null_resources(&device->null_resources, device)))
goto out_cleanup_depth_stencil_formats;
goto out_cleanup_format_info;
vkd3d_render_pass_cache_init(&device->render_pass_cache);
vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator);
@ -3232,8 +3233,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
return S_OK;
out_cleanup_depth_stencil_formats:
vkd3d_cleanup_depth_stencil_formats(device);
out_cleanup_format_info:
vkd3d_cleanup_format_info(device);
out_stop_fence_worker:
vkd3d_fence_worker_stop(&device->fence_worker, device);
out_free_private_store:

View File

@ -781,12 +781,28 @@ static unsigned int max_miplevel_count(const D3D12_RESOURCE_DESC *desc)
return vkd3d_log2i(size) + 1;
}
static const struct vkd3d_format_compatibility_list *vkd3d_get_format_compatibility_list(
const struct d3d12_device *device, DXGI_FORMAT dxgi_format)
{
unsigned int i;
for (i = 0; i < device->format_compatibility_list_count; ++i)
{
if (device->format_compatibility_lists[i].typeless_format == dxgi_format)
return &device->format_compatibility_lists[i];
}
return NULL;
}
static HRESULT vkd3d_create_image(struct d3d12_device *device,
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
const D3D12_RESOURCE_DESC *desc, VkImage *vk_image)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
const struct vkd3d_format_compatibility_list *compat_list;
const bool sparse_resource = !heap_properties;
VkImageFormatListCreateInfoKHR format_list;
const struct vkd3d_format *format;
VkImageCreateInfo image_info;
VkResult vr;
@ -801,7 +817,21 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device,
image_info.pNext = NULL;
image_info.flags = 0;
if (!(desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) && format->type == VKD3D_FORMAT_TYPE_TYPELESS)
{
image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
/* Format compatibility rules are more relaxed for UAVs. */
if (!(desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
&& (compat_list = vkd3d_get_format_compatibility_list(device, desc->Format)))
{
format_list.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR;
format_list.pNext = NULL;
format_list.viewFormatCount = compat_list->format_count;
format_list.pViewFormats = compat_list->vk_formats;
image_info.pNext = &format_list;
}
}
if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D
&& desc->Width == desc->Height && desc->DepthOrArraySize >= 6
&& desc->SampleDesc.Count == 1)

View File

@ -139,7 +139,213 @@ static const struct vkd3d_format vkd3d_depth_stencil_formats[] =
#undef SINT
#undef UINT
HRESULT vkd3d_init_depth_stencil_formats(struct d3d12_device *device)
static const struct vkd3d_format_compatibility_info
{
DXGI_FORMAT format;
DXGI_FORMAT typeless_format;
}
vkd3d_format_compatibility_info[] =
{
/* DXGI_FORMAT_R32G32B32A32_TYPELESS */
{DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_TYPELESS},
{DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_TYPELESS},
{DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_TYPELESS},
/* DXGI_FORMAT_R32G32B32_TYPELESS */
{DXGI_FORMAT_R32G32B32_UINT, DXGI_FORMAT_R32G32B32_TYPELESS},
{DXGI_FORMAT_R32G32B32_SINT, DXGI_FORMAT_R32G32B32_TYPELESS},
{DXGI_FORMAT_R32G32B32_FLOAT, DXGI_FORMAT_R32G32B32_TYPELESS},
/* DXGI_FORMAT_R16G16B16A16_TYPELESS */
{DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_TYPELESS},
{DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_TYPELESS},
{DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_TYPELESS},
{DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_TYPELESS},
{DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_TYPELESS},
/* DXGI_FORMAT_R32G32_TYPELESS */
{DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_TYPELESS},
{DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_TYPELESS},
{DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_TYPELESS},
/* DXGI_FORMAT_R32G8X24_TYPELESS */
{DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_R32G8X24_TYPELESS},
{DXGI_FORMAT_X32_TYPELESS_G8X24_UINT, DXGI_FORMAT_R32G8X24_TYPELESS},
{DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32G8X24_TYPELESS},
/* DXGI_FORMAT_R10G10B10A2_TYPELESS */
{DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_TYPELESS},
{DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_TYPELESS},
/* DXGI_FORMAT_R8G8B8A8_TYPELESS */
{DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_TYPELESS},
{DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_TYPELESS},
{DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS},
{DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_TYPELESS},
{DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS},
/* DXGI_FORMAT_R16G16_TYPELESS */
{DXGI_FORMAT_R16G16_UNORM, DXGI_FORMAT_R16G16_TYPELESS},
{DXGI_FORMAT_R16G16_SNORM, DXGI_FORMAT_R16G16_TYPELESS},
{DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_TYPELESS},
{DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_TYPELESS},
{DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_TYPELESS},
/* DXGI_FORMAT_R32_TYPELESS */
{DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_TYPELESS},
{DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS},
{DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_TYPELESS},
{DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_TYPELESS},
/* DXGI_FORMAT_R24G8_TYPELESS */
{DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_R24G8_TYPELESS},
{DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_R24G8_TYPELESS},
{DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_R24G8_TYPELESS},
/* DXGI_FORMAT_R8G8_TYPELESS */
{DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_TYPELESS},
{DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_TYPELESS},
{DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_TYPELESS},
{DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_TYPELESS},
/* DXGI_FORMAT_R16_TYPELESS */
{DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_R16_TYPELESS},
{DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_TYPELESS},
{DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16_TYPELESS},
{DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_TYPELESS},
{DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_TYPELESS},
{DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_TYPELESS},
/* DXGI_FORMAT_R8_TYPELESS */
{DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_TYPELESS},
{DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_TYPELESS},
{DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_TYPELESS},
{DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_TYPELESS},
/* DXGI_FORMAT_BC1_TYPELESS */
{DXGI_FORMAT_BC1_UNORM_SRGB, DXGI_FORMAT_BC1_TYPELESS},
{DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_TYPELESS},
/* DXGI_FORMAT_BC2_TYPELESS */
{DXGI_FORMAT_BC2_UNORM_SRGB, DXGI_FORMAT_BC2_TYPELESS},
{DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_TYPELESS},
/* DXGI_FORMAT_BC3_TYPELESS */
{DXGI_FORMAT_BC3_UNORM_SRGB, DXGI_FORMAT_BC3_TYPELESS},
{DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_TYPELESS},
/* DXGI_FORMAT_BC4_TYPELESS */
{DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_TYPELESS},
{DXGI_FORMAT_BC4_SNORM, DXGI_FORMAT_BC4_TYPELESS},
/* DXGI_FORMAT_BC5_TYPELESS */
{DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_TYPELESS},
{DXGI_FORMAT_BC5_SNORM, DXGI_FORMAT_BC5_TYPELESS},
/* DXGI_FORMAT_BC6H_TYPELESS */
{DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_TYPELESS},
{DXGI_FORMAT_BC6H_SF16, DXGI_FORMAT_BC6H_TYPELESS},
/* DXGI_FORMAT_BC7_TYPELESS */
{DXGI_FORMAT_BC7_UNORM_SRGB, DXGI_FORMAT_BC7_TYPELESS},
{DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_TYPELESS},
/* DXGI_FORMAT_B8G8R8A8_TYPELESS */
{DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_B8G8R8A8_TYPELESS},
{DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_TYPELESS},
/* DXGI_FORMAT_B8G8R8X8_TYPELESS */
{DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, DXGI_FORMAT_B8G8R8X8_TYPELESS},
{DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8X8_TYPELESS},
};
static bool dxgi_format_is_depth_stencil(DXGI_FORMAT dxgi_format)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(vkd3d_formats); ++i)
{
const struct vkd3d_format *current = &vkd3d_formats[i];
if (current->dxgi_format == dxgi_format)
return current->vk_aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
}
for (i = 0; i < ARRAY_SIZE(vkd3d_depth_stencil_formats); ++i)
{
if (vkd3d_depth_stencil_formats[i].dxgi_format == dxgi_format)
return true;
}
return false;
}
/* FIXME: This table should be generated at compile-time. */
static HRESULT vkd3d_init_format_compatibility_lists(struct d3d12_device *device)
{
struct vkd3d_format_compatibility_list *lists, *current_list;
const struct vkd3d_format_compatibility_info *current;
DXGI_FORMAT dxgi_format;
VkFormat vk_format;
unsigned int count;
unsigned int i, j;
device->format_compatibility_list_count = 0;
device->format_compatibility_lists = NULL;
if (!device->vk_info.KHR_image_format_list)
return S_OK;
count = 1;
dxgi_format = vkd3d_format_compatibility_info[0].typeless_format;
for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i)
{
DXGI_FORMAT typeless_format = vkd3d_format_compatibility_info[i].typeless_format;
if (dxgi_format != typeless_format)
{
++count;
dxgi_format = typeless_format;
}
}
if (!(lists = vkd3d_calloc(count, sizeof(*lists))))
return E_OUTOFMEMORY;
count = 0;
current_list = lists;
current_list->typeless_format = vkd3d_format_compatibility_info[0].typeless_format;
for (i = 0; i < ARRAY_SIZE(vkd3d_format_compatibility_info); ++i)
{
current = &vkd3d_format_compatibility_info[i];
if (current_list->typeless_format != current->typeless_format)
{
/* Avoid empty format lists. */
if (current_list->format_count)
{
++current_list;
++count;
}
current_list->typeless_format = current->typeless_format;
}
/* In Vulkan, each depth-stencil format is only compatible with itself. */
if (dxgi_format_is_depth_stencil(current->format))
continue;
if (!(vk_format = vkd3d_get_vk_format(current->format)))
continue;
for (j = 0; j < current_list->format_count; ++j)
{
if (current_list->vk_formats[j] == vk_format)
break;
}
if (j >= current_list->format_count)
{
assert(current_list->format_count < VKD3D_MAX_COMPATIBLE_FORMAT_COUNT);
current_list->vk_formats[current_list->format_count++] = vk_format;
}
}
if (current_list->format_count)
++count;
device->format_compatibility_list_count = count;
device->format_compatibility_lists = lists;
return S_OK;
}
static void vkd3d_cleanup_format_compatibility_lists(struct d3d12_device *device)
{
vkd3d_free((void *)device->format_compatibility_lists);
device->format_compatibility_lists = NULL;
device->format_compatibility_list_count = 0;
}
static HRESULT vkd3d_init_depth_stencil_formats(struct d3d12_device *device)
{
const unsigned int count = ARRAY_SIZE(vkd3d_depth_stencil_formats);
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
@ -178,7 +384,7 @@ HRESULT vkd3d_init_depth_stencil_formats(struct d3d12_device *device)
return S_OK;
}
void vkd3d_cleanup_depth_stencil_formats(struct d3d12_device *device)
static void vkd3d_cleanup_depth_stencil_formats(struct d3d12_device *device)
{
if (vkd3d_depth_stencil_formats != device->depth_stencil_formats)
vkd3d_free((void *)device->depth_stencil_formats);
@ -186,6 +392,25 @@ void vkd3d_cleanup_depth_stencil_formats(struct d3d12_device *device)
device->depth_stencil_formats = NULL;
}
HRESULT vkd3d_init_format_info(struct d3d12_device *device)
{
HRESULT hr;
if (FAILED(hr = vkd3d_init_depth_stencil_formats(device)))
return hr;
if FAILED(hr = vkd3d_init_format_compatibility_lists(device))
vkd3d_cleanup_depth_stencil_formats(device);
return hr;
}
void vkd3d_cleanup_format_info(struct d3d12_device *device)
{
vkd3d_cleanup_depth_stencil_formats(device);
vkd3d_cleanup_format_compatibility_lists(device);
}
/* We use overrides for depth/stencil formats. This is required in order to
* properly support typeless formats because depth/stencil formats are only
* compatible with themselves in Vulkan.

View File

@ -48,10 +48,11 @@
#define VKD3D_DESCRIPTOR_MAGIC_DSV 0x00565344u
#define VKD3D_DESCRIPTOR_MAGIC_RTV 0x00565452u
#define VKD3D_MAX_QUEUE_FAMILY_COUNT 3u
#define VKD3D_MAX_SHADER_EXTENSIONS 1u
#define VKD3D_MAX_SHADER_STAGES 5u
#define VKD3D_MAX_VK_SYNC_OBJECTS 4u
#define VKD3D_MAX_COMPATIBLE_FORMAT_COUNT 6u
#define VKD3D_MAX_QUEUE_FAMILY_COUNT 3u
#define VKD3D_MAX_SHADER_EXTENSIONS 1u
#define VKD3D_MAX_SHADER_STAGES 5u
#define VKD3D_MAX_VK_SYNC_OBJECTS 4u
struct d3d12_command_list;
struct d3d12_device;
@ -96,6 +97,7 @@ struct vkd3d_vulkan_info
bool KHR_dedicated_allocation;
bool KHR_draw_indirect_count;
bool KHR_get_memory_requirements2;
bool KHR_image_format_list;
bool KHR_maintenance3;
bool KHR_push_descriptor;
/* EXT device extensions */
@ -1029,6 +1031,13 @@ HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources,
void vkd3d_destroy_null_resources(struct vkd3d_null_resources *null_resources,
struct d3d12_device *device) DECLSPEC_HIDDEN;
struct vkd3d_format_compatibility_list
{
DXGI_FORMAT typeless_format;
unsigned int format_count;
VkFormat vk_formats[VKD3D_MAX_COMPATIBLE_FORMAT_COUNT];
};
/* ID3D12Device */
struct d3d12_device
{
@ -1070,6 +1079,8 @@ struct d3d12_device
HRESULT removed_reason;
const struct vkd3d_format *depth_stencil_formats;
unsigned int format_compatibility_list_count;
const struct vkd3d_format_compatibility_list *format_compatibility_lists;
struct vkd3d_null_resources null_resources;
};
@ -1133,8 +1144,8 @@ static inline bool vkd3d_format_is_compressed(const struct vkd3d_format *format)
const struct vkd3d_format *vkd3d_get_format(const struct d3d12_device *device,
DXGI_FORMAT dxgi_format, bool depth_stencil) DECLSPEC_HIDDEN;
HRESULT vkd3d_init_depth_stencil_formats(struct d3d12_device *device) DECLSPEC_HIDDEN;
void vkd3d_cleanup_depth_stencil_formats(struct d3d12_device *device) DECLSPEC_HIDDEN;
HRESULT vkd3d_init_format_info(struct d3d12_device *device) DECLSPEC_HIDDEN;
void vkd3d_cleanup_format_info(struct d3d12_device *device) DECLSPEC_HIDDEN;
static inline const struct vkd3d_format *vkd3d_format_from_d3d12_resource_desc(
const struct d3d12_device *device, const D3D12_RESOURCE_DESC *desc, DXGI_FORMAT view_format)