vk: Implement vkFlushMappedMemoryRanges()
authorKristian Høgsberg <krh@sweater.jf.intel.com>
Tue, 1 Dec 2015 23:25:07 +0000 (15:25 -0800)
committerKristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
Fri, 4 Dec 2015 17:51:47 +0000 (09:51 -0800)
We'll do a runtime switch on device->info.has_llc for now.

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

index c25ad34a6133e8b3bcd778c09d7121cb14323553..724c4120a06ada79c609098541c17bb1efb0da88 100644 (file)
@@ -1035,22 +1035,57 @@ void anv_UnmapMemory(
    anv_gem_munmap(mem->map, mem->map_size);
 }
 
+static void
+clflush_mapped_ranges(struct anv_device         *device,
+                      uint32_t                   count,
+                      const VkMappedMemoryRange *ranges)
+{
+   for (uint32_t i = 0; i < count; i++) {
+      ANV_FROM_HANDLE(anv_device_memory, mem, ranges[i].memory);
+      void *p = mem->map + (ranges[i].offset & ~CACHELINE_MASK);
+      void *end = mem->map + ranges[i].offset + ranges[i].size;
+
+      while (p < end) {
+         __builtin_ia32_clflush(p);
+         p += CACHELINE_SIZE;
+      }
+   }
+}
+
 VkResult anv_FlushMappedMemoryRanges(
-    VkDevice                                    device,
+    VkDevice                                    _device,
     uint32_t                                    memoryRangeCount,
     const VkMappedMemoryRange*                  pMemoryRanges)
 {
-   /* clflush here for !llc platforms */
+   ANV_FROM_HANDLE(anv_device, device, _device);
+
+   if (device->info.has_llc)
+      return VK_SUCCESS;
+
+   /* Make sure the writes we're flushing have landed. */
+   __builtin_ia32_sfence();
+
+   clflush_mapped_ranges(device, memoryRangeCount, pMemoryRanges);
 
    return VK_SUCCESS;
 }
 
 VkResult anv_InvalidateMappedMemoryRanges(
-    VkDevice                                    device,
+    VkDevice                                    _device,
     uint32_t                                    memoryRangeCount,
     const VkMappedMemoryRange*                  pMemoryRanges)
 {
-   return anv_FlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
+   ANV_FROM_HANDLE(anv_device, device, _device);
+
+   if (device->info.has_llc)
+      return VK_SUCCESS;
+
+   clflush_mapped_ranges(device, memoryRangeCount, pMemoryRanges);
+
+   /* Make sure no reads get moved up above the invalidate. */
+   __builtin_ia32_lfence();
+
+   return VK_SUCCESS;
 }
 
 void anv_GetBufferMemoryRequirements(
index 3fc305ba15e354f1903a3fc75016f4bba0b9301c..c21d9d7c8567a24ed5a75d6d188e6302f1b9ea1c 100644 (file)
@@ -391,6 +391,9 @@ struct anv_state_stream {
    uint32_t end;
 };
 
+#define CACHELINE_SIZE 64
+#define CACHELINE_MASK 63
+
 void anv_block_pool_init(struct anv_block_pool *pool,
                          struct anv_device *device, uint32_t block_size);
 void anv_block_pool_finish(struct anv_block_pool *pool);