[PATCH vkd3d 1/3] vkd3d: Validate texture resource alignments.

Conor McCarthy cmccarthy at codeweavers.com
Wed Nov 27 07:48:34 CST 2019


Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 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,
+        struct d3d12_device *device, 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, device, 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,
-- 
2.24.0




More information about the wine-devel mailing list