vkd3d: Use vkGetDeviceImageMemoryRequirementsKHR in vkd3d_get_image_allocation_info.

Signed-off-by: Philip Rebohle <philip.rebohle@tu-dortmund.de>
This commit is contained in:
Philip Rebohle 2022-04-21 16:24:53 +02:00 committed by Hans-Kristian Arntzen
parent beb58f8472
commit d5ad5bb1de
1 changed files with 108 additions and 78 deletions

View File

@ -484,19 +484,26 @@ static bool vkd3d_format_check_usage_support(struct d3d12_device *device, VkForm
return (supported_flags & required_flags) == required_flags;
}
static HRESULT vkd3d_create_image(struct d3d12_device *device,
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
const D3D12_RESOURCE_DESC1 *desc, struct d3d12_resource *resource, VkImage *vk_image)
struct vkd3d_image_create_info
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
struct vkd3d_format_compatibility_list compat_list;
const bool sparse_resource = !heap_properties;
struct vkd3d_format_compatibility_list format_compat_list;
VkImageFormatListCreateInfoKHR format_list;
const struct vkd3d_format *format;
VkImageCreateInfo image_info;
};
static HRESULT vkd3d_get_image_create_info(struct d3d12_device *device,
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
const D3D12_RESOURCE_DESC1 *desc, struct d3d12_resource *resource,
struct vkd3d_image_create_info *create_info)
{
struct vkd3d_format_compatibility_list *compat_list = &create_info->format_compat_list;
VkImageFormatListCreateInfoKHR *format_list = &create_info->format_list;
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
VkImageCreateInfo *image_info = &create_info->image_info;
const bool sparse_resource = !heap_properties;
const struct vkd3d_format *format;
bool use_concurrent;
unsigned int i;
VkResult vr;
if (!resource)
{
@ -511,32 +518,32 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device,
format = resource->format;
}
image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
image_info.pNext = NULL;
image_info.flags = 0;
image_info->sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
image_info->pNext = NULL;
image_info->flags = 0;
if (!(desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL))
{
if (vkd3d_get_format_compatibility_list(device, desc, &compat_list))
if (vkd3d_get_format_compatibility_list(device, desc, compat_list))
{
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;
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;
image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
image_info->pNext = format_list;
image_info->flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
}
}
if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D
&& desc->Width == desc->Height && desc->DepthOrArraySize >= 6
&& desc->SampleDesc.Count == 1)
image_info.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
image_info->flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
image_info.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
image_info->flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
if (sparse_resource)
{
image_info.flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT |
image_info->flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT |
VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT |
VK_IMAGE_CREATE_SPARSE_ALIASED_BIT;
@ -560,24 +567,24 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device,
}
}
image_info.imageType = vk_image_type_from_d3d12_resource_dimension(desc->Dimension);
image_info.format = format->vk_format;
image_info.extent.width = desc->Width;
image_info.extent.height = desc->Height;
image_info->imageType = vk_image_type_from_d3d12_resource_dimension(desc->Dimension);
image_info->format = format->vk_format;
image_info->extent.width = desc->Width;
image_info->extent.height = desc->Height;
if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
{
image_info.extent.depth = desc->DepthOrArraySize;
image_info.arrayLayers = 1;
image_info->extent.depth = desc->DepthOrArraySize;
image_info->arrayLayers = 1;
}
else
{
image_info.extent.depth = 1;
image_info.arrayLayers = desc->DepthOrArraySize;
image_info->extent.depth = 1;
image_info->arrayLayers = desc->DepthOrArraySize;
}
image_info.mipLevels = min(desc->MipLevels, max_miplevel_count(desc));
image_info.samples = vk_samples_from_dxgi_sample_desc(&desc->SampleDesc);
image_info->mipLevels = min(desc->MipLevels, max_miplevel_count(desc));
image_info->samples = vk_samples_from_dxgi_sample_desc(&desc->SampleDesc);
if (sparse_resource)
{
@ -587,15 +594,15 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device,
return E_INVALIDARG;
}
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info->tiling = VK_IMAGE_TILING_OPTIMAL;
}
else if (desc->Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || desc->Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE)
{
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info->tiling = VK_IMAGE_TILING_OPTIMAL;
}
else if (desc->Layout == D3D12_TEXTURE_LAYOUT_ROW_MAJOR)
{
image_info.tiling = VK_IMAGE_TILING_LINEAR;
image_info->tiling = VK_IMAGE_TILING_LINEAR;
}
else
{
@ -603,26 +610,26 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device,
return E_NOTIMPL;
}
image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
image_info->usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
image_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_info->usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
image_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
image_info->usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
if (desc->Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS)
image_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
image_info->usage |= VK_IMAGE_USAGE_STORAGE_BIT;
if (!(desc->Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE))
image_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
image_info->usage |= VK_IMAGE_USAGE_SAMPLED_BIT;
/* Additional usage flags for shader-based copies */
if (vkd3d_format_allows_shader_copies(format->dxgi_format))
{
image_info.usage |= (format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
image_info->usage |= (format->vk_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT)
? VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
: VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
}
if (vkd3d_resource_can_be_vrs(device, heap_properties, desc))
image_info.usage |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
image_info->usage |= VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
use_concurrent = !!(device->unique_queue_mask & (device->unique_queue_mask - 1));
@ -642,61 +649,61 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device,
{
/* For multi-queue, we have to use CONCURRENT since D3D does
* not give us enough information to do ownership transfers. */
image_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
image_info.queueFamilyIndexCount = device->queue_family_count;
image_info.pQueueFamilyIndices = device->queue_family_indices;
image_info->sharingMode = VK_SHARING_MODE_CONCURRENT;
image_info->queueFamilyIndexCount = device->queue_family_count;
image_info->pQueueFamilyIndices = device->queue_family_indices;
}
else
{
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
image_info.queueFamilyIndexCount = 0;
image_info.pQueueFamilyIndices = NULL;
image_info->sharingMode = VK_SHARING_MODE_EXCLUSIVE;
image_info->queueFamilyIndexCount = 0;
image_info->pQueueFamilyIndices = NULL;
}
if (heap_properties && is_cpu_accessible_heap(heap_properties))
{
image_info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
image_info->initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
/* Required for ReadFromSubresource(). */
image_info.tiling = VK_IMAGE_TILING_LINEAR;
image_info->tiling = VK_IMAGE_TILING_LINEAR;
if ((vkd3d_config_flags & VKD3D_CONFIG_FLAG_IGNORE_RTV_HOST_VISIBLE) &&
(image_info.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
(image_info->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
{
WARN("Workaround applied. Ignoring RTV on linear resources.\n");
image_info.usage &= ~VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_info->usage &= ~VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
if (resource)
resource->desc.Flags &= ~D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
}
}
else
{
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_info->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
}
if ((image_info.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
!vkd3d_format_check_usage_support(device, format->vk_format, image_info.usage, image_info.tiling))
image_info.flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
if ((image_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
!vkd3d_format_check_usage_support(device, format->vk_format, image_info->usage, image_info->tiling))
image_info->flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
if (image_info.tiling == VK_IMAGE_TILING_LINEAR)
if (image_info->tiling == VK_IMAGE_TILING_LINEAR)
{
bool supported = vkd3d_is_linear_tiling_supported(device, &image_info);
bool supported = vkd3d_is_linear_tiling_supported(device, image_info);
/* Apparently NV drivers do not support EXTENDED_USAGE_BIT on linear images? */
if (!supported && (image_info.flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT))
if (!supported && (image_info->flags & VK_IMAGE_CREATE_EXTENDED_USAGE_BIT))
{
WARN("Linear image not supported, attempting without EXTENDED_USAGE as a workaround ...\n");
image_info.flags &= ~VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
supported = vkd3d_is_linear_tiling_supported(device, &image_info);
image_info->flags &= ~VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
supported = vkd3d_is_linear_tiling_supported(device, image_info);
}
if (!supported)
{
WARN("Linear image not supported, forcing OPTIMAL tiling ...\n");
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info->tiling = VK_IMAGE_TILING_OPTIMAL;
if ((image_info.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
!vkd3d_format_check_usage_support(device, format->vk_format, image_info.usage, image_info.tiling))
image_info.flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
if ((image_info->flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) &&
!vkd3d_format_check_usage_support(device, format->vk_format, image_info->usage, image_info->tiling))
image_info->flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
}
}
@ -708,14 +715,14 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device,
// D3D12 only allows sparse images with one aspect, so we can only
// get one struct for metadata aspect and one for the data aspect
VK_CALL(vkGetPhysicalDeviceSparseImageFormatProperties(
device->vk_physical_device, image_info.format,
image_info.imageType, image_info.samples, image_info.usage,
image_info.tiling, &sparse_info_count, sparse_infos));
device->vk_physical_device, image_info->format,
image_info->imageType, image_info->samples, image_info->usage,
image_info->tiling, &sparse_info_count, sparse_infos));
if (!sparse_info_count)
{
ERR("Sparse images not supported with format %u, type %u, samples %u, usage %#x, tiling %u.\n",
image_info.format, image_info.imageType, image_info.samples, image_info.usage, image_info.tiling);
image_info->format, image_info->imageType, image_info->samples, image_info->usage, image_info->tiling);
return E_INVALIDARG;
}
@ -734,7 +741,7 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device,
if (resource)
{
if (image_info.tiling == VK_IMAGE_TILING_LINEAR)
if (image_info->tiling == VK_IMAGE_TILING_LINEAR)
{
resource->flags |= VKD3D_RESOURCE_LINEAR_TILING;
resource->common_layout = VK_IMAGE_LAYOUT_GENERAL;
@ -746,7 +753,23 @@ static HRESULT vkd3d_create_image(struct d3d12_device *device,
resource->flags |= VKD3D_RESOURCE_SIMULTANEOUS_ACCESS;
}
if ((vr = VK_CALL(vkCreateImage(device->vk_device, &image_info, NULL, vk_image))) < 0)
return S_OK;
}
static HRESULT vkd3d_create_image(struct d3d12_device *device,
const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
const D3D12_RESOURCE_DESC1 *desc, struct d3d12_resource *resource, VkImage *vk_image)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
struct vkd3d_image_create_info create_info;
VkResult vr;
HRESULT hr;
if (FAILED(hr = vkd3d_get_image_create_info(device, heap_properties,
heap_flags, desc, resource, &create_info)))
return hr;
if ((vr = VK_CALL(vkCreateImage(device->vk_device, &create_info.image_info, NULL, vk_image))) < 0)
WARN("Failed to create Vulkan image, vr %d.\n", vr);
return hresult_from_vk_result(vr);
@ -757,10 +780,11 @@ HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device,
{
static const D3D12_HEAP_PROPERTIES heap_properties = {D3D12_HEAP_TYPE_DEFAULT};
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
VkDeviceImageMemoryRequirementsKHR requirement_info;
struct vkd3d_image_create_info create_info;
D3D12_RESOURCE_DESC1 validated_desc;
VkMemoryRequirements requirements;
VkMemoryRequirements2 requirements;
VkDeviceSize target_alignment;
VkImage vk_image;
HRESULT hr;
assert(desc->Dimension != D3D12_RESOURCE_DIMENSION_BUFFER);
@ -773,15 +797,21 @@ HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device,
desc = &validated_desc;
}
/* XXX: We have to create an image to get its memory requirements. */
if (FAILED(hr = vkd3d_create_image(device, &heap_properties, 0, desc, NULL, &vk_image)))
if (FAILED(hr = vkd3d_get_image_create_info(device, &heap_properties, 0, desc, NULL, &create_info)))
return hr;
VK_CALL(vkGetImageMemoryRequirements(device->vk_device, vk_image, &requirements));
VK_CALL(vkDestroyImage(device->vk_device, vk_image, NULL));
requirement_info.sType = VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR;
requirement_info.pNext = NULL;
requirement_info.pCreateInfo = &create_info.image_info;
requirement_info.planeAspect = 0; /* irrelevant for us */
allocation_info->SizeInBytes = requirements.size;
allocation_info->Alignment = requirements.alignment;
requirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
requirements.pNext = NULL;
VK_CALL(vkGetDeviceImageMemoryRequirementsKHR(device->vk_device, &requirement_info, &requirements));
allocation_info->SizeInBytes = requirements.memoryRequirements.size;
allocation_info->Alignment = requirements.memoryRequirements.alignment;
/* Do not report alignments greater than DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT
* since that might confuse apps. Instead, pad the allocation so that we can