anv: Better handle return codes from anv_physical_device_init
[mesa.git] / src / intel / vulkan / anv_device.c
index a8835f74179726ff28a4dc075dda33259efba3f7..fcbe5873aa2733611a49defdb8d77754c574dd97 100644 (file)
@@ -28,7 +28,7 @@
 #include <fcntl.h>
 
 #include "anv_private.h"
-#include "mesa/main/git_sha1.h"
+#include "anv_timestamp.h"
 #include "util/strtod.h"
 #include "util/debug.h"
 
@@ -62,35 +62,33 @@ anv_physical_device_init(struct anv_physical_device *device,
 
    fd = open(path, O_RDWR | O_CLOEXEC);
    if (fd < 0)
-      return vk_errorf(VK_ERROR_INITIALIZATION_FAILED,
-                       "failed to open %s: %m", path);
+      return vk_error(VK_ERROR_INCOMPATIBLE_DRIVER);
 
    device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
    device->instance = instance;
-   device->path = path;
+
+   assert(strlen(path) < ARRAY_SIZE(device->path));
+   strncpy(device->path, path, ARRAY_SIZE(device->path));
 
    device->chipset_id = anv_gem_get_param(fd, I915_PARAM_CHIPSET_ID);
    if (!device->chipset_id) {
-      result = vk_errorf(VK_ERROR_INITIALIZATION_FAILED,
-                         "failed to get chipset id: %m");
+      result = vk_error(VK_ERROR_INCOMPATIBLE_DRIVER);
       goto fail;
    }
 
-   device->name = brw_get_device_name(device->chipset_id);
-   device->info = brw_get_device_info(device->chipset_id);
-   if (!device->info) {
-      result = vk_errorf(VK_ERROR_INITIALIZATION_FAILED,
-                         "failed to get device info");
+   device->name = gen_get_device_name(device->chipset_id);
+   if (!gen_get_device_info(device->chipset_id, &device->info)) {
+      result = vk_error(VK_ERROR_INCOMPATIBLE_DRIVER);
       goto fail;
    }
 
-   if (device->info->is_haswell) {
+   if (device->info.is_haswell) {
       fprintf(stderr, "WARNING: Haswell Vulkan support is incomplete\n");
-   } else if (device->info->gen == 7 && !device->info->is_baytrail) {
+   } else if (device->info.gen == 7 && !device->info.is_baytrail) {
       fprintf(stderr, "WARNING: Ivy Bridge Vulkan support is incomplete\n");
-   } else if (device->info->gen == 7 && device->info->is_baytrail) {
+   } else if (device->info.gen == 7 && device->info.is_baytrail) {
       fprintf(stderr, "WARNING: Bay Trail Vulkan support is incomplete\n");
-   } else if (device->info->gen >= 8) {
+   } else if (device->info.gen >= 8) {
       /* Broadwell, Cherryview, Skylake, Broxton, Kabylake is as fully
        * supported as anything */
    } else {
@@ -99,6 +97,17 @@ anv_physical_device_init(struct anv_physical_device *device,
       goto fail;
    }
 
+   device->cmd_parser_version = -1;
+   if (device->info.gen == 7) {
+      device->cmd_parser_version =
+         anv_gem_get_param(fd, I915_PARAM_CMD_PARSER_VERSION);
+      if (device->cmd_parser_version == -1) {
+         result = vk_errorf(VK_ERROR_INITIALIZATION_FAILED,
+                            "failed to get command parser version");
+         goto fail;
+      }
+   }
+
    if (anv_gem_get_aperture(fd, &device->aperture_size) == -1) {
       result = vk_errorf(VK_ERROR_INITIALIZATION_FAILED,
                          "failed to get aperture size: %m");
@@ -117,7 +126,7 @@ anv_physical_device_init(struct anv_physical_device *device,
       goto fail;
    }
 
-   if (!device->info->has_llc &&
+   if (!device->info.has_llc &&
        anv_gem_get_param(fd, I915_PARAM_MMAP_VERSION) < 1) {
       result = vk_errorf(VK_ERROR_INITIALIZATION_FAILED,
                          "kernel missing wc mmap");
@@ -126,11 +135,38 @@ anv_physical_device_init(struct anv_physical_device *device,
 
    bool swizzled = anv_gem_get_bit6_swizzle(fd, I915_TILING_X);
 
+   /* GENs prior to 8 do not support EU/Subslice info */
+   if (device->info.gen >= 8) {
+      device->subslice_total = anv_gem_get_param(fd, I915_PARAM_SUBSLICE_TOTAL);
+      device->eu_total = anv_gem_get_param(fd, I915_PARAM_EU_TOTAL);
+
+      /* Without this information, we cannot get the right Braswell
+       * brandstrings, and we have to use conservative numbers for GPGPU on
+       * many platforms, but otherwise, things will just work.
+       */
+      if (device->subslice_total < 1 || device->eu_total < 1) {
+         fprintf(stderr, "WARNING: Kernel 4.1 required to properly"
+                         " query GPU properties.\n");
+      }
+   } else if (device->info.gen == 7) {
+      device->subslice_total = 1 << (device->info.gt - 1);
+   }
+
+   if (device->info.is_cherryview &&
+       device->subslice_total > 0 && device->eu_total > 0) {
+      /* Logical CS threads = EUs per subslice * 7 threads per EU */
+      uint32_t max_cs_threads = device->eu_total / device->subslice_total * 7;
+
+      /* Fuse configurations may give more threads than expected, never less. */
+      if (max_cs_threads > device->info.max_cs_threads)
+         device->info.max_cs_threads = max_cs_threads;
+   }
+
    close(fd);
 
    brw_process_intel_debug_variable();
 
-   device->compiler = brw_compiler_create(NULL, device->info);
+   device->compiler = brw_compiler_create(NULL, &device->info);
    if (device->compiler == NULL) {
       result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
       goto fail;
@@ -138,8 +174,12 @@ anv_physical_device_init(struct anv_physical_device *device,
    device->compiler->shader_debug_log = compiler_debug_log;
    device->compiler->shader_perf_log = compiler_perf_log;
 
+   result = anv_init_wsi(device);
+   if (result != VK_SUCCESS)
+       goto fail;
+
    /* XXX: Actually detect bit6 swizzling */
-   isl_device_init(&device->isl_dev, device->info, swizzled);
+   isl_device_init(&device->isl_dev, &device->info, swizzled);
 
    return VK_SUCCESS;
 
@@ -151,6 +191,7 @@ fail:
 static void
 anv_physical_device_finish(struct anv_physical_device *device)
 {
+   anv_finish_wsi(device);
    ralloc_free(device->compiler);
 }
 
@@ -159,11 +200,19 @@ static const VkExtensionProperties global_extensions[] = {
       .extensionName = VK_KHR_SURFACE_EXTENSION_NAME,
       .specVersion = 25,
    },
+#ifdef VK_USE_PLATFORM_XCB_KHR
    {
       .extensionName = VK_KHR_XCB_SURFACE_EXTENSION_NAME,
       .specVersion = 5,
    },
-#ifdef HAVE_WAYLAND_PLATFORM
+#endif
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+   {
+      .extensionName = VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
+      .specVersion = 5,
+   },
+#endif
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
    {
       .extensionName = VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME,
       .specVersion = 4,
@@ -179,7 +228,7 @@ static const VkExtensionProperties device_extensions[] = {
 };
 
 static void *
-default_alloc_func(void *pUserData, size_t size, size_t align, 
+default_alloc_func(void *pUserData, size_t size, size_t align,
                    VkSystemAllocationScope allocationScope)
 {
    return malloc(size);
@@ -214,11 +263,16 @@ VkResult anv_CreateInstance(
 
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
 
-   uint32_t client_version = pCreateInfo->pApplicationInfo ?
-                             pCreateInfo->pApplicationInfo->apiVersion :
-                             VK_MAKE_VERSION(1, 0, 0);
+   uint32_t client_version;
+   if (pCreateInfo->pApplicationInfo &&
+       pCreateInfo->pApplicationInfo->apiVersion != 0) {
+      client_version = pCreateInfo->pApplicationInfo->apiVersion;
+   } else {
+      client_version = VK_MAKE_VERSION(1, 0, 0);
+   }
+
    if (VK_MAKE_VERSION(1, 0, 0) > client_version ||
-       client_version > VK_MAKE_VERSION(1, 0, 3)) {
+       client_version > VK_MAKE_VERSION(1, 0, 0xfff)) {
       return vk_errorf(VK_ERROR_INCOMPATIBLE_DRIVER,
                        "Client requested version %d.%d.%d",
                        VK_VERSION_MAJOR(client_version),
@@ -239,7 +293,7 @@ VkResult anv_CreateInstance(
          return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
    }
 
-   instance = anv_alloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
+   instance = vk_alloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
                          VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
    if (!instance)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -258,8 +312,6 @@ VkResult anv_CreateInstance(
 
    VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
 
-   anv_init_wsi(instance);
-
    *pInstance = anv_instance_to_handle(instance);
 
    return VK_SUCCESS;
@@ -277,13 +329,11 @@ void anv_DestroyInstance(
       anv_physical_device_finish(&instance->physicalDevice);
    }
 
-   anv_finish_wsi(instance);
-
    VG(VALGRIND_DESTROY_MEMPOOL(instance));
 
    _mesa_locale_fini();
 
-   anv_free(&instance->alloc, instance);
+   vk_free(&instance->alloc, instance);
 }
 
 VkResult anv_EnumeratePhysicalDevices(
@@ -295,8 +345,15 @@ VkResult anv_EnumeratePhysicalDevices(
    VkResult result;
 
    if (instance->physicalDeviceCount < 0) {
-      result = anv_physical_device_init(&instance->physicalDevice,
-                                        instance, "/dev/dri/renderD128");
+      char path[20];
+      for (unsigned i = 0; i < 8; i++) {
+         snprintf(path, sizeof(path), "/dev/dri/renderD%d", 128 + i);
+         result = anv_physical_device_init(&instance->physicalDevice,
+                                           instance, path);
+         if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
+            break;
+      }
+
       if (result == VK_ERROR_INCOMPATIBLE_DRIVER) {
          instance->physicalDeviceCount = 0;
       } else if (result == VK_SUCCESS) {
@@ -328,6 +385,8 @@ VkResult anv_EnumeratePhysicalDevices(
    } else if (*pPhysicalDeviceCount >= 1) {
       pPhysicalDevices[0] = anv_physical_device_to_handle(&instance->physicalDevice);
       *pPhysicalDeviceCount = 1;
+   } else if (*pPhysicalDeviceCount < instance->physicalDeviceCount) {
+      return VK_INCOMPLETE;
    } else {
       *pPhysicalDeviceCount = 0;
    }
@@ -345,15 +404,15 @@ void anv_GetPhysicalDeviceFeatures(
       .robustBufferAccess                       = true,
       .fullDrawIndexUint32                      = true,
       .imageCubeArray                           = false,
-      .independentBlend                         = pdevice->info->gen >= 8,
+      .independentBlend                         = true,
       .geometryShader                           = true,
       .tessellationShader                       = false,
-      .sampleRateShading                        = false,
+      .sampleRateShading                        = true,
       .dualSrcBlend                             = true,
       .logicOp                                  = true,
       .multiDrawIndirect                        = false,
       .drawIndirectFirstInstance                = false,
-      .depthClamp                               = false,
+      .depthClamp                               = true,
       .depthBiasClamp                           = false,
       .fillModeNonSolid                         = true,
       .depthBounds                              = false,
@@ -361,16 +420,16 @@ void anv_GetPhysicalDeviceFeatures(
       .largePoints                              = true,
       .alphaToOne                               = true,
       .multiViewport                            = true,
-      .samplerAnisotropy                        = false, /* FINISHME */
-      .textureCompressionETC2                   = true,
-      .textureCompressionASTC_LDR               = true,
+      .samplerAnisotropy                        = true,
+      .textureCompressionETC2                   = pdevice->info.gen >= 8 ||
+                                                  pdevice->info.is_baytrail,
+      .textureCompressionASTC_LDR               = pdevice->info.gen >= 9, /* FINISHME CHV */
       .textureCompressionBC                     = true,
       .occlusionQueryPrecise                    = true,
-      .pipelineStatisticsQuery                  = true,
-      .vertexPipelineStoresAndAtomics           = pdevice->info->gen >= 8,
+      .pipelineStatisticsQuery                  = false,
       .fragmentStoresAndAtomics                 = true,
       .shaderTessellationAndGeometryPointSize   = true,
-      .shaderImageGatherExtended                = true,
+      .shaderImageGatherExtended                = false,
       .shaderStorageImageExtendedFormats        = false,
       .shaderStorageImageMultisample            = false,
       .shaderUniformBufferArrayDynamicIndexing  = true,
@@ -388,13 +447,18 @@ void anv_GetPhysicalDeviceFeatures(
       .variableMultisampleRate                  = false,
       .inheritedQueries                         = false,
    };
+
+   /* We can't do image stores in vec4 shaders */
+   pFeatures->vertexPipelineStoresAndAtomics =
+      pdevice->compiler->scalar_stage[MESA_SHADER_VERTEX] &&
+      pdevice->compiler->scalar_stage[MESA_SHADER_GEOMETRY];
 }
 
 void
 anv_device_get_cache_uuid(void *uuid)
 {
    memset(uuid, 0, VK_UUID_SIZE);
-   snprintf(uuid, VK_UUID_SIZE, "anv-%s", MESA_GIT_SHA1 + 4);
+   snprintf(uuid, VK_UUID_SIZE, "anv-%s", ANV_TIMESTAMP);
 }
 
 void anv_GetPhysicalDeviceProperties(
@@ -402,24 +466,26 @@ void anv_GetPhysicalDeviceProperties(
     VkPhysicalDeviceProperties*                 pProperties)
 {
    ANV_FROM_HANDLE(anv_physical_device, pdevice, physicalDevice);
-   const struct brw_device_info *devinfo = pdevice->info;
-
-   anv_finishme("Get correct values for VkPhysicalDeviceLimits");
+   const struct gen_device_info *devinfo = &pdevice->info;
 
    const float time_stamp_base = devinfo->gen >= 9 ? 83.333 : 80.0;
 
+   /* See assertions made when programming the buffer surface state. */
+   const uint32_t max_raw_buffer_sz = devinfo->gen >= 7 ?
+                                      (1ul << 30) : (1ul << 27);
+
    VkSampleCountFlags sample_counts =
       isl_device_get_sample_counts(&pdevice->isl_dev);
 
    VkPhysicalDeviceLimits limits = {
       .maxImageDimension1D                      = (1 << 14),
       .maxImageDimension2D                      = (1 << 14),
-      .maxImageDimension3D                      = (1 << 10),
+      .maxImageDimension3D                      = (1 << 11),
       .maxImageDimensionCube                    = (1 << 14),
-      .maxImageArrayLayers                      = (1 << 10),
+      .maxImageArrayLayers                      = (1 << 11),
       .maxTexelBufferElements                   = 128 * 1024 * 1024,
-      .maxUniformBufferRange                    = UINT32_MAX,
-      .maxStorageBufferRange                    = UINT32_MAX,
+      .maxUniformBufferRange                    = (1ul << 27),
+      .maxStorageBufferRange                    = max_raw_buffer_sz,
       .maxPushConstantsSize                     = MAX_PUSH_CONSTANTS_SIZE,
       .maxMemoryAllocationCount                 = UINT32_MAX,
       .maxSamplerAllocationCount                = 64 * 1024,
@@ -480,7 +546,7 @@ void anv_GetPhysicalDeviceProperties(
       .maxSamplerAnisotropy                     = 16,
       .maxViewports                             = MAX_VIEWPORTS,
       .maxViewportDimensions                    = { (1 << 14), (1 << 14) },
-      .viewportBoundsRange                      = { -16384.0, 16384.0 },
+      .viewportBoundsRange                      = { INT16_MIN, INT16_MAX },
       .viewportSubPixelBits                     = 13, /* We take a float? */
       .minMemoryMapAlignment                    = 4096, /* A page */
       .minTexelBufferOffsetAlignment            = 1,
@@ -490,9 +556,9 @@ void anv_GetPhysicalDeviceProperties(
       .maxTexelOffset                           = 7,
       .minTexelGatherOffset                     = -8,
       .maxTexelGatherOffset                     = 7,
-      .minInterpolationOffset                   = 0, /* FIXME */
-      .maxInterpolationOffset                   = 0, /* FIXME */
-      .subPixelInterpolationOffsetBits          = 0, /* FIXME */
+      .minInterpolationOffset                   = -0.5,
+      .maxInterpolationOffset                   = 0.4375,
+      .subPixelInterpolationOffsetBits          = 4,
       .maxFramebufferWidth                      = (1 << 14),
       .maxFramebufferHeight                     = (1 << 14),
       .maxFramebufferLayers                     = (1 << 10),
@@ -508,7 +574,7 @@ void anv_GetPhysicalDeviceProperties(
       .storageImageSampleCounts                 = VK_SAMPLE_COUNT_1_BIT,
       .maxSampleMaskWords                       = 1,
       .timestampComputeAndGraphics              = false,
-      .timestampPeriod                          = time_stamp_base / (1000 * 1000 * 1000),
+      .timestampPeriod                          = time_stamp_base,
       .maxClipDistances                         = 0 /* FIXME */,
       .maxCullDistances                         = 0 /* FIXME */,
       .maxCombinedClipAndCullDistances          = 0 /* FIXME */,
@@ -525,7 +591,7 @@ void anv_GetPhysicalDeviceProperties(
    };
 
    *pProperties = (VkPhysicalDeviceProperties) {
-      .apiVersion = VK_MAKE_VERSION(1, 0, 2),
+      .apiVersion = VK_MAKE_VERSION(1, 0, 5),
       .driverVersion = 1,
       .vendorID = 0x8086,
       .deviceID = pdevice->chipset_id,
@@ -572,7 +638,7 @@ void anv_GetPhysicalDeviceMemoryProperties(
     */
    heap_size = 3 * physical_device->aperture_size / 4;
 
-   if (physical_device->info->has_llc) {
+   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.
        */
@@ -616,16 +682,18 @@ PFN_vkVoidFunction anv_GetInstanceProcAddr(
     VkInstance                                  instance,
     const char*                                 pName)
 {
-   return anv_lookup_entrypoint(pName);
+   return anv_lookup_entrypoint(NULL, pName);
 }
 
-/* The loader wants us to expose a second GetInstanceProcAddr function
- * to work around certain LD_PRELOAD issues seen in apps.
+/* With version 1+ of the loader interface the ICD should expose
+ * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps.
  */
+PUBLIC
 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(
     VkInstance                                  instance,
     const char*                                 pName);
 
+PUBLIC
 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(
     VkInstance                                  instance,
     const char*                                 pName)
@@ -634,10 +702,11 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(
 }
 
 PFN_vkVoidFunction anv_GetDeviceProcAddr(
-    VkDevice                                    device,
+    VkDevice                                    _device,
     const char*                                 pName)
 {
-   return anv_lookup_entrypoint(pName);
+   ANV_FROM_HANDLE(anv_device, device, _device);
+   return anv_lookup_entrypoint(&device->info, pName);
 }
 
 static VkResult
@@ -709,8 +778,7 @@ anv_device_submit_simple_batch(struct anv_device *device,
 
    /* Kernel driver requires 8 byte aligned batch length */
    size = align_u32(batch->next - batch->start, 8);
-   assert(size < device->batch_bo_pool.bo_size);
-   result = anv_bo_pool_alloc(&device->batch_bo_pool, &bo);
+   result = anv_bo_pool_alloc(&device->batch_bo_pool, &bo, size);
    if (result != VK_SUCCESS)
       return result;
 
@@ -744,7 +812,7 @@ anv_device_submit_simple_batch(struct anv_device *device,
    ret = anv_gem_execbuffer(device, &execbuf);
    if (ret != 0) {
       /* We don't know the real error. */
-      result = vk_errorf(VK_ERROR_OUT_OF_DEVICE_MEMORY, "execbuf2 failed: %m");
+      result = vk_errorf(VK_ERROR_DEVICE_LOST, "execbuf2 failed: %m");
       goto fail;
    }
 
@@ -752,7 +820,7 @@ anv_device_submit_simple_batch(struct anv_device *device,
    ret = anv_gem_wait(device, bo.gem_handle, &timeout);
    if (ret != 0) {
       /* We don't know the real error. */
-      result = vk_errorf(VK_ERROR_OUT_OF_DEVICE_MEMORY, "execbuf2 failed: %m");
+      result = vk_errorf(VK_ERROR_DEVICE_LOST, "execbuf2 failed: %m");
       goto fail;
    }
 
@@ -787,9 +855,7 @@ VkResult anv_CreateDevice(
          return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT);
    }
 
-   anv_set_dispatch_devinfo(physical_device->info);
-
-   device = anv_alloc2(&physical_device->instance->alloc, pAllocator,
+   device = vk_alloc2(&physical_device->instance->alloc, pAllocator,
                        sizeof(*device), 8,
                        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
    if (!device)
@@ -817,12 +883,22 @@ VkResult anv_CreateDevice(
       goto fail_fd;
    }
 
-   device->info = *physical_device->info;
+   device->info = physical_device->info;
    device->isl_dev = physical_device->isl_dev;
 
+   /* On Broadwell and later, we can use batch chaining to more efficiently
+    * implement growing command buffers.  Prior to Haswell, the kernel
+    * command parser gets in the way and we have to fall back to growing
+    * the batch.
+    */
+   device->can_chain_batches = device->info.gen >= 8;
+
+   device->robust_buffer_access = pCreateInfo->pEnabledFeatures &&
+      pCreateInfo->pEnabledFeatures->robustBufferAccess;
+
    pthread_mutex_init(&device->mutex, NULL);
 
-   anv_bo_pool_init(&device->batch_bo_pool, device, ANV_CMD_BUFFER_BATCH_SIZE);
+   anv_bo_pool_init(&device->batch_bo_pool, device);
 
    anv_block_pool_init(&device->dynamic_state_block_pool, device, 16384);
 
@@ -830,7 +906,8 @@ VkResult anv_CreateDevice(
                        &device->dynamic_state_block_pool);
 
    anv_block_pool_init(&device->instruction_block_pool, device, 128 * 1024);
-   anv_pipeline_cache_init(&device->default_pipeline_cache, device);
+   anv_state_pool_init(&device->instruction_state_pool,
+                       &device->instruction_block_pool);
 
    anv_block_pool_init(&device->surface_state_block_pool, device, 4096);
 
@@ -839,7 +916,7 @@ VkResult anv_CreateDevice(
 
    anv_bo_init_new(&device->workaround_bo, device, 1024);
 
-   anv_block_pool_init(&device->scratch_block_pool, device, 0x10000);
+   anv_scratch_pool_init(device, &device->scratch_pool);
 
    anv_queue_init(device, &device->queue);
 
@@ -864,9 +941,7 @@ VkResult anv_CreateDevice(
    if (result != VK_SUCCESS)
       goto fail_fd;
 
-   result = anv_device_init_meta(device);
-   if (result != VK_SUCCESS)
-      goto fail_fd;
+   anv_device_init_blorp(device);
 
    anv_device_init_border_colors(device);
 
@@ -877,7 +952,7 @@ VkResult anv_CreateDevice(
  fail_fd:
    close(device->fd);
  fail_device:
-   anv_free(&device->alloc, device);
+   vk_free(&device->alloc, device);
 
    return result;
 }
@@ -890,7 +965,7 @@ void anv_DestroyDevice(
 
    anv_queue_finish(&device->queue);
 
-   anv_device_finish_meta(device);
+   anv_device_finish_blorp(device);
 
 #ifdef HAVE_VALGRIND
    /* We only need to free these to prevent valgrind errors.  The backing
@@ -905,16 +980,17 @@ void anv_DestroyDevice(
    anv_bo_pool_finish(&device->batch_bo_pool);
    anv_state_pool_finish(&device->dynamic_state_pool);
    anv_block_pool_finish(&device->dynamic_state_block_pool);
+   anv_state_pool_finish(&device->instruction_state_pool);
    anv_block_pool_finish(&device->instruction_block_pool);
    anv_state_pool_finish(&device->surface_state_pool);
    anv_block_pool_finish(&device->surface_state_block_pool);
-   anv_block_pool_finish(&device->scratch_block_pool);
+   anv_scratch_pool_finish(device, &device->scratch_pool);
 
    close(device->fd);
 
    pthread_mutex_destroy(&device->mutex);
 
-   anv_free(&device->alloc, device);
+   vk_free(&device->alloc, device);
 }
 
 VkResult anv_EnumerateInstanceExtensionProperties(
@@ -1014,8 +1090,7 @@ VkResult anv_QueueSubmit(
          ret = anv_gem_execbuffer(device, &cmd_buffer->execbuf2.execbuf);
          if (ret != 0) {
             /* We don't know the real error. */
-            return vk_errorf(VK_ERROR_OUT_OF_DEVICE_MEMORY,
-                             "execbuf2 failed: %m");
+            return vk_errorf(VK_ERROR_DEVICE_LOST, "execbuf2 failed: %m");
          }
 
          for (uint32_t k = 0; k < cmd_buffer->execbuf2.bo_count; k++)
@@ -1027,8 +1102,7 @@ VkResult anv_QueueSubmit(
       ret = anv_gem_execbuffer(device, &fence->execbuf);
       if (ret != 0) {
          /* We don't know the real error. */
-         return vk_errorf(VK_ERROR_OUT_OF_DEVICE_MEMORY,
-                          "execbuf2 failed: %m");
+         return vk_errorf(VK_ERROR_DEVICE_LOST, "execbuf2 failed: %m");
       }
    }
 
@@ -1040,7 +1114,7 @@ VkResult anv_QueueWaitIdle(
 {
    ANV_FROM_HANDLE(anv_queue, queue, _queue);
 
-   return ANV_CALL(DeviceWaitIdle)(anv_device_to_handle(queue->device));
+   return anv_DeviceWaitIdle(anv_device_to_handle(queue->device));
 }
 
 VkResult anv_DeviceWaitIdle(
@@ -1053,8 +1127,8 @@ VkResult anv_DeviceWaitIdle(
    batch.start = batch.next = cmds;
    batch.end = (void *) cmds + sizeof(cmds);
 
-   anv_batch_emit(&batch, GEN7_MI_BATCH_BUFFER_END);
-   anv_batch_emit(&batch, GEN7_MI_NOOP);
+   anv_batch_emit(&batch, GEN7_MI_BATCH_BUFFER_END, bbe);
+   anv_batch_emit(&batch, GEN7_MI_NOOP, noop);
 
    return anv_device_submit_simple_batch(device, &batch);
 }
@@ -1099,7 +1173,7 @@ VkResult anv_AllocateMemory(
 
    /* FINISHME: Fail if allocation request exceeds heap size. */
 
-   mem = anv_alloc2(&device->alloc, pAllocator, sizeof(*mem), 8,
+   mem = vk_alloc2(&device->alloc, pAllocator, sizeof(*mem), 8,
                     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    if (mem == NULL)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -1118,7 +1192,7 @@ VkResult anv_AllocateMemory(
    return VK_SUCCESS;
 
  fail:
-   anv_free2(&device->alloc, pAllocator, mem);
+   vk_free2(&device->alloc, pAllocator, mem);
 
    return result;
 }
@@ -1140,7 +1214,7 @@ void anv_FreeMemory(
    if (mem->bo.gem_handle != 0)
       anv_gem_close(device, mem->bo.gem_handle);
 
-   anv_free2(&device->alloc, pAllocator, mem);
+   vk_free2(&device->alloc, pAllocator, mem);
 }
 
 VkResult anv_MapMemory(
@@ -1340,26 +1414,6 @@ VkResult anv_BindBufferMemory(
    return VK_SUCCESS;
 }
 
-VkResult anv_BindImageMemory(
-    VkDevice                                    device,
-    VkImage                                     _image,
-    VkDeviceMemory                              _memory,
-    VkDeviceSize                                memoryOffset)
-{
-   ANV_FROM_HANDLE(anv_device_memory, mem, _memory);
-   ANV_FROM_HANDLE(anv_image, image, _image);
-
-   if (mem) {
-      image->bo = &mem->bo;
-      image->offset = memoryOffset;
-   } else {
-      image->bo = NULL;
-      image->offset = 0;
-   }
-
-   return VK_SUCCESS;
-}
-
 VkResult anv_QueueBindSparse(
     VkQueue                                     queue,
     uint32_t                                    bindInfoCount,
@@ -1376,35 +1430,33 @@ VkResult anv_CreateFence(
     VkFence*                                    pFence)
 {
    ANV_FROM_HANDLE(anv_device, device, _device);
+   struct anv_bo fence_bo;
    struct anv_fence *fence;
    struct anv_batch batch;
    VkResult result;
 
-   const uint32_t fence_size = 128;
-
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
 
-   fence = anv_alloc2(&device->alloc, pAllocator, sizeof(*fence), 8,
-                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-   if (fence == NULL)
-      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
-   result = anv_bo_init_new(&fence->bo, device, fence_size);
+   result = anv_bo_pool_alloc(&device->batch_bo_pool, &fence_bo, 4096);
    if (result != VK_SUCCESS)
-      goto fail;
+      return result;
 
-   fence->bo.map =
-      anv_gem_mmap(device, fence->bo.gem_handle, 0, fence->bo.size, 0);
-   batch.next = batch.start = fence->bo.map;
+   /* Fences are small.  Just store the CPU data structure in the BO. */
+   fence = fence_bo.map;
+   fence->bo = fence_bo;
+
+   /* Place the batch after the CPU data but on its own cache line. */
+   const uint32_t batch_offset = align_u32(sizeof(*fence), CACHELINE_SIZE);
+   batch.next = batch.start = fence->bo.map + batch_offset;
    batch.end = fence->bo.map + fence->bo.size;
-   anv_batch_emit(&batch, GEN7_MI_BATCH_BUFFER_END);
-   anv_batch_emit(&batch, GEN7_MI_NOOP);
+   anv_batch_emit(&batch, GEN7_MI_BATCH_BUFFER_END, bbe);
+   anv_batch_emit(&batch, GEN7_MI_NOOP, noop);
 
    if (!device->info.has_llc) {
-      assert(((uintptr_t) fence->bo.map & CACHELINE_MASK) == 0);
-      assert(batch.next - fence->bo.map <= CACHELINE_SIZE);
+      assert(((uintptr_t) batch.start & CACHELINE_MASK) == 0);
+      assert(batch.next - batch.start <= CACHELINE_SIZE);
       __builtin_ia32_mfence();
-      __builtin_ia32_clflush(fence->bo.map);
+      __builtin_ia32_clflush(batch.start);
    }
 
    fence->exec2_objects[0].handle = fence->bo.gem_handle;
@@ -1418,8 +1470,8 @@ VkResult anv_CreateFence(
 
    fence->execbuf.buffers_ptr = (uintptr_t) fence->exec2_objects;
    fence->execbuf.buffer_count = 1;
-   fence->execbuf.batch_start_offset = 0;
-   fence->execbuf.batch_len = batch.next - fence->bo.map;
+   fence->execbuf.batch_start_offset = batch.start - fence->bo.map;
+   fence->execbuf.batch_len = batch.next - batch.start;
    fence->execbuf.cliprects_ptr = 0;
    fence->execbuf.num_cliprects = 0;
    fence->execbuf.DR1 = 0;
@@ -1435,11 +1487,6 @@ VkResult anv_CreateFence(
    *pFence = anv_fence_to_handle(fence);
 
    return VK_SUCCESS;
-
- fail:
-   anv_free2(&device->alloc, pAllocator, fence);
-
-   return result;
 }
 
 void anv_DestroyFence(
@@ -1450,9 +1497,8 @@ void anv_DestroyFence(
    ANV_FROM_HANDLE(anv_device, device, _device);
    ANV_FROM_HANDLE(anv_fence, fence, _fence);
 
-   anv_gem_munmap(fence->bo.map, fence->bo.size);
-   anv_gem_close(device, fence->bo.gem_handle);
-   anv_free2(&device->alloc, pAllocator, fence);
+   assert(fence->bo.map == fence);
+   anv_bo_pool_free(&device->batch_bo_pool, &fence->bo);
 }
 
 VkResult anv_ResetFences(
@@ -1659,7 +1705,7 @@ VkResult anv_CreateBuffer(
 
    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
 
-   buffer = anv_alloc2(&device->alloc, pAllocator, sizeof(*buffer), 8,
+   buffer = vk_alloc2(&device->alloc, pAllocator, sizeof(*buffer), 8,
                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    if (buffer == NULL)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -1682,7 +1728,7 @@ void anv_DestroyBuffer(
    ANV_FROM_HANDLE(anv_device, device, _device);
    ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
 
-   anv_free2(&device->alloc, pAllocator, buffer);
+   vk_free2(&device->alloc, pAllocator, buffer);
 }
 
 void
@@ -1690,24 +1736,12 @@ anv_fill_buffer_surface_state(struct anv_device *device, struct anv_state state,
                               enum isl_format format,
                               uint32_t offset, uint32_t range, uint32_t stride)
 {
-   switch (device->info.gen) {
-   case 7:
-      if (device->info.is_haswell)
-         gen75_fill_buffer_surface_state(state.map, format, offset, range,
-                                         stride);
-      else
-         gen7_fill_buffer_surface_state(state.map, format, offset, range,
-                                        stride);
-      break;
-   case 8:
-      gen8_fill_buffer_surface_state(state.map, format, offset, range, stride);
-      break;
-   case 9:
-      gen9_fill_buffer_surface_state(state.map, format, offset, range, stride);
-      break;
-   default:
-      unreachable("unsupported gen\n");
-   }
+   isl_buffer_fill_state(&device->isl_dev, state.map,
+                         .address = offset,
+                         .mocs = device->default_mocs,
+                         .size = range,
+                         .format = format,
+                         .stride = stride);
 
    if (!device->info.has_llc)
       anv_state_clflush(state);
@@ -1721,7 +1755,7 @@ void anv_DestroySampler(
    ANV_FROM_HANDLE(anv_device, device, _device);
    ANV_FROM_HANDLE(anv_sampler, sampler, _sampler);
 
-   anv_free2(&device->alloc, pAllocator, sampler);
+   vk_free2(&device->alloc, pAllocator, sampler);
 }
 
 VkResult anv_CreateFramebuffer(
@@ -1737,7 +1771,7 @@ VkResult anv_CreateFramebuffer(
 
    size_t size = sizeof(*framebuffer) +
                  sizeof(struct anv_image_view *) * pCreateInfo->attachmentCount;
-   framebuffer = anv_alloc2(&device->alloc, pAllocator, size, 8,
+   framebuffer = vk_alloc2(&device->alloc, pAllocator, size, 8,
                             VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    if (framebuffer == NULL)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -1765,25 +1799,5 @@ void anv_DestroyFramebuffer(
    ANV_FROM_HANDLE(anv_device, device, _device);
    ANV_FROM_HANDLE(anv_framebuffer, fb, _fb);
 
-   anv_free2(&device->alloc, pAllocator, fb);
-}
-
-void vkCmdDbgMarkerBegin(
-    VkCommandBuffer                              commandBuffer,
-    const char*                                 pMarker)
-   __attribute__ ((visibility ("default")));
-
-void vkCmdDbgMarkerEnd(
-   VkCommandBuffer                              commandBuffer)
-   __attribute__ ((visibility ("default")));
-
-void vkCmdDbgMarkerBegin(
-    VkCommandBuffer                              commandBuffer,
-    const char*                                 pMarker)
-{
-}
-
-void vkCmdDbgMarkerEnd(
-    VkCommandBuffer                              commandBuffer)
-{
+   vk_free2(&device->alloc, pAllocator, fb);
 }