[PATCH vkd3d 1/2] vkd3d: Always return a valid allocation size for D3D12 default alignments.
Conor McCarthy
cmccarthy at codeweavers.com
Wed Nov 13 08:48:28 CST 2019
Some hardware and driver combinations, e.g. AMD RX 580 / RADV, do not support
alignments of 0x1000 and 0x10000. This causes GetResourceAllocationInfo() to
return a size of ~0 for valid D3D12 alignments. Some games do not check for
this. For example Hitman 2 will allocate heaps of size 0xffffffff and run out
of vram. This patch also fixes RX 580 alignment test failures.
Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
libs/vkd3d/device.c | 35 ++++++++++++++++++++++++-----------
1 file changed, 24 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 0624318..7421978 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -2893,6 +2893,19 @@ static void STDMETHODCALLTYPE d3d12_device_CopyDescriptorsSimple(ID3D12Device *i
1, &src_descriptor_range_offset, &descriptor_count, descriptor_heap_type);
}
+static bool d3d12_validate_resource_alignment(const D3D12_RESOURCE_DESC *desc,
+ uint64_t requested_alignment, uint64_t vk_alignment, uint64_t estimated_size)
+{
+ /* We must return true if the requested alignment is one of D3D12's default alignments. Some games,
+ * e.g. Hitman 2, assume that these will work and don't check the returned allocation size for ~0. */
+ if (requested_alignment == D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT)
+ return estimated_size <= D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+
+ return !(desc->Alignment % vk_alignment)
+ || requested_alignment == D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT
+ || (desc->SampleDesc.Count > 1 && requested_alignment == D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT);
+}
+
static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResourceAllocationInfo(
ID3D12Device *iface, D3D12_RESOURCE_ALLOCATION_INFO *info, UINT visible_mask,
UINT count, const D3D12_RESOURCE_DESC *resource_descs)
@@ -2930,6 +2943,7 @@ static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResour
if (desc->Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
{
+ estimated_size = desc->Width;
info->SizeInBytes = desc->Width;
info->Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
}
@@ -2943,21 +2957,20 @@ static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResour
info->Alignment = max(info->Alignment, requested_alignment);
- if (info->Alignment < D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT)
+ if (!(format = vkd3d_format_from_d3d12_resource_desc(device, desc, 0)))
{
- if (!(format = vkd3d_format_from_d3d12_resource_desc(device, desc, 0)))
- {
- WARN("Invalid format %#x.\n", desc->Format);
- goto invalid;
- }
-
- estimated_size = desc->Width * desc->Height * desc->DepthOrArraySize * format->byte_count;
- if (estimated_size > D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT)
- info->Alignment = max(info->Alignment, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT);
+ WARN("Invalid format %#x.\n", desc->Format);
+ goto invalid;
}
+
+ estimated_size = desc->Width * desc->Height * desc->DepthOrArraySize * format->byte_count;
+
+ if (info->Alignment < D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT
+ && estimated_size > D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT)
+ info->Alignment = max(info->Alignment, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT);
}
- if (desc->Alignment % info->Alignment)
+ if (!d3d12_validate_resource_alignment(desc, requested_alignment, info->Alignment, estimated_size))
{
WARN("Invalid resource alignment %#"PRIx64" (required %#"PRIx64").\n",
desc->Alignment, info->Alignment);
--
2.23.0
More information about the wine-devel
mailing list