From af60bc03ba3e580a44d1b14840fa3cdbcb124c51 Mon Sep 17 00:00:00 2001 From: Conor McCarthy Date: Thu, 28 Nov 2019 00:19:13 +1000 Subject: [PATCH] vkd3d: Validate texture resource alignments. Signed-off-by: Conor McCarthy Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- libs/vkd3d/device.c | 4 +-- libs/vkd3d/resource.c | 56 +++++++++++++++++++++++++++++++++----- libs/vkd3d/vkd3d_private.h | 2 +- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 59859add..31d793f8 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -2920,7 +2920,7 @@ static D3D12_RESOURCE_ALLOCATION_INFO * STDMETHODCALLTYPE d3d12_device_GetResour desc = &resource_descs[0]; - if (FAILED(d3d12_resource_validate_desc(desc))) + if (FAILED(d3d12_resource_validate_desc(desc, device))) { WARN("Invalid resource desc.\n"); goto invalid; @@ -3226,7 +3226,7 @@ static void STDMETHODCALLTYPE d3d12_device_GetCopyableFootprints(ID3D12Device *i return; } - if (FAILED(d3d12_resource_validate_desc(desc))) + if (FAILED(d3d12_resource_validate_desc(desc, device))) { WARN("Invalid resource desc.\n"); return; diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index f5cdf4ad..e7fc3662 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1001,7 +1001,7 @@ HRESULT vkd3d_get_image_allocation_info(struct d3d12_device *device, HRESULT hr; assert(desc->Dimension != D3D12_RESOURCE_DIMENSION_BUFFER); - assert(d3d12_resource_validate_desc(desc) == S_OK); + assert(d3d12_resource_validate_desc(desc, device) == S_OK); if (!desc->MipLevels) { @@ -1591,8 +1591,45 @@ static void d3d12_validate_resource_flags(D3D12_RESOURCE_FLAGS flags) FIXME("Ignoring D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER.\n"); } -HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc) +static bool d3d12_resource_validate_texture_alignment(const D3D12_RESOURCE_DESC *desc, + const struct vkd3d_format *format) { + uint64_t estimated_size; + + if (!desc->Alignment) + return true; + + if (desc->Alignment != D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT + && desc->Alignment != D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT + && (desc->SampleDesc.Count == 1 || desc->Alignment != D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT)) + { + WARN("Invalid resource alignment %#"PRIx64".\n", desc->Alignment); + return false; + } + + if (desc->Alignment < D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT) + { + /* Windows uses the slice size to determine small alignment eligibility. DepthOrArraySize is ignored. */ + estimated_size = desc->Width * desc->Height * format->byte_count * format->block_byte_count + / (format->block_width * format->block_height); + if (estimated_size > D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT) + { + WARN("Invalid resource alignment %#"PRIx64" (required %#x).\n", + desc->Alignment, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT); + return false; + } + } + + /* The size check for MSAA textures with D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT is probably + * not important. The 4MB requirement is no longer universal and Vulkan has no such requirement. */ + + return true; +} + +HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d12_device *device) +{ + const struct vkd3d_format *format; + switch (desc->Dimension) { case D3D12_RESOURCE_DIMENSION_BUFFER: @@ -1618,10 +1655,17 @@ HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc) WARN("1D texture with a height of %u.\n", desc->Height); return E_INVALIDARG; } - break; - + /* Fall through. */ case D3D12_RESOURCE_DIMENSION_TEXTURE2D: case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + if (!(format = vkd3d_format_from_d3d12_resource_desc(device, desc, 0))) + { + WARN("Invalid format %#x.\n", desc->Format); + return E_INVALIDARG; + } + + if (!d3d12_resource_validate_texture_alignment(desc, format)) + return E_INVALIDARG; break; default: @@ -1631,8 +1675,6 @@ HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc) d3d12_validate_resource_flags(desc->Flags); - /* FIXME: Validate alignment for textures. */ - return S_OK; } @@ -1703,7 +1745,7 @@ static HRESULT d3d12_resource_init(struct d3d12_resource *resource, struct d3d12 resource->gpu_address = 0; resource->flags = 0; - if (FAILED(hr = d3d12_resource_validate_desc(&resource->desc))) + if (FAILED(hr = d3d12_resource_validate_desc(&resource->desc, device))) return hr; switch (desc->Dimension) diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index df8d1a10..9ff6bbaa 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -435,7 +435,7 @@ static inline bool d3d12_resource_is_texture(const struct d3d12_resource *resour } bool d3d12_resource_is_cpu_accessible(const struct d3d12_resource *resource) DECLSPEC_HIDDEN; -HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc) DECLSPEC_HIDDEN; +HRESULT d3d12_resource_validate_desc(const D3D12_RESOURCE_DESC *desc, struct d3d12_device *device) DECLSPEC_HIDDEN; HRESULT d3d12_committed_resource_create(struct d3d12_device *device, const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,