From 2a8b5471cadd379720cf383377bc78c44b78e7b9 Mon Sep 17 00:00:00 2001 From: David Gow Date: Mon, 1 Nov 2021 18:37:35 +0800 Subject: [PATCH] vkd3d: Handle D3D12_APPEND_ALIGNED_ELEMENT for <4 byte wide elements In d3d12, input element alignment needs to be the _minimum_ of 4 and the size of the type. See the D3D11 spec, section 4.4.6, which behaves similarly: https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#4.4.6%20Element%20Alignment This is correctly taken into account when generating, e.g., the vertex_buffer_stride_align_mask used for validation, but is not taken into account when D3D12_APPEND_ALIGNED_ELEMENT is used to automatically place input elements. Currently, vkd3d always assumes the alignment is 4. This means that, for example, bytes or shorts should be packed tightly together when D3D12_APPEND_ALIGNED_ELEMENT is used, but are instead padded to 4 bytes. Fixing this makes units appear in Age of Empires IV (see vkd3d-proton issue #880 for examples.) Signed-off-by: David Gow --- libs/vkd3d/state.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index e51c11ea..847f497b 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -2807,9 +2807,9 @@ static HRESULT compute_input_layout_offsets(const struct d3d12_device *device, if (e->AlignedByteOffset != D3D12_APPEND_ALIGNED_ELEMENT) offsets[i] = e->AlignedByteOffset; else - offsets[i] = input_slot_offsets[e->InputSlot]; + offsets[i] = align(input_slot_offsets[e->InputSlot], min(4, format->byte_count)); - input_slot_offsets[e->InputSlot] = align(offsets[i] + format->byte_count, 4); + input_slot_offsets[e->InputSlot] = offsets[i] + format->byte_count; } return S_OK;