Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- v2: Remove unnecessary struct d3d12_device *device. --- 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 59859ad..31d793f 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 f5cdf4a..6e8c98e 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 df8d1a1..9ff6bba 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,