anv: Fix FlushMappedMemoryRanges for odd mmap offsets
authorJason Ekstrand <jason@jlekstrand.net>
Sat, 30 Oct 2021 21:57:02 +0000 (16:57 -0500)
committerMarge Bot <emma+marge@anholt.net>
Tue, 9 Nov 2021 02:48:24 +0000 (02:48 +0000)
When the client calls vkMapMemory(), we have to align the requested
offset down to the nearest page or else the map will fail.  On platforms
where we have DRM_IOCTL_I915_GEM_MMAP_OFFSET, we always map the whole
buffer.  In either case, the original map may start before the requested
offset and we need to take that into account when we clflush.

Cc: mesa-stable@lists.freedesktop.org
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13610>

src/intel/vulkan/anv_device.c
src/intel/vulkan/anv_private.h

index 8d85306..32fb9d6 100644 (file)
@@ -4073,8 +4073,9 @@ VkResult anv_MapMemory(
 
    mem->map = map;
    mem->map_size = map_size;
+   mem->map_delta = (offset - map_offset);
 
-   *ppData = mem->map + (offset - map_offset);
+   *ppData = mem->map + mem->map_delta;
 
    return VK_SUCCESS;
 }
@@ -4093,6 +4094,7 @@ void anv_UnmapMemory(
 
    mem->map = NULL;
    mem->map_size = 0;
+   mem->map_delta = 0;
 }
 
 static void
@@ -4102,14 +4104,15 @@ clflush_mapped_ranges(struct anv_device         *device,
 {
    for (uint32_t i = 0; i < count; i++) {
       ANV_FROM_HANDLE(anv_device_memory, mem, ranges[i].memory);
-      if (ranges[i].offset >= mem->map_size)
+      uint64_t map_offset = ranges[i].offset + mem->map_delta;
+      if (map_offset >= mem->map_size)
          continue;
 
       if (mem->type->propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
          continue;
 
-      intel_clflush_range(mem->map + ranges[i].offset,
-                        MIN2(ranges[i].size, mem->map_size - ranges[i].offset));
+      intel_clflush_range(mem->map + map_offset,
+                          MIN2(ranges[i].size, mem->map_size - map_offset));
    }
 }
 
index 3fdbfce..b02f954 100644 (file)
@@ -1777,6 +1777,9 @@ struct anv_device_memory {
    VkDeviceSize                                 map_size;
    void *                                       map;
 
+   /* The map, from the user PoV is map + map_delta */
+   uint32_t                                     map_delta;
+
    /* If set, we are holding reference to AHardwareBuffer
     * which we must release when memory is freed.
     */