vk: Expose two memory types for non-LLC GPUs
authorKristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
Fri, 4 Dec 2015 07:09:09 +0000 (23:09 -0800)
committerKristian Høgsberg Kristensen <kristian.h.kristensen@intel.com>
Fri, 4 Dec 2015 17:51:47 +0000 (09:51 -0800)
We're required to expose a host-visible, coherent memory type. On big
core GPUs that share, LLC, we can expose one such memory type that's
also cached.  However, on non-LLC GPUs we can't both be cached and
coherent. Thus, we expose both the required coherent type and the cached
but non-coherent combination.

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

index 384a457742f81ba9e90a1185a49302b34b36445e..a8bc409144d68157aecded26444393a766790bf5 100644 (file)
@@ -553,15 +553,38 @@ void anv_GetPhysicalDeviceMemoryProperties(
     */
    heap_size = 3 * physical_device->aperture_size / 4;
 
-   /* The property flags below are valid only for llc platforms. */
-   pMemoryProperties->memoryTypeCount = 1;
-   pMemoryProperties->memoryTypes[0] = (VkMemoryType) {
-      .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
-                       VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
-                       VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
-                       VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
-      .heapIndex = 1,
-   };
+   if (physical_device->info->has_llc) {
+      /* Big core GPUs share LLC with the CPU and thus one memory type can be
+       * both cached and coherent at the same time.
+       */
+      pMemoryProperties->memoryTypeCount = 1;
+      pMemoryProperties->memoryTypes[0] = (VkMemoryType) {
+         .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                          VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                          VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
+                          VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
+         .heapIndex = 1,
+      };
+   } else {
+      /* The spec requires that we expose a host-visible, coherent memory
+       * type, but Atom GPUs don't share LLC. Thus we offer two memory types
+       * to give the application a choice between cached, but not coherent and
+       * coherent but uncached (WC though).
+       */
+      pMemoryProperties->memoryTypeCount = 2;
+      pMemoryProperties->memoryTypes[0] = (VkMemoryType) {
+         .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                          VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                          VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+         .heapIndex = 1,
+      };
+      pMemoryProperties->memoryTypes[1] = (VkMemoryType) {
+         .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+                          VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+                          VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
+         .heapIndex = 1,
+      };
+   }
 
    pMemoryProperties->memoryHeapCount = 1;
    pMemoryProperties->memoryHeaps[0] = (VkMemoryHeap) {
@@ -976,7 +999,8 @@ VkResult anv_AllocateMemory(
    assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
 
    /* We support exactly one memory heap. */
-   assert(pAllocateInfo->memoryTypeIndex == 0);
+   assert(pAllocateInfo->memoryTypeIndex == 0 ||
+          (!device->info.has_llc && pAllocateInfo->memoryTypeIndex < 2));
 
    /* FINISHME: Fail if allocation request exceeds heap size. */
 
@@ -989,6 +1013,8 @@ VkResult anv_AllocateMemory(
    if (result != VK_SUCCESS)
       goto fail;
 
+   mem->type_index = pAllocateInfo->memoryTypeIndex;
+
    *pMem = anv_device_memory_to_handle(mem);
 
    return VK_SUCCESS;
index 3c0441b66f38333e3e6fa14b358fa5e02d438ae5..7c8cf2416247c43b56ffab5c09ee239880f897f0 100644 (file)
@@ -784,6 +784,7 @@ __gen_combine_address(struct anv_batch *batch, void *location,
 
 struct anv_device_memory {
    struct anv_bo                                bo;
+   uint32_t                                     type_index;
    VkDeviceSize                                 map_size;
    void *                                       map;
 };