Mesa (main): radv: reject binding buffer/image when the device memory is too small

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jun 18 08:21:49 UTC 2021


Module: Mesa
Branch: main
Commit: 50233d0daa3ca444a1f1caf6e9eab1144d28530d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=50233d0daa3ca444a1f1caf6e9eab1144d28530d

Author: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Date:   Thu Jun 17 14:46:50 2021 +0200

radv: reject binding buffer/image when the device memory is too small

>From the Vulkan spec 1.2.181:
    "The difference of the size of memory and memoryOffset must be
     greater than or equal to the size member of the
     VkMemoryRequirements structure returned from a call to
     vkGetImageMemoryRequirements with the same image"

This is invalid usage but adding a check in the driver is safe and
might avoid spurious failures.

This is a workaround for the inventory GPU hang with Cyberpunk 2077
which is actually a game bug. Luckily the game handles this error
gracefully.

Since the addrlib change from March, addrlib now selects a better
swizzle mode (4KB instead of 64KB) which reduces image size. Though,
the game assumes that an image with 2 mips is always smaller than the
same image but with 6 mips. This is not always true if the swizzle mode
is different. Then, it creates a D312 heap that is too small for the 2
mips image and the GPU hang with a memory violation, ugh...

Note that next vkd3d-proton release should also reject this but
fixing both sides is fine.

Cc: 21.1 mesa-stable
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4823
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4593
Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11448>

---

 src/amd/vulkan/radv_device.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index e7fea9b838d..8f8a0194c01 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -5466,14 +5466,27 @@ radv_GetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory,
 }
 
 VkResult
-radv_BindBufferMemory2(VkDevice device, uint32_t bindInfoCount,
+radv_BindBufferMemory2(VkDevice _device, uint32_t bindInfoCount,
                        const VkBindBufferMemoryInfo *pBindInfos)
 {
+   RADV_FROM_HANDLE(radv_device, device, _device);
+
    for (uint32_t i = 0; i < bindInfoCount; ++i) {
       RADV_FROM_HANDLE(radv_device_memory, mem, pBindInfos[i].memory);
       RADV_FROM_HANDLE(radv_buffer, buffer, pBindInfos[i].buffer);
 
       if (mem) {
+         if (mem->alloc_size) {
+            VkMemoryRequirements req;
+
+            radv_GetBufferMemoryRequirements(_device, pBindInfos[i].buffer, &req);
+
+            if (pBindInfos[i].memoryOffset + req.size > mem->alloc_size) {
+               return vk_errorf(device->instance, VK_ERROR_UNKNOWN,
+                                "Device memory object too small for the buffer.\n");
+            }
+         }
+
          buffer->bo = mem->bo;
          buffer->offset = pBindInfos[i].memoryOffset;
       } else {
@@ -5496,14 +5509,27 @@ radv_BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory,
 }
 
 VkResult
-radv_BindImageMemory2(VkDevice device, uint32_t bindInfoCount,
+radv_BindImageMemory2(VkDevice _device, uint32_t bindInfoCount,
                       const VkBindImageMemoryInfo *pBindInfos)
 {
+   RADV_FROM_HANDLE(radv_device, device, _device);
+
    for (uint32_t i = 0; i < bindInfoCount; ++i) {
       RADV_FROM_HANDLE(radv_device_memory, mem, pBindInfos[i].memory);
       RADV_FROM_HANDLE(radv_image, image, pBindInfos[i].image);
 
       if (mem) {
+         if (mem->alloc_size) {
+            VkMemoryRequirements req;
+
+            radv_GetImageMemoryRequirements(_device, pBindInfos[i].image, &req);
+
+            if (pBindInfos[i].memoryOffset + req.size > mem->alloc_size) {
+               return vk_errorf(device->instance, VK_ERROR_UNKNOWN,
+                                "Device memory object too small for the image.\n");
+            }
+         }
+
          image->bo = mem->bo;
          image->offset = pBindInfos[i].memoryOffset;
       } else {



More information about the mesa-commit mailing list