anv/device: Handle non-4k-aligned calls to MapMemory
authorJason Ekstrand <jason.ekstrand@intel.com>
Fri, 1 Jan 2016 17:26:06 +0000 (09:26 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Fri, 1 Jan 2016 17:29:29 +0000 (09:29 -0800)
As per the spec:

   minMemoryMapAlignment is the minimum required alignment, in bytes, of
   host-visible memory allocations within the host address space. When
   mapping a memory allocation with vkMapMemory, subtracting offset bytes
   from the returned pointer will always produce a multiple of the value of
   this limit.

src/vulkan/anv_device.c

index 88a4b8d067d0455ef22ac87f521c26b240a38c37..9a56d9b7de0f3fa31f3a53d122ae6af899167f8b 100644 (file)
@@ -468,7 +468,7 @@ void anv_GetPhysicalDeviceProperties(
       .maxViewportDimensions                    = { (1 << 14), (1 << 14) },
       .viewportBoundsRange                      = { -1.0, 1.0 }, /* FIXME */
       .viewportSubPixelBits                     = 13, /* We take a float? */
-      .minMemoryMapAlignment                    = 64, /* A cache line */
+      .minMemoryMapAlignment                    = 4096, /* A page */
       .minTexelBufferOffsetAlignment            = 1,
       .minUniformBufferOffsetAlignment          = 1,
       .minStorageBufferOffsetAlignment          = 1,
@@ -1082,10 +1082,19 @@ VkResult anv_MapMemory(
    if (!device->info.has_llc && mem->type_index == 0)
       gem_flags |= I915_MMAP_WC;
 
-   mem->map = anv_gem_mmap(device, mem->bo.gem_handle, offset, size, gem_flags);
-   mem->map_size = size;
+   /* GEM will fail to map if the offset isn't 4k-aligned.  Round down. */
+   uint64_t map_offset = offset & ~4095ull;
+   assert(offset >= map_offset);
+   uint64_t map_size = (offset + size) - map_offset;
 
-   *ppData = mem->map;
+   /* Let's map whole pages */
+   map_size = (map_size + 4095) & ~4095ull;
+
+   mem->map = anv_gem_mmap(device, mem->bo.gem_handle,
+                           map_offset, map_size, gem_flags);
+   mem->map_size = map_size;
+
+   *ppData = mem->map + (offset - map_offset);
 
    return VK_SUCCESS;
 }