=?UTF-8?Q?J=C3=B3zef=20Kucia=20?=: libs/vkd3d: Validate miplevel count while creating resources.

Alexandre Julliard julliard at winehq.org
Thu Jan 11 15:34:06 CST 2018


Module: vkd3d
Branch: master
Commit: ee8eb9b4e4f40041240e5531c4684b7ae0c0fcb9
URL:    https://source.winehq.org/git/vkd3d.git/?a=commit;h=ee8eb9b4e4f40041240e5531c4684b7ae0c0fcb9

Author: Józef Kucia <jkucia at codeweavers.com>
Date:   Thu Jan 11 17:03:44 2018 +0100

libs/vkd3d: Validate miplevel count while creating resources.

vkd3d_log2i() is imported from wined3d.

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 configure.ac                   |  1 +
 include/private/vkd3d_common.h | 32 ++++++++++++++++++++++++++++++++
 libs/vkd3d/resource.c          | 40 +++++++++++++++++++++++++++++++++++-----
 m4/check-builtin-functions.m4  | 10 ++++++++++
 tests/d3d12.c                  | 25 +++++++++++++++++++++++++
 5 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/configure.ac b/configure.ac
index 27c03a6..d13b440 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,6 +79,7 @@ AS_IF([test "x$with_spirv_tools" = "xyes"],
 PKG_CHECK_MODULES([XCB], [xcb xcb-keysyms])
 
 dnl Check for functions
+VKD3D_CHECK_BUILTIN_CLZ
 VKD3D_CHECK_BUILTIN_POPCOUNT
 VKD3D_CHECK_SYNC_ADD_AND_FETCH_FUNC
 VKD3D_CHECK_SYNC_SUB_AND_FETCH_FUNC
diff --git a/include/private/vkd3d_common.h b/include/private/vkd3d_common.h
index ce8f32e..2e3873b 100644
--- a/include/private/vkd3d_common.h
+++ b/include/private/vkd3d_common.h
@@ -50,6 +50,38 @@ static inline unsigned int vkd3d_popcount(unsigned int v)
 #endif
 }
 
+/* Undefined for x == 0. */
+static inline unsigned int vkd3d_log2i(unsigned int x)
+{
+#ifdef HAVE_BUILTIN_CLZ
+    return __builtin_clz(x) ^ 0x1f;
+#else
+    static const unsigned int l[] =
+    {
+        ~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+          4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+          5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+          5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+    };
+    unsigned int i;
+
+    return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24
+            : l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];
+#endif
+}
+
 #ifndef _WIN32
 # if HAVE_SYNC_ADD_AND_FETCH
 static inline LONG InterlockedIncrement(LONG volatile *x)
diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c
index 72848a4..264578b 100644
--- a/libs/vkd3d/resource.c
+++ b/libs/vkd3d/resource.c
@@ -103,14 +103,16 @@ HRESULT vkd3d_create_buffer(struct d3d12_device *device,
 }
 
 static HRESULT vkd3d_create_image(struct d3d12_resource *resource, struct d3d12_device *device,
-        const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
-        const D3D12_RESOURCE_DESC *desc)
+        const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags)
 {
     const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
     const struct vkd3d_format *format;
+    const D3D12_RESOURCE_DESC *desc;
     VkImageCreateInfo image_info;
     VkResult vr;
 
+    desc = &resource->desc;
+
     if (!(format = vkd3d_format_from_d3d12_resource_desc(desc, 0)))
     {
         WARN("Invalid DXGI format %#x.\n", desc->Format);
@@ -606,6 +608,30 @@ struct d3d12_resource *unsafe_impl_from_ID3D12Resource(ID3D12Resource *iface)
     return impl_from_ID3D12Resource(iface);
 }
 
+static HRESULT validate_buffer_desc(const D3D12_RESOURCE_DESC *desc)
+{
+    if (desc->MipLevels != 1)
+    {
+        WARN("Invalid miplevel count %u for buffer.\n", desc->MipLevels);
+        return E_INVALIDARG;
+    }
+
+    return S_OK;
+}
+
+static HRESULT validate_texture_desc(D3D12_RESOURCE_DESC *desc)
+{
+    if (!desc->MipLevels)
+    {
+        unsigned int size = max(desc->Width, desc->Height);
+        if (desc->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
+            size = max(size, desc->DepthOrArraySize);
+        desc->MipLevels = vkd3d_log2i(size) + 1;
+    }
+
+    return S_OK;
+}
+
 static HRESULT d3d12_committed_resource_init(struct d3d12_resource *resource, struct d3d12_device *device,
         const D3D12_HEAP_PROPERTIES *heap_properties, D3D12_HEAP_FLAGS heap_flags,
         const D3D12_RESOURCE_DESC *desc, D3D12_RESOURCE_STATES initial_state,
@@ -658,8 +684,10 @@ static HRESULT d3d12_committed_resource_init(struct d3d12_resource *resource, st
     switch (desc->Dimension)
     {
         case D3D12_RESOURCE_DIMENSION_BUFFER:
-            if (FAILED(hr = vkd3d_create_buffer(device, heap_properties, heap_flags, desc,
-                    &resource->u.vk_buffer)))
+            if (FAILED(hr = validate_buffer_desc(&resource->desc)))
+                return hr;
+            if (FAILED(hr = vkd3d_create_buffer(device, heap_properties, heap_flags,
+                    &resource->desc, &resource->u.vk_buffer)))
                 return hr;
             if (!(resource->gpu_address = vkd3d_gpu_va_allocator_allocate(&device->gpu_va_allocator,
                     desc->Width, resource)))
@@ -679,8 +707,10 @@ static HRESULT d3d12_committed_resource_init(struct d3d12_resource *resource, st
         case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
         case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
         case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
+            if (FAILED(hr = validate_texture_desc(&resource->desc)))
+                return hr;
             resource->flags |= VKD3D_RESOURCE_INITIAL_STATE_TRANSITION;
-            if (FAILED(hr = vkd3d_create_image(resource, device, heap_properties, heap_flags, desc)))
+            if (FAILED(hr = vkd3d_create_image(resource, device, heap_properties, heap_flags)))
                 return hr;
             if (FAILED(hr = vkd3d_allocate_image_memory(resource, device, heap_properties, heap_flags)))
             {
diff --git a/m4/check-builtin-functions.m4 b/m4/check-builtin-functions.m4
index c09eb47..2b24a80 100644
--- a/m4/check-builtin-functions.m4
+++ b/m4/check-builtin-functions.m4
@@ -18,6 +18,16 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([int main(void) { return __sync_sub_and_fetch((in
                          [Define to 1 if you have __sync_sub_and_fetch.])],
                [AC_MSG_RESULT([no])])])
 
+dnl VKD3D_CHECK_BUILTIN_CLZ
+AC_DEFUN([VKD3D_CHECK_BUILTIN_CLZ],
+[AC_MSG_CHECKING([for __builtin_clz])
+AC_LINK_IFELSE([AC_LANG_SOURCE([int main(void) { return __builtin_clz(0); }])],
+               [AC_MSG_RESULT([yes])
+               AC_DEFINE([HAVE_BUILTIN_CLZ],
+                         [1],
+                         [Define to 1 if you have __builtin_clz.])],
+               [AC_MSG_RESULT([no])])])
+
 dnl VKD3D_CHECK_BUILTIN_POPCOUNT
 AC_DEFUN([VKD3D_CHECK_BUILTIN_POPCOUNT],
 [AC_MSG_CHECKING([for __builtin_popcount])
diff --git a/tests/d3d12.c b/tests/d3d12.c
index dfc9257..5511620 100644
--- a/tests/d3d12.c
+++ b/tests/d3d12.c
@@ -2213,6 +2213,24 @@ static void test_create_committed_resource(void)
     refcount = ID3D12Resource_Release(resource);
     ok(!refcount, "ID3D12Resource has %u references left.\n", (unsigned int)refcount);
 
+    resource_desc.MipLevels = 0;
+    hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
+            &resource_desc, D3D12_RESOURCE_STATE_RENDER_TARGET, &clear_value,
+            &IID_ID3D12Resource, (void **)&resource);
+    ok(SUCCEEDED(hr), "Failed to create committed resource, hr %#x.\n", hr);
+    resource_desc = ID3D12Resource_GetDesc(resource);
+    ok(resource_desc.MipLevels == 6, "Got unexpected miplevels %u.\n", resource_desc.MipLevels);
+    ID3D12Resource_Release(resource);
+    resource_desc.MipLevels = 10;
+    hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
+            &resource_desc, D3D12_RESOURCE_STATE_RENDER_TARGET, &clear_value,
+            &IID_ID3D12Resource, (void **)&resource);
+    ok(SUCCEEDED(hr), "Failed to create committed resource, hr %#x.\n", hr);
+    resource_desc = ID3D12Resource_GetDesc(resource);
+    ok(resource_desc.MipLevels == 10, "Got unexpected miplevels %u.\n", resource_desc.MipLevels);
+    ID3D12Resource_Release(resource);
+    resource_desc.MipLevels = 1;
+
     hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
             &resource_desc, D3D12_RESOURCE_STATE_RENDER_TARGET | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
             &clear_value, &IID_ID3D12Resource, (void **)&resource);
@@ -2291,6 +2309,13 @@ static void test_create_committed_resource(void)
     refcount = ID3D12Resource_Release(resource);
     ok(!refcount, "ID3D12Resource has %u references left.\n", (unsigned int)refcount);
 
+    resource_desc.MipLevels = 0;
+    hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
+            &resource_desc, D3D12_RESOURCE_STATE_GENERIC_READ, &clear_value,
+            &IID_ID3D12Resource, (void **)&resource);
+    ok(hr == E_INVALIDARG, "Failed to create committed resource, hr %#x.\n", hr);
+    resource_desc.MipLevels = 1;
+
     /* The clear value must be NULL for buffers. */
     hr = ID3D12Device_CreateCommittedResource(device, &heap_properties, D3D12_HEAP_FLAG_NONE,
             &resource_desc, D3D12_RESOURCE_STATE_GENERIC_READ, &clear_value,




More information about the wine-cvs mailing list