[Mesa-dev] [PATCH] anv/i965: drop copies of gen_device_info fields into brw_context

Lionel Landwerlin lionel.g.landwerlin at intel.com
Fri Jun 23 16:48:22 UTC 2017


This removes a few fields in brw_context that are copies of what's
already in gen_device_info.

v2: Retain has_separate_stencil in brw_context (Jason/Lionel)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
---
 src/intel/vulkan/genX_pipeline.c                  |   5 +-
 src/mesa/drivers/dri/i965/brw_binding_tables.c    |   6 +-
 src/mesa/drivers/dri/i965/brw_blorp.c             |  24 +-
 src/mesa/drivers/dri/i965/brw_clear.c             |   8 +-
 src/mesa/drivers/dri/i965/brw_clip.c              |   3 +-
 src/mesa/drivers/dri/i965/brw_clip_state.c        |   7 +-
 src/mesa/drivers/dri/i965/brw_compute.c           |  14 +-
 src/mesa/drivers/dri/i965/brw_context.c           |  94 ++-
 src/mesa/drivers/dri/i965/brw_context.h           |  17 -
 src/mesa/drivers/dri/i965/brw_cs.c                |   2 +-
 src/mesa/drivers/dri/i965/brw_curbe.c             |   4 +-
 src/mesa/drivers/dri/i965/brw_draw.c              |  19 +-
 src/mesa/drivers/dri/i965/brw_draw_upload.c       |  22 +-
 src/mesa/drivers/dri/i965/brw_ff_gs.c             |  13 +-
 src/mesa/drivers/dri/i965/brw_formatquery.c       |   5 +-
 src/mesa/drivers/dri/i965/brw_gs.c                |   3 +-
 src/mesa/drivers/dri/i965/brw_gs_state.c          |   3 +-
 src/mesa/drivers/dri/i965/brw_link.cpp            |   9 +-
 src/mesa/drivers/dri/i965/brw_meta_util.c         |   9 +-
 src/mesa/drivers/dri/i965/brw_misc_state.c        |  65 +-
 src/mesa/drivers/dri/i965/brw_performance_query.c |  14 +-
 src/mesa/drivers/dri/i965/brw_pipe_control.c      |  46 +-
 src/mesa/drivers/dri/i965/brw_primitive_restart.c |   3 +-
 src/mesa/drivers/dri/i965/brw_program.c           |  11 +-
 src/mesa/drivers/dri/i965/brw_program_cache.c     |  31 +-
 src/mesa/drivers/dri/i965/brw_queryobj.c          |  30 +-
 src/mesa/drivers/dri/i965/brw_sampler_state.c     | 761 ++++++++++++++++++++++
 src/mesa/drivers/dri/i965/brw_state_upload.c      |  33 +-
 src/mesa/drivers/dri/i965/brw_surface_formats.c   |   9 +-
 src/mesa/drivers/dri/i965/brw_tcs.c               |  10 +-
 src/mesa/drivers/dri/i965/brw_tex_layout.c        |  60 +-
 src/mesa/drivers/dri/i965/brw_urb.c               |   6 +-
 src/mesa/drivers/dri/i965/brw_vs.c                |   8 +-
 src/mesa/drivers/dri/i965/brw_wm.c                |  33 +-
 src/mesa/drivers/dri/i965/brw_wm_state.c          |   2 +-
 src/mesa/drivers/dri/i965/brw_wm_surface_state.c  |  49 +-
 src/mesa/drivers/dri/i965/gen6_constant_state.c   |   3 +-
 src/mesa/drivers/dri/i965/gen6_queryobj.c         |  17 +-
 src/mesa/drivers/dri/i965/gen6_sol.c              |   6 +-
 src/mesa/drivers/dri/i965/gen7_l3_state.c         |  11 +-
 src/mesa/drivers/dri/i965/gen7_misc_state.c       |   3 +-
 src/mesa/drivers/dri/i965/gen7_sol_state.c        |   9 +-
 src/mesa/drivers/dri/i965/gen7_urb.c              |  13 +-
 src/mesa/drivers/dri/i965/gen8_depth_state.c      |   9 +-
 src/mesa/drivers/dri/i965/genX_state_upload.c     |  16 +-
 src/mesa/drivers/dri/i965/hsw_queryobj.c          |  10 +-
 src/mesa/drivers/dri/i965/hsw_sol.c               |   9 +-
 src/mesa/drivers/dri/i965/intel_batchbuffer.c     |  61 +-
 src/mesa/drivers/dri/i965/intel_batchbuffer.h     |   4 +-
 src/mesa/drivers/dri/i965/intel_blit.c            |  27 +-
 src/mesa/drivers/dri/i965/intel_copy_image.c      |   3 +-
 src/mesa/drivers/dri/i965/intel_extensions.c      |  37 +-
 src/mesa/drivers/dri/i965/intel_fbo.c             |  16 +-
 src/mesa/drivers/dri/i965/intel_mipmap_tree.c     | 114 ++--
 src/mesa/drivers/dri/i965/intel_pixel_read.c      |   5 +-
 src/mesa/drivers/dri/i965/intel_tex.c             |   3 +-
 src/mesa/drivers/dri/i965/intel_tex_image.c       |  13 +-
 src/mesa/drivers/dri/i965/intel_tex_subimage.c    |   5 +-
 src/mesa/drivers/dri/i965/intel_tex_validate.c    |   3 +-
 59 files changed, 1393 insertions(+), 442 deletions(-)
 create mode 100644 src/mesa/drivers/dri/i965/brw_sampler_state.c

diff --git a/src/intel/vulkan/genX_pipeline.c b/src/intel/vulkan/genX_pipeline.c
index 55db5339d67..a2bd5a0cd89 100644
--- a/src/intel/vulkan/genX_pipeline.c
+++ b/src/intel/vulkan/genX_pipeline.c
@@ -1687,6 +1687,9 @@ genX(graphics_pipeline_create)(
 
 #if 0
    /* From gen7_vs_state.c */
+   const struct anv_physical_device *physical_device =
+      &device->instance->physicalDevice;
+   const struct gen_device_info *devinfo = &physical_device->info;
 
    /**
     * From Graphics BSpec: 3D-Media-GPGPU Engine > 3D Pipeline Stages >
@@ -1700,7 +1703,7 @@ genX(graphics_pipeline_create)(
     * whole fixed function pipeline" means to emit a PIPE_CONTROL with the "CS
     * Stall" bit set.
     */
-   if (!brw->is_haswell && !brw->is_baytrail)
+   if (!devinfo->is_haswell && !devinfo->is_baytrail)
       gen7_emit_vs_workaround_flush(brw);
 #endif
 
diff --git a/src/mesa/drivers/dri/i965/brw_binding_tables.c b/src/mesa/drivers/dri/i965/brw_binding_tables.c
index c0a763d0aeb..1aa9b832954 100644
--- a/src/mesa/drivers/dri/i965/brw_binding_tables.c
+++ b/src/mesa/drivers/dri/i965/brw_binding_tables.c
@@ -56,9 +56,11 @@ brw_upload_binding_table(struct brw_context *brw,
                          const struct brw_stage_prog_data *prog_data,
                          struct brw_stage_state *stage_state)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    if (prog_data->binding_table.size_bytes == 0) {
       /* There are no surfaces; skip making the binding table altogether. */
-      if (stage_state->bind_bo_offset == 0 && brw->gen < 9)
+      if (stage_state->bind_bo_offset == 0 && devinfo->gen < 9)
          return;
 
       stage_state->bind_bo_offset = 0;
@@ -82,7 +84,7 @@ brw_upload_binding_table(struct brw_context *brw,
 
    brw->ctx.NewDriverState |= BRW_NEW_BINDING_TABLE_POINTERS;
 
-   if (brw->gen >= 7) {
+   if (devinfo->gen >= 7) {
       BEGIN_BATCH(2);
       OUT_BATCH(packet_name << 16 | (2 - 2));
       /* Align SurfaceStateOffset[16:6] format to [15:5] PS Binding Table field
diff --git a/src/mesa/drivers/dri/i965/brw_blorp.c b/src/mesa/drivers/dri/i965/brw_blorp.c
index 111c6712f98..dc1e2bdc236 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp.c
+++ b/src/mesa/drivers/dri/i965/brw_blorp.c
@@ -66,13 +66,15 @@ brw_blorp_upload_shader(struct blorp_context *blorp,
 void
 brw_blorp_init(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    blorp_init(&brw->blorp, brw, &brw->isl_dev);
 
    brw->blorp.compiler = brw->screen->compiler;
 
-   switch (brw->gen) {
+   switch (devinfo->gen) {
    case 4:
-      if (brw->is_g4x) {
+      if (devinfo->is_g4x) {
          brw->blorp.exec = gen45_blorp_exec;
       } else {
          brw->blorp.exec = gen4_blorp_exec;
@@ -91,7 +93,7 @@ brw_blorp_init(struct brw_context *brw)
       brw->blorp.mocs.tex = GEN7_MOCS_L3;
       brw->blorp.mocs.rb = GEN7_MOCS_L3;
       brw->blorp.mocs.vb = GEN7_MOCS_L3;
-      if (brw->is_haswell) {
+      if (devinfo->is_haswell) {
          brw->blorp.exec = gen75_blorp_exec;
       } else {
          brw->blorp.exec = gen7_blorp_exec;
@@ -308,6 +310,8 @@ brw_blorp_blit_miptrees(struct brw_context *brw,
                         GLenum filter, bool mirror_x, bool mirror_y,
                         bool decode_srgb, bool encode_srgb)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* Blorp operates in logical layers */
    src_layer = physical_to_logical_layer(src_mt, src_layer);
    dst_layer = physical_to_logical_layer(dst_mt, dst_layer);
@@ -336,7 +340,7 @@ brw_blorp_blit_miptrees(struct brw_context *brw,
     * shouldn't affect rendering correctness, since the destination format is
     * R32_FLOAT, so only the contents of the red channel matters.
     */
-   if (brw->gen == 6 &&
+   if (devinfo->gen == 6 &&
        src_mt->num_samples > 1 && dst_mt->num_samples <= 1 &&
        src_mt->format == dst_mt->format &&
        (dst_format == MESA_FORMAT_L_FLOAT32 ||
@@ -473,6 +477,7 @@ try_blorp_blit(struct brw_context *brw,
                GLfloat dstX0, GLfloat dstY0, GLfloat dstX1, GLfloat dstY1,
                GLenum filter, GLbitfield buffer_bit)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
 
    /* Sync up the state of window system buffers.  We need to do this before
@@ -538,7 +543,7 @@ try_blorp_blit(struct brw_context *brw,
       /* Blorp doesn't support combined depth stencil which is all we have
        * prior to gen6.
        */
-      if (brw->gen < 6)
+      if (devinfo->gen < 6)
          return false;
 
       src_irb =
@@ -1077,6 +1082,7 @@ intel_hiz_exec(struct brw_context *brw, struct intel_mipmap_tree *mt,
    assert(intel_miptree_level_has_hiz(mt, level));
    assert(op != BLORP_HIZ_OP_NONE);
    const char *opname = NULL;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    switch (op) {
    case BLORP_HIZ_OP_DEPTH_RESOLVE:
@@ -1102,7 +1108,7 @@ intel_hiz_exec(struct brw_context *brw, struct intel_mipmap_tree *mt,
     * different value is written into the HiZ surface.
     */
    if (op == BLORP_HIZ_OP_DEPTH_CLEAR || op == BLORP_HIZ_OP_HIZ_RESOLVE) {
-      if (brw->gen == 6) {
+      if (devinfo->gen == 6) {
          /* From the Sandy Bridge PRM, volume 2 part 1, page 313:
           *
           *   "If other rendering operations have preceded this clear, a
@@ -1114,7 +1120,7 @@ intel_hiz_exec(struct brw_context *brw, struct intel_mipmap_tree *mt,
                                       PIPE_CONTROL_RENDER_TARGET_FLUSH |
                                       PIPE_CONTROL_DEPTH_CACHE_FLUSH |
                                       PIPE_CONTROL_CS_STALL);
-      } else if (brw->gen >= 7) {
+      } else if (devinfo->gen >= 7) {
          /*
           * From the Ivybridge PRM, volume 2, "Depth Buffer Clear":
           *
@@ -1163,7 +1169,7 @@ intel_hiz_exec(struct brw_context *brw, struct intel_mipmap_tree *mt,
     * different value is written into the HiZ surface.
     */
    if (op == BLORP_HIZ_OP_DEPTH_CLEAR || op == BLORP_HIZ_OP_HIZ_RESOLVE) {
-      if (brw->gen == 6) {
+      if (devinfo->gen == 6) {
          /* From the Sandy Bridge PRM, volume 2 part 1, page 314:
           *
           *     "DevSNB, DevSNB-B{W/A}]: Depth buffer clear pass must be
@@ -1176,7 +1182,7 @@ intel_hiz_exec(struct brw_context *brw, struct intel_mipmap_tree *mt,
          brw_emit_pipe_control_flush(brw,
                                      PIPE_CONTROL_DEPTH_CACHE_FLUSH |
                                      PIPE_CONTROL_CS_STALL);
-      } else if (brw->gen >= 8) {
+      } else if (devinfo->gen >= 8) {
          /*
           * From the Broadwell PRM, volume 7, "Depth Buffer Clear":
           *
diff --git a/src/mesa/drivers/dri/i965/brw_clear.c b/src/mesa/drivers/dri/i965/brw_clear.c
index 72453d16eb1..55124ace249 100644
--- a/src/mesa/drivers/dri/i965/brw_clear.c
+++ b/src/mesa/drivers/dri/i965/brw_clear.c
@@ -107,8 +107,9 @@ brw_fast_clear_depth(struct gl_context *ctx)
       intel_get_renderbuffer(fb, BUFFER_DEPTH);
    struct intel_mipmap_tree *mt = depth_irb->mt;
    struct gl_renderbuffer_attachment *depth_att = &fb->Attachment[BUFFER_DEPTH];
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
-   if (brw->gen < 6)
+   if (devinfo->gen < 6)
       return false;
 
    if (!intel_renderbuffer_has_hiz(depth_irb))
@@ -148,7 +149,7 @@ brw_fast_clear_depth(struct gl_context *ctx)
        *        width of the map (LOD0) is not multiple of 16, fast clear
        *        optimization must be disabled.
        */
-      if (brw->gen == 6 &&
+      if (devinfo->gen == 6 &&
           (minify(mt->physical_width0,
                   depth_irb->mt_level - mt->first_level) % 16) != 0)
 	 return false;
@@ -201,6 +202,7 @@ brw_clear(struct gl_context *ctx, GLbitfield mask)
    struct brw_context *brw = brw_context(ctx);
    struct gl_framebuffer *fb = ctx->DrawBuffer;
    bool partial_clear = ctx->Scissor.EnableFlags && !noop_scissor(fb);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    if (!_mesa_check_conditional_render(ctx))
       return;
@@ -234,7 +236,7 @@ brw_clear(struct gl_context *ctx, GLbitfield mask)
       mask &= ~BUFFER_BITS_COLOR;
    }
 
-   if (brw->gen >= 6 && (mask & BUFFER_BITS_DEPTH_STENCIL)) {
+   if (devinfo->gen >= 6 && (mask & BUFFER_BITS_DEPTH_STENCIL)) {
       brw_blorp_clear_depth_stencil(brw, fb, mask, partial_clear);
       debug_mask("blorp depth/stencil", mask & BUFFER_BITS_DEPTH_STENCIL);
       mask &= ~BUFFER_BITS_DEPTH_STENCIL;
diff --git a/src/mesa/drivers/dri/i965/brw_clip.c b/src/mesa/drivers/dri/i965/brw_clip.c
index e3023e50e9c..3a7c4829ed7 100644
--- a/src/mesa/drivers/dri/i965/brw_clip.c
+++ b/src/mesa/drivers/dri/i965/brw_clip.c
@@ -69,6 +69,7 @@ static void compile_clip_prog( struct brw_context *brw,
 void
 brw_upload_clip_prog(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    struct brw_clip_prog_key key;
 
@@ -113,7 +114,7 @@ brw_upload_clip_prog(struct brw_context *brw)
    if (ctx->Transform.ClipPlanesEnabled)
       key.nr_userclip = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1;
 
-   if (brw->gen == 5)
+   if (devinfo->gen == 5)
        key.clip_mode = BRW_CLIP_MODE_KERNEL_CLIP;
    else
        key.clip_mode = BRW_CLIP_MODE_NORMAL;
diff --git a/src/mesa/drivers/dri/i965/brw_clip_state.c b/src/mesa/drivers/dri/i965/brw_clip_state.c
index 8f22c0ff673..d5b20247b5f 100644
--- a/src/mesa/drivers/dri/i965/brw_clip_state.c
+++ b/src/mesa/drivers/dri/i965/brw_clip_state.c
@@ -38,6 +38,7 @@
 static void
 brw_upload_clip_unit(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    struct brw_clip_unit_state *clip;
 
@@ -80,7 +81,7 @@ brw_upload_clip_unit(struct brw_context *brw)
       /* Although up to 16 concurrent Clip threads are allowed on Ironlake,
        * only 2 threads can output VUEs at a time.
        */
-      if (brw->gen == 5)
+      if (devinfo->gen == 5)
          clip->thread4.max_threads = 16 - 1;
       else
          clip->thread4.max_threads = 2 - 1;
@@ -90,7 +91,7 @@ brw_upload_clip_unit(struct brw_context *brw)
    }
 
    /* _NEW_TRANSFORM */
-   if (brw->gen == 5 || brw->is_g4x)
+   if (devinfo->gen == 5 || devinfo->is_g4x)
       clip->clip5.userclip_enable_flags = ctx->Transform.ClipPlanesEnabled;
    else
       /* Up to 6 actual clip flags, plus the 7th for negative RHW workaround. */
@@ -121,7 +122,7 @@ brw_upload_clip_unit(struct brw_context *brw)
       clip->clip5.api_mode = BRW_CLIP_API_OGL;
    clip->clip5.clip_mode = brw->clip.prog_data->clip_mode;
 
-   if (brw->is_g4x)
+   if (devinfo->is_g4x)
       clip->clip5.negative_w_clip_test = 1;
 
    clip->viewport_xmin = -1;
diff --git a/src/mesa/drivers/dri/i965/brw_compute.c b/src/mesa/drivers/dri/i965/brw_compute.c
index 80461536359..50131b21e0b 100644
--- a/src/mesa/drivers/dri/i965/brw_compute.c
+++ b/src/mesa/drivers/dri/i965/brw_compute.c
@@ -37,6 +37,7 @@
 static void
 prepare_indirect_gpgpu_walker(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    GLintptr indirect_offset = brw->compute.num_work_groups_offset;
    struct brw_bo *bo = brw->compute.num_work_groups_bo;
 
@@ -50,7 +51,7 @@ prepare_indirect_gpgpu_walker(struct brw_context *brw)
                          I915_GEM_DOMAIN_VERTEX, 0,
                          indirect_offset + 8);
 
-   if (brw->gen > 7)
+   if (devinfo->gen > 7)
       return;
 
    /* Clear upper 32-bits of SRC0 and all 64-bits of SRC1 */
@@ -115,6 +116,7 @@ prepare_indirect_gpgpu_walker(struct brw_context *brw)
 static void
 brw_emit_gpgpu_walker(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    const struct brw_cs_prog_data *prog_data =
       brw_cs_prog_data(brw->cs.base.prog_data);
 
@@ -126,7 +128,7 @@ brw_emit_gpgpu_walker(struct brw_context *brw)
    } else {
       indirect_flag =
          GEN7_GPGPU_INDIRECT_PARAMETER_ENABLE |
-         (brw->gen == 7 ? GEN7_GPGPU_PREDICATE_ENABLE : 0);
+         (devinfo->gen == 7 ? GEN7_GPGPU_PREDICATE_ENABLE : 0);
       prepare_indirect_gpgpu_walker(brw);
    }
 
@@ -141,11 +143,11 @@ brw_emit_gpgpu_walker(struct brw_context *brw)
    if (right_non_aligned != 0)
       right_mask >>= (simd_size - right_non_aligned);
 
-   uint32_t dwords = brw->gen < 8 ? 11 : 15;
+   uint32_t dwords = devinfo->gen < 8 ? 11 : 15;
    BEGIN_BATCH(dwords);
    OUT_BATCH(GPGPU_WALKER << 16 | (dwords - 2) | indirect_flag);
    OUT_BATCH(0);
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       OUT_BATCH(0);                     /* Indirect Data Length */
       OUT_BATCH(0);                     /* Indirect Data Start Address */
    }
@@ -153,11 +155,11 @@ brw_emit_gpgpu_walker(struct brw_context *brw)
    OUT_BATCH(SET_FIELD(simd_size / 16, GPGPU_WALKER_SIMD_SIZE) |
              SET_FIELD(thread_width_max - 1, GPGPU_WALKER_THREAD_WIDTH_MAX));
    OUT_BATCH(0);                        /* Thread Group ID Starting X */
-   if (brw->gen >= 8)
+   if (devinfo->gen >= 8)
       OUT_BATCH(0);                     /* MBZ */
    OUT_BATCH(num_groups[0]);            /* Thread Group ID X Dimension */
    OUT_BATCH(0);                        /* Thread Group ID Starting Y */
-   if (brw->gen >= 8)
+   if (devinfo->gen >= 8)
       OUT_BATCH(0);                     /* MBZ */
    OUT_BATCH(num_groups[1]);            /* Thread Group ID Y Dimension */
    OUT_BATCH(0);                        /* Thread Group ID Starting/Resume Z */
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index e921a41c827..d5c1330d6a9 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -195,6 +195,7 @@ intel_update_state(struct gl_context * ctx)
    struct brw_context *brw = brw_context(ctx);
    struct intel_texture_object *tex_obj;
    struct intel_renderbuffer *depth_irb;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    if (ctx->swrast_context)
       _swrast_InvalidateState(ctx, new_state);
@@ -246,7 +247,7 @@ intel_update_state(struct gl_context * ctx)
       intel_miptree_prepare_texture(brw, tex_obj->mt, tex_obj->_Format,
                                     &aux_supported);
 
-      if (!aux_supported && brw->gen >= 9 &&
+      if (!aux_supported && devinfo->gen >= 9 &&
           intel_disable_rb_aux_buffer(brw, tex_obj->mt->bo)) {
          perf_debug("Sampling renderbuffer with non-compressible format - "
                     "turning off compression");
@@ -384,6 +385,8 @@ static void
 brw_init_driver_functions(struct brw_context *brw,
                           struct dd_function_table *functions)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    _mesa_init_driver_functions(functions);
 
    /* GLX uses DRI2 invalidate events to handle window resizing.
@@ -415,9 +418,9 @@ brw_init_driver_functions(struct brw_context *brw,
 
    brwInitFragProgFuncs( functions );
    brw_init_common_queryobj_functions(functions);
-   if (brw->gen >= 8 || brw->is_haswell)
+   if (devinfo->gen >= 8 || devinfo->is_haswell)
       hsw_init_queryobj_functions(functions);
-   else if (brw->gen >= 6)
+   else if (devinfo->gen >= 6)
       gen6_init_queryobj_functions(functions);
    else
       gen4_init_queryobj_functions(functions);
@@ -433,7 +436,7 @@ brw_init_driver_functions(struct brw_context *brw,
       functions->EndTransformFeedback = hsw_end_transform_feedback;
       functions->PauseTransformFeedback = hsw_pause_transform_feedback;
       functions->ResumeTransformFeedback = hsw_resume_transform_feedback;
-   } else if (brw->gen >= 7) {
+   } else if (devinfo->gen >= 7) {
       functions->BeginTransformFeedback = gen7_begin_transform_feedback;
       functions->EndTransformFeedback = gen7_end_transform_feedback;
       functions->PauseTransformFeedback = gen7_pause_transform_feedback;
@@ -449,7 +452,7 @@ brw_init_driver_functions(struct brw_context *brw,
          brw_get_transform_feedback_vertex_count;
    }
 
-   if (brw->gen >= 6)
+   if (devinfo->gen >= 6)
       functions->GetSamplePosition = gen6_get_sample_position;
 }
 
@@ -458,12 +461,13 @@ brw_initialize_context_constants(struct brw_context *brw)
 {
    struct gl_context *ctx = &brw->ctx;
    const struct brw_compiler *compiler = brw->screen->compiler;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    const bool stage_exists[MESA_SHADER_STAGES] = {
       [MESA_SHADER_VERTEX] = true,
-      [MESA_SHADER_TESS_CTRL] = brw->gen >= 7,
-      [MESA_SHADER_TESS_EVAL] = brw->gen >= 7,
-      [MESA_SHADER_GEOMETRY] = brw->gen >= 6,
+      [MESA_SHADER_TESS_CTRL] = devinfo->gen >= 7,
+      [MESA_SHADER_TESS_EVAL] = devinfo->gen >= 7,
+      [MESA_SHADER_GEOMETRY] = devinfo->gen >= 6,
       [MESA_SHADER_FRAGMENT] = true,
       [MESA_SHADER_COMPUTE] =
          ((ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGL_CORE) &&
@@ -480,7 +484,7 @@ brw_initialize_context_constants(struct brw_context *brw)
    }
 
    unsigned max_samplers =
-      brw->gen >= 8 || brw->is_haswell ? BRW_MAX_TEX_UNIT : 16;
+      devinfo->gen >= 8 || devinfo->is_haswell ? BRW_MAX_TEX_UNIT : 16;
 
    ctx->Const.MaxDualSourceDrawBuffers = 1;
    ctx->Const.MaxDrawBuffers = BRW_MAX_DRAW_BUFFERS;
@@ -506,7 +510,7 @@ brw_initialize_context_constants(struct brw_context *brw)
 
    ctx->Const.MaxTextureCoordUnits = 8; /* Mesa limit */
    ctx->Const.MaxImageUnits = MAX_IMAGE_UNITS;
-   if (brw->gen >= 7) {
+   if (devinfo->gen >= 7) {
       ctx->Const.MaxRenderbufferSize = 16384;
       ctx->Const.MaxTextureLevels = MIN2(15 /* 16384 */, MAX_TEXTURE_LEVELS);
       ctx->Const.MaxCubeTextureLevels = 15; /* 16384 */
@@ -516,17 +520,17 @@ brw_initialize_context_constants(struct brw_context *brw)
       ctx->Const.MaxCubeTextureLevels = 14; /* 8192 */
    }
    ctx->Const.Max3DTextureLevels = 12; /* 2048 */
-   ctx->Const.MaxArrayTextureLayers = brw->gen >= 7 ? 2048 : 512;
+   ctx->Const.MaxArrayTextureLayers = devinfo->gen >= 7 ? 2048 : 512;
    ctx->Const.MaxTextureMbytes = 1536;
-   ctx->Const.MaxTextureRectSize = brw->gen >= 7 ? 16384 : 8192;
+   ctx->Const.MaxTextureRectSize = devinfo->gen >= 7 ? 16384 : 8192;
    ctx->Const.MaxTextureMaxAnisotropy = 16.0;
    ctx->Const.MaxTextureLodBias = 15.0;
    ctx->Const.StripTextureBorder = true;
-   if (brw->gen >= 7) {
+   if (devinfo->gen >= 7) {
       ctx->Const.MaxProgramTextureGatherComponents = 4;
       ctx->Const.MinProgramTextureGatherOffset = -32;
       ctx->Const.MaxProgramTextureGatherOffset = 31;
-   } else if (brw->gen == 6) {
+   } else if (devinfo->gen == 6) {
       ctx->Const.MaxProgramTextureGatherComponents = 1;
       ctx->Const.MinProgramTextureGatherOffset = -8;
       ctx->Const.MaxProgramTextureGatherOffset = 7;
@@ -625,7 +629,7 @@ brw_initialize_context_constants(struct brw_context *brw)
 
    ctx->Const.MinLineWidth = 1.0;
    ctx->Const.MinLineWidthAA = 1.0;
-   if (brw->gen >= 6) {
+   if (devinfo->gen >= 6) {
       ctx->Const.MaxLineWidth = 7.375;
       ctx->Const.MaxLineWidthAA = 7.375;
       ctx->Const.LineWidthGranularity = 0.125;
@@ -648,11 +652,11 @@ brw_initialize_context_constants(struct brw_context *brw)
    ctx->Const.MaxPointSizeAA = 255.0;
    ctx->Const.PointSizeGranularity = 1.0;
 
-   if (brw->gen >= 5 || brw->is_g4x)
+   if (devinfo->gen >= 5 || devinfo->is_g4x)
       ctx->Const.MaxClipPlanes = 8;
 
    ctx->Const.GLSLTessLevelsAsInputs = true;
-   ctx->Const.LowerTCSPatchVerticesIn = brw->gen >= 8;
+   ctx->Const.LowerTCSPatchVerticesIn = devinfo->gen >= 8;
    ctx->Const.LowerTESPatchVerticesIn = true;
    ctx->Const.PrimitiveRestartForPatches = true;
 
@@ -703,7 +707,7 @@ brw_initialize_context_constants(struct brw_context *brw)
     * that affect provoking vertex decision. Always use last vertex
     * convention for quad primitive which works as expected for now.
     */
-   if (brw->gen >= 6)
+   if (devinfo->gen >= 6)
       ctx->Const.QuadsFollowProvokingVertexConvention = false;
 
    ctx->Const.NativeIntegers = true;
@@ -749,7 +753,7 @@ brw_initialize_context_constants(struct brw_context *brw)
    ctx->Const.TextureBufferOffsetAlignment = 16;
    ctx->Const.MaxTextureBufferSize = 128 * 1024 * 1024;
 
-   if (brw->gen >= 6) {
+   if (devinfo->gen >= 6) {
       ctx->Const.MaxVarying = 32;
       ctx->Const.Program[MESA_SHADER_VERTEX].MaxOutputComponents = 128;
       ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxInputComponents = 64;
@@ -767,13 +771,13 @@ brw_initialize_context_constants(struct brw_context *brw)
          brw->screen->compiler->glsl_compiler_options[i];
    }
 
-   if (brw->gen >= 7) {
+   if (devinfo->gen >= 7) {
       ctx->Const.MaxViewportWidth = 32768;
       ctx->Const.MaxViewportHeight = 32768;
    }
 
    /* ARB_viewport_array, OES_viewport_array */
-   if (brw->gen >= 6) {
+   if (devinfo->gen >= 6) {
       ctx->Const.MaxViewports = GEN6_NUM_VIEWPORTS;
       ctx->Const.ViewportSubpixelBits = 0;
 
@@ -784,7 +788,7 @@ brw_initialize_context_constants(struct brw_context *brw)
    }
 
    /* ARB_gpu_shader5 */
-   if (brw->gen >= 7)
+   if (devinfo->gen >= 7)
       ctx->Const.MaxVertexStreams = MIN2(4, MAX_VERTEX_STREAMS);
 
    /* ARB_framebuffer_no_attachments */
@@ -805,7 +809,7 @@ brw_initialize_cs_context_constants(struct brw_context *brw)
    struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    /* FINISHME: Do this for all platforms that the kernel supports */
-   if (brw->is_cherryview &&
+   if (devinfo->is_cherryview &&
        screen->subslice_total > 0 && screen->eu_total > 0) {
       /* Logical CS threads = EUs per subslice * 7 threads per EU */
       uint32_t max_cs_threads = screen->eu_total / screen->subslice_total * 7;
@@ -844,6 +848,7 @@ static void
 brw_process_driconf_options(struct brw_context *brw)
 {
    struct gl_context *ctx = &brw->ctx;
+   struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    driOptionCache *options = &brw->optionCache;
    driParseConfigFiles(options, &brw->screen->optionCache,
@@ -859,10 +864,9 @@ brw_process_driconf_options(struct brw_context *brw)
    }
 
    if (INTEL_DEBUG & DEBUG_NO_HIZ) {
-       brw->has_hiz = false;
-       /* On gen6, you can only do separate stencil with HIZ. */
-       if (brw->gen == 6)
-          brw->has_separate_stencil = false;
+      /* On gen6, you can only do separate stencil with HIZ. */
+      if (devinfo->gen == 6)
+         brw->has_separate_stencil = false;
    }
 
    if (driQueryOptionb(options, "always_flush_batch")) {
@@ -954,24 +958,7 @@ brwCreateContext(gl_api api,
    brw->screen = screen;
    brw->bufmgr = screen->bufmgr;
 
-   brw->gen = devinfo->gen;
-   brw->gt = devinfo->gt;
-   brw->is_g4x = devinfo->is_g4x;
-   brw->is_baytrail = devinfo->is_baytrail;
-   brw->is_haswell = devinfo->is_haswell;
-   brw->is_cherryview = devinfo->is_cherryview;
-   brw->is_broxton = devinfo->is_broxton || devinfo->is_geminilake;
-   brw->has_llc = devinfo->has_llc;
-   brw->has_hiz = devinfo->has_hiz_and_separate_stencil;
    brw->has_separate_stencil = devinfo->has_hiz_and_separate_stencil;
-   brw->has_pln = devinfo->has_pln;
-   brw->has_compr4 = devinfo->has_compr4;
-   brw->has_surface_tile_offset = devinfo->has_surface_tile_offset;
-   brw->has_negative_rhw_bug = devinfo->has_negative_rhw_bug;
-   brw->needs_unlit_centroid_workaround =
-      devinfo->needs_unlit_centroid_workaround;
-
-   brw->must_use_separate_stencil = devinfo->must_use_separate_stencil;
    brw->has_swizzling = screen->hw_has_swizzling;
 
    isl_device_init(&brw->isl_dev, devinfo, screen->hw_has_swizzling);
@@ -981,13 +968,13 @@ brwCreateContext(gl_api api,
    brw->tes.base.stage = MESA_SHADER_TESS_EVAL;
    brw->gs.base.stage = MESA_SHADER_GEOMETRY;
    brw->wm.base.stage = MESA_SHADER_FRAGMENT;
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       gen8_init_vtable_surface_functions(brw);
       brw->vtbl.emit_depth_stencil_hiz = gen8_emit_depth_stencil_hiz;
-   } else if (brw->gen >= 7) {
+   } else if (devinfo->gen >= 7) {
       gen7_init_vtable_surface_functions(brw);
       brw->vtbl.emit_depth_stencil_hiz = gen7_emit_depth_stencil_hiz;
-   } else if (brw->gen >= 6) {
+   } else if (devinfo->gen >= 6) {
       gen6_init_vtable_surface_functions(brw);
       brw->vtbl.emit_depth_stencil_hiz = gen6_emit_depth_stencil_hiz;
    } else {
@@ -1050,9 +1037,9 @@ brwCreateContext(gl_api api,
 
    intel_fbo_init(brw);
 
-   intel_batchbuffer_init(&brw->batch, brw->bufmgr, brw->has_llc);
+   intel_batchbuffer_init(&brw->batch, brw->bufmgr, devinfo->has_llc);
 
-   if (brw->gen >= 6) {
+   if (devinfo->gen >= 6) {
       /* Create a new hardware context.  Using a hardware context means that
        * our GPU state will be saved/restored on context switch, allowing us
        * to assume that the GPU is in the same state we left it in.
@@ -1085,7 +1072,7 @@ brwCreateContext(gl_api api,
 
    brw->urb.size = devinfo->urb.size;
 
-   if (brw->gen == 6)
+   if (devinfo->gen == 6)
       brw->urb.gs_present = false;
 
    brw->prim_restart.in_progress = false;
@@ -1135,6 +1122,7 @@ intelDestroyContext(__DRIcontext * driContextPriv)
    struct brw_context *brw =
       (struct brw_context *) driContextPriv->driverPrivate;
    struct gl_context *ctx = &brw->ctx;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    _mesa_meta_free(&brw->ctx);
 
@@ -1146,7 +1134,7 @@ intelDestroyContext(__DRIcontext * driContextPriv)
       brw_destroy_shader_time(brw);
    }
 
-   if (brw->gen >= 6)
+   if (devinfo->gen >= 6)
       blorp_finish(&brw->blorp);
 
    brw_destroy_state(brw);
@@ -1313,7 +1301,9 @@ void
 intel_resolve_for_dri2_flush(struct brw_context *brw,
                              __DRIdrawable *drawable)
 {
-   if (brw->gen < 6) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen < 6) {
       /* MSAA and fast color clear are not supported, so don't waste time
        * checking whether a resolve is needed.
        */
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index a7d52f4e3e5..32840ec1b99 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -745,25 +745,8 @@ struct brw_context
 
    uint64_t max_gtt_map_object_size;
 
-   int gen;
-   int gt;
-
-   bool is_g4x;
-   bool is_baytrail;
-   bool is_haswell;
-   bool is_cherryview;
-   bool is_broxton;
-
-   bool has_hiz;
    bool has_separate_stencil;
-   bool must_use_separate_stencil;
-   bool has_llc;
    bool has_swizzling;
-   bool has_surface_tile_offset;
-   bool has_compr4;
-   bool has_negative_rhw_bug;
-   bool has_pln;
-   bool no_simd8;
 
    /**
     * Some versions of Gen hardware don't do centroid interpolation correctly
diff --git a/src/mesa/drivers/dri/i965/brw_cs.c b/src/mesa/drivers/dri/i965/brw_cs.c
index cc564a012b6..cf72889b411 100644
--- a/src/mesa/drivers/dri/i965/brw_cs.c
+++ b/src/mesa/drivers/dri/i965/brw_cs.c
@@ -155,7 +155,7 @@ brw_codegen_cs_prog(struct brw_context *brw,
     * number of threads per subslice.
     */
    const unsigned scratch_ids_per_subslice =
-      brw->is_haswell ? 16 * 8 : devinfo->max_cs_threads;
+      devinfo->is_haswell ? 16 * 8 : devinfo->max_cs_threads;
 
    brw_alloc_stage_scratch(brw, &brw->cs.base,
                            prog_data.base.total_scratch,
diff --git a/src/mesa/drivers/dri/i965/brw_curbe.c b/src/mesa/drivers/dri/i965/brw_curbe.c
index 139a3bcdf86..12a6310bc32 100644
--- a/src/mesa/drivers/dri/i965/brw_curbe.c
+++ b/src/mesa/drivers/dri/i965/brw_curbe.c
@@ -195,6 +195,7 @@ static const GLfloat fixed_plane[6][4] = {
 static void
 brw_upload_constant_buffer(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    /* BRW_NEW_PUSH_CONSTANT_ALLOCATION */
    const GLuint sz = brw->curbe.total_size;
@@ -324,7 +325,7 @@ emit:
     *
     * BRW_NEW_FRAGMENT_PROGRAM
     */
-   if (brw->gen == 4 && !brw->is_g4x &&
+   if (devinfo->gen == 4 && !devinfo->is_g4x &&
        (brw->fragment_program->info.inputs_read & (1 << VARYING_SLOT_POS))) {
       BEGIN_BATCH(2);
       OUT_BATCH(_3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP << 16 | (2 - 2));
@@ -347,4 +348,3 @@ const struct brw_tracked_state brw_constant_buffer = {
    },
    .emit = brw_upload_constant_buffer,
 };
-
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index 821f1e24e94..1300c2539b1 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -158,6 +158,7 @@ brw_emit_prim(struct brw_context *brw,
               struct brw_transform_feedback_object *xfb_obj,
               unsigned stream)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    int verts_per_instance;
    int vertex_access_type;
    int indirect_flag;
@@ -169,20 +170,20 @@ brw_emit_prim(struct brw_context *brw,
    int base_vertex_location = prim->basevertex;
 
    if (prim->indexed) {
-      vertex_access_type = brw->gen >= 7 ?
+      vertex_access_type = devinfo->gen >= 7 ?
          GEN7_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM :
          GEN4_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM;
       start_vertex_location += brw->ib.start_vertex_offset;
       base_vertex_location += brw->vb.start_vertex_bias;
    } else {
-      vertex_access_type = brw->gen >= 7 ?
+      vertex_access_type = devinfo->gen >= 7 ?
          GEN7_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL :
          GEN4_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL;
       start_vertex_location += brw->vb.start_vertex_bias;
    }
 
    /* We only need to trim the primitive count on pre-Gen6. */
-   if (brw->gen < 6)
+   if (devinfo->gen < 6)
       verts_per_instance = trim(prim->mode, prim->count);
    else
       verts_per_instance = prim->count;
@@ -257,9 +258,9 @@ brw_emit_prim(struct brw_context *brw,
       indirect_flag = 0;
    }
 
-   BEGIN_BATCH(brw->gen >= 7 ? 7 : 6);
+   BEGIN_BATCH(devinfo->gen >= 7 ? 7 : 6);
 
-   if (brw->gen >= 7) {
+   if (devinfo->gen >= 7) {
       const int predicate_enable =
          (brw->predicate.state == BRW_PREDICATE_STATE_USE_BIT)
          ? GEN7_3DPRIM_PREDICATE_ENABLE : 0;
@@ -287,6 +288,7 @@ static void
 brw_merge_inputs(struct brw_context *brw,
                  const struct gl_vertex_array *arrays[])
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    const struct gl_context *ctx = &brw->ctx;
    GLuint i;
 
@@ -301,7 +303,7 @@ brw_merge_inputs(struct brw_context *brw,
       brw->vb.inputs[i].glarray = arrays[i];
    }
 
-   if (brw->gen < 8 && !brw->is_haswell) {
+   if (devinfo->gen < 8 && !devinfo->is_haswell) {
       uint64_t mask = ctx->VertexProgram._Current->info.inputs_read;
       /* Prior to Haswell, the hardware can't natively support GL_FIXED or
        * 2_10_10_10_REV vertex formats.  Set appropriate workaround flags.
@@ -401,7 +403,7 @@ brw_postdraw_set_buffers_need_resolve(struct brw_context *brw)
 
       if (!irb)
          continue;
-     
+
       brw_render_cache_set_add_bo(brw, irb->mt->bo);
       intel_miptree_finish_render(brw, irb->mt, irb->mt_level,
                                   irb->mt_layer, irb->layer_count);
@@ -475,6 +477,7 @@ brw_try_draw_prims(struct gl_context *ctx,
                    struct gl_buffer_object *indirect)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    GLuint i;
    bool fail_next = false;
 
@@ -609,7 +612,7 @@ brw_try_draw_prims(struct gl_context *ctx,
       if (i > 0 && vs_prog_data->uses_drawid)
          brw->ctx.NewDriverState |= BRW_NEW_VERTICES;
 
-      if (brw->gen < 6)
+      if (devinfo->gen < 6)
          brw_set_prim(brw, &prims[i]);
       else
          gen6_set_prim(brw, &prims[i]);
diff --git a/src/mesa/drivers/dri/i965/brw_draw_upload.c b/src/mesa/drivers/dri/i965/brw_draw_upload.c
index 05b6b1a50f1..f7619ccee2b 100644
--- a/src/mesa/drivers/dri/i965/brw_draw_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_draw_upload.c
@@ -252,8 +252,9 @@ brw_get_vertex_surface_type(struct brw_context *brw,
                             const struct gl_vertex_array *glarray)
 {
    int size = glarray->Size;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    const bool is_ivybridge_or_older =
-      brw->gen <= 7 && !brw->is_baytrail && !brw->is_haswell;
+      devinfo->gen <= 7 && !devinfo->is_baytrail && !devinfo->is_haswell;
 
    if (unlikely(INTEL_DEBUG & DEBUG_VERTS))
       fprintf(stderr, "type %s size %d normalized %d\n",
@@ -295,7 +296,7 @@ brw_get_vertex_surface_type(struct brw_context *brw,
       case GL_FLOAT: return float_types[size];
       case GL_HALF_FLOAT:
       case GL_HALF_FLOAT_OES:
-         if (brw->gen < 6 && size == 3)
+         if (devinfo->gen < 6 && size == 3)
             return half_float_types[4];
          else
             return half_float_types[size];
@@ -314,7 +315,7 @@ brw_get_vertex_surface_type(struct brw_context *brw,
             return ubyte_types_norm[size];
          }
       case GL_FIXED:
-         if (brw->gen >= 8 || brw->is_haswell)
+         if (devinfo->gen >= 8 || devinfo->is_haswell)
             return fixed_point_types[size];
 
          /* This produces GL_FIXED inputs as values between INT32_MIN and
@@ -328,7 +329,7 @@ brw_get_vertex_surface_type(struct brw_context *brw,
        */
       case GL_INT_2_10_10_10_REV:
          assert(size == 4);
-         if (brw->gen >= 8 || brw->is_haswell) {
+         if (devinfo->gen >= 8 || devinfo->is_haswell) {
             return glarray->Format == GL_BGRA
                ? ISL_FORMAT_B10G10R10A2_SNORM
                : ISL_FORMAT_R10G10B10A2_SNORM;
@@ -336,7 +337,7 @@ brw_get_vertex_surface_type(struct brw_context *brw,
          return ISL_FORMAT_R10G10B10A2_UINT;
       case GL_UNSIGNED_INT_2_10_10_10_REV:
          assert(size == 4);
-         if (brw->gen >= 8 || brw->is_haswell) {
+         if (devinfo->gen >= 8 || devinfo->is_haswell) {
             return glarray->Format == GL_BGRA
                ? ISL_FORMAT_B10G10R10A2_UNORM
                : ISL_FORMAT_R10G10B10A2_UNORM;
@@ -353,7 +354,7 @@ brw_get_vertex_surface_type(struct brw_context *brw,
        */
       if (glarray->Type == GL_INT_2_10_10_10_REV) {
          assert(size == 4);
-         if (brw->gen >= 8 || brw->is_haswell) {
+         if (devinfo->gen >= 8 || devinfo->is_haswell) {
             return glarray->Format == GL_BGRA
                ? ISL_FORMAT_B10G10R10A2_SSCALED
                : ISL_FORMAT_R10G10B10A2_SSCALED;
@@ -361,7 +362,7 @@ brw_get_vertex_surface_type(struct brw_context *brw,
          return ISL_FORMAT_R10G10B10A2_UINT;
       } else if (glarray->Type == GL_UNSIGNED_INT_2_10_10_10_REV) {
          assert(size == 4);
-         if (brw->gen >= 8 || brw->is_haswell) {
+         if (devinfo->gen >= 8 || devinfo->is_haswell) {
             return glarray->Format == GL_BGRA
                ? ISL_FORMAT_B10G10R10A2_USCALED
                : ISL_FORMAT_R10G10B10A2_USCALED;
@@ -374,7 +375,7 @@ brw_get_vertex_surface_type(struct brw_context *brw,
       case GL_FLOAT: return float_types[size];
       case GL_HALF_FLOAT:
       case GL_HALF_FLOAT_OES:
-         if (brw->gen < 6 && size == 3)
+         if (devinfo->gen < 6 && size == 3)
             return half_float_types[4];
          else
             return half_float_types[size];
@@ -385,7 +386,7 @@ brw_get_vertex_surface_type(struct brw_context *brw,
       case GL_UNSIGNED_SHORT: return ushort_types_scale[size];
       case GL_UNSIGNED_BYTE: return ubyte_types_scale[size];
       case GL_FIXED:
-         if (brw->gen >= 8 || brw->is_haswell)
+         if (devinfo->gen >= 8 || devinfo->is_haswell)
             return fixed_point_types[size];
 
          /* This produces GL_FIXED inputs as values between INT32_MIN and
@@ -452,6 +453,7 @@ copy_array_to_vbo_array(struct brw_context *brw,
 void
 brw_prepare_vertices(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    /* BRW_NEW_VS_PROG_DATA */
    const struct brw_vs_prog_data *vs_prog_data =
@@ -474,7 +476,7 @@ brw_prepare_vertices(struct brw_context *brw)
     * is passed sideband through the fixed function units.  So, we need to
     * prepare the vertex buffer for it, but it's not present in inputs_read.
     */
-   if (brw->gen >= 6 && (ctx->Polygon.FrontMode != GL_FILL ||
+   if (devinfo->gen >= 6 && (ctx->Polygon.FrontMode != GL_FILL ||
                            ctx->Polygon.BackMode != GL_FILL)) {
       vs_inputs |= VERT_BIT_EDGEFLAG;
    }
diff --git a/src/mesa/drivers/dri/i965/brw_ff_gs.c b/src/mesa/drivers/dri/i965/brw_ff_gs.c
index b7b4b716011..cb9b13e5700 100644
--- a/src/mesa/drivers/dri/i965/brw_ff_gs.c
+++ b/src/mesa/drivers/dri/i965/brw_ff_gs.c
@@ -47,6 +47,7 @@ void
 brw_codegen_ff_gs_prog(struct brw_context *brw,
                        struct brw_ff_gs_prog_key *key)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_ff_gs_compile c;
    const GLuint *program;
    void *mem_ctx;
@@ -62,7 +63,7 @@ brw_codegen_ff_gs_prog(struct brw_context *brw,
 
    /* Begin the compilation:
     */
-   brw_init_codegen(&brw->screen->devinfo, &c.func, mem_ctx);
+   brw_init_codegen(devinfo, &c.func, mem_ctx);
 
    c.func.single_program_flow = 1;
 
@@ -71,7 +72,7 @@ brw_codegen_ff_gs_prog(struct brw_context *brw,
     */
    brw_set_default_mask_control(&c.func, BRW_MASK_DISABLE);
 
-   if (brw->gen >= 6) {
+   if (devinfo->gen >= 6) {
       unsigned num_verts;
       bool check_edge_flag;
       /* On Sandybridge, we use the GS for implementing transform feedback
@@ -134,8 +135,7 @@ brw_codegen_ff_gs_prog(struct brw_context *brw,
 
    if (unlikely(INTEL_DEBUG & DEBUG_GS)) {
       fprintf(stderr, "gs:\n");
-      brw_disassemble(&brw->screen->devinfo, c.func.store,
-                      0, program_size, stderr);
+      brw_disassemble(devinfo, c.func.store, 0, program_size, stderr);
       fprintf(stderr, "\n");
     }
 
@@ -161,6 +161,7 @@ static void
 brw_ff_gs_populate_key(struct brw_context *brw,
                        struct brw_ff_gs_prog_key *key)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    static const unsigned swizzle_for_offset[4] = {
       BRW_SWIZZLE4(0, 1, 2, 3),
       BRW_SWIZZLE4(1, 2, 3, 3),
@@ -187,10 +188,10 @@ brw_ff_gs_populate_key(struct brw_context *brw,
       key->pv_first = true;
    }
 
-   if (brw->gen >= 7) {
+   if (devinfo->gen >= 7) {
       /* On Gen7 and later, we don't use GS (yet). */
       key->need_gs_prog = false;
-   } else if (brw->gen == 6) {
+   } else if (devinfo->gen == 6) {
       /* On Gen6, GS is used for transform feedback. */
       /* BRW_NEW_TRANSFORM_FEEDBACK */
       if (_mesa_is_xfb_active_and_unpaused(ctx)) {
diff --git a/src/mesa/drivers/dri/i965/brw_formatquery.c b/src/mesa/drivers/dri/i965/brw_formatquery.c
index 5faf91fa9e7..4f3b9e467be 100644
--- a/src/mesa/drivers/dri/i965/brw_formatquery.c
+++ b/src/mesa/drivers/dri/i965/brw_formatquery.c
@@ -32,11 +32,12 @@ brw_query_samples_for_format(struct gl_context *ctx, GLenum target,
                              GLenum internalFormat, int samples[16])
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    (void) target;
    (void) internalFormat;
 
-   switch (brw->gen) {
+   switch (devinfo->gen) {
    case 10:
    case 9:
       samples[0] = 16;
@@ -76,7 +77,7 @@ brw_query_samples_for_format(struct gl_context *ctx, GLenum target,
       return 1;
 
    default:
-      assert(brw->gen < 6);
+      assert(devinfo->gen < 6);
       samples[0] = 1;
       return 1;
    }
diff --git a/src/mesa/drivers/dri/i965/brw_gs.c b/src/mesa/drivers/dri/i965/brw_gs.c
index 0c04ef0dacc..0de833a3e7c 100644
--- a/src/mesa/drivers/dri/i965/brw_gs.c
+++ b/src/mesa/drivers/dri/i965/brw_gs.c
@@ -196,6 +196,7 @@ brw_gs_populate_key(struct brw_context *brw,
 void
 brw_upload_gs_prog(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_stage_state *stage_state = &brw->gs.base;
    struct brw_gs_prog_key key;
    /* BRW_NEW_GEOMETRY_PROGRAM */
@@ -206,7 +207,7 @@ brw_upload_gs_prog(struct brw_context *brw)
 
    if (gp == NULL) {
       /* No geometry shader.  Vertex data just passes straight through. */
-      if (brw->gen == 6 &&
+      if (devinfo->gen == 6 &&
           (brw->ctx.NewDriverState & BRW_NEW_TRANSFORM_FEEDBACK)) {
          gen6_brw_upload_ff_gs_prog(brw);
          return;
diff --git a/src/mesa/drivers/dri/i965/brw_gs_state.c b/src/mesa/drivers/dri/i965/brw_gs_state.c
index bc3d2e5961a..bd26e41b7b6 100644
--- a/src/mesa/drivers/dri/i965/brw_gs_state.c
+++ b/src/mesa/drivers/dri/i965/brw_gs_state.c
@@ -39,6 +39,7 @@
 static void
 brw_upload_gs_unit(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_gs_unit_state *gs;
 
    gs = brw_state_batch(brw, sizeof(*gs), 32, &brw->ff_gs.state_offset);
@@ -77,7 +78,7 @@ brw_upload_gs_unit(struct brw_context *brw)
 	 gs->thread4.max_threads = 0;
    }
 
-   if (brw->gen == 5)
+   if (devinfo->gen == 5)
       gs->thread4.rendering_enable = 1;
 
    /* BRW_NEW_VIEWPORT_COUNT */
diff --git a/src/mesa/drivers/dri/i965/brw_link.cpp b/src/mesa/drivers/dri/i965/brw_link.cpp
index e9158c596c5..a1082a7a05a 100644
--- a/src/mesa/drivers/dri/i965/brw_link.cpp
+++ b/src/mesa/drivers/dri/i965/brw_link.cpp
@@ -74,10 +74,12 @@ static void
 brw_lower_packing_builtins(struct brw_context *brw,
                            exec_list *ir)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* Gens < 7 don't have instructions to convert to or from half-precision,
     * and Gens < 6 don't expose that functionality.
     */
-   if (brw->gen != 6)
+   if (devinfo->gen != 6)
       return;
 
    lower_packing_builtins(ir, LOWER_PACK_HALF_2x16 | LOWER_UNPACK_HALF_2x16);
@@ -88,6 +90,7 @@ process_glsl_ir(struct brw_context *brw,
                 struct gl_shader_program *shader_prog,
                 struct gl_linked_shader *shader)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
 
    /* Temporary memory context for any new IR. */
@@ -108,7 +111,7 @@ process_glsl_ir(struct brw_context *brw,
                                      EXP_TO_EXP2 |
                                      LOG_TO_LOG2 |
                                      DFREXP_DLDEXP_TO_ARITH);
-   if (brw->gen < 7) {
+   if (devinfo->gen < 7) {
       instructions_to_lower |= BIT_COUNT_TO_MATH |
                                EXTRACT_TO_SHIFTS |
                                INSERT_TO_SHIFTS |
@@ -120,7 +123,7 @@ process_glsl_ir(struct brw_context *brw,
    /* Pre-gen6 HW can only nest if-statements 16 deep.  Beyond this,
     * if-statements need to be flattened.
     */
-   if (brw->gen < 6)
+   if (devinfo->gen < 6)
       lower_if_to_cond_assign(shader->Stage, shader->ir, 16);
 
    do_lower_texture_projection(shader->ir);
diff --git a/src/mesa/drivers/dri/i965/brw_meta_util.c b/src/mesa/drivers/dri/i965/brw_meta_util.c
index 575f437750b..d00426c1bbe 100644
--- a/src/mesa/drivers/dri/i965/brw_meta_util.c
+++ b/src/mesa/drivers/dri/i965/brw_meta_util.c
@@ -277,6 +277,7 @@ brw_is_color_fast_clear_compatible(struct brw_context *brw,
                                    const struct intel_mipmap_tree *mt,
                                    const union gl_color_union *color)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    const struct gl_context *ctx = &brw->ctx;
 
    /* If we're mapping the render format to a different format than the
@@ -287,7 +288,7 @@ brw_is_color_fast_clear_compatible(struct brw_context *brw,
     * state so the hardware probably legitimately doesn't need to support
     * this case. At least on Gen9 this really does seem to cause problems.
     */
-   if (brw->gen >= 9 &&
+   if (devinfo->gen >= 9 &&
        brw_isl_format_for_mesa_format(mt->format) !=
        brw->mesa_to_isl_render_format[mt->format])
       return false;
@@ -297,7 +298,7 @@ brw_is_color_fast_clear_compatible(struct brw_context *brw,
     * resolved in intel_update_state. In that case it's pointless to do a
     * fast clear because it's very likely to be immediately resolved.
     */
-   if (brw->gen >= 9 &&
+   if (devinfo->gen >= 9 &&
        mt->num_samples <= 1 &&
        ctx->Color.sRGBEnabled &&
        _mesa_get_srgb_format_linear(mt->format) != mt->format)
@@ -305,7 +306,7 @@ brw_is_color_fast_clear_compatible(struct brw_context *brw,
 
    const mesa_format format = _mesa_get_render_format(ctx, mt->format);
    if (_mesa_is_format_integer_color(format)) {
-      if (brw->gen >= 8) {
+      if (devinfo->gen >= 8) {
          perf_debug("Integer fast clear not enabled for (%s)",
                     _mesa_get_format_name(format));
       }
@@ -317,7 +318,7 @@ brw_is_color_fast_clear_compatible(struct brw_context *brw,
          continue;
       }
 
-      if (brw->gen < 9 &&
+      if (devinfo->gen < 9 &&
           color->f[i] != 0.0f && color->f[i] != 1.0f) {
          return false;
       }
diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c
index d242aa49918..427afa04e26 100644
--- a/src/mesa/drivers/dri/i965/brw_misc_state.c
+++ b/src/mesa/drivers/dri/i965/brw_misc_state.c
@@ -54,7 +54,9 @@
 static void
 upload_pipelined_state_pointers(struct brw_context *brw)
 {
-   if (brw->gen == 5) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen == 5) {
       /* Need to flush before changing clip max threads for errata. */
       BEGIN_BATCH(1);
       OUT_BATCH(MI_FLUSH);
@@ -140,6 +142,7 @@ static bool
 rebase_depth_stencil(struct brw_context *brw, struct intel_renderbuffer *irb,
                      bool invalidate)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    uint32_t tile_mask_x = 0, tile_mask_y = 0;
 
@@ -160,7 +163,7 @@ rebase_depth_stencil(struct brw_context *brw, struct intel_renderbuffer *irb,
    bool rebase = tile_x & 7 || tile_y & 7;
 
    /* We didn't even have intra-tile offsets before g45. */
-   rebase |= (!brw->has_surface_tile_offset && (tile_x || tile_y));
+   rebase |= (!devinfo->has_surface_tile_offset && (tile_x || tile_y));
 
    if (rebase) {
       perf_debug("HW workaround: blitting depth level %d to a temporary "
@@ -199,6 +202,7 @@ void
 brw_workaround_depthstencil_alignment(struct brw_context *brw,
                                       GLbitfield clear_mask)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    struct gl_framebuffer *fb = ctx->DrawBuffer;
    struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(fb, BUFFER_DEPTH);
@@ -219,7 +223,7 @@ brw_workaround_depthstencil_alignment(struct brw_context *brw,
    /* Gen6+ doesn't require the workarounds, since we always program the
     * surface state at the start of the whole surface.
     */
-   if (brw->gen >= 6)
+   if (devinfo->gen >= 6)
       return;
 
    /* Check if depth buffer is in depth/stencil format.  If so, then it's only
@@ -257,6 +261,7 @@ brw_workaround_depthstencil_alignment(struct brw_context *brw,
 void
 brw_emit_depthbuffer(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    struct gl_framebuffer *fb = ctx->DrawBuffer;
    /* _NEW_BUFFERS */
@@ -277,7 +282,7 @@ brw_emit_depthbuffer(struct brw_context *brw)
       separate_stencil = stencil_mt->format == MESA_FORMAT_S_UINT8;
 
       /* Gen7 supports only separate stencil */
-      assert(separate_stencil || brw->gen < 7);
+      assert(separate_stencil || devinfo->gen < 7);
    }
 
    /* If there's a packed depth/stencil bound to stencil only, we need to
@@ -297,14 +302,14 @@ brw_emit_depthbuffer(struct brw_context *brw)
        * set to the same value. Gens after 7 implicitly always set
        * Separate_Stencil_Enable; software cannot disable it.
        */
-      if ((brw->gen < 7 && hiz) || brw->gen >= 7) {
+      if ((devinfo->gen < 7 && hiz) || devinfo->gen >= 7) {
          assert(!_mesa_is_format_packed_depth_stencil(depth_mt->format));
       }
 
       /* Prior to Gen7, if using separate stencil, hiz must be enabled. */
-      assert(brw->gen >= 7 || !separate_stencil || hiz);
+      assert(devinfo->gen >= 7 || !separate_stencil || hiz);
 
-      assert(brw->gen < 6 || depth_mt->tiling == I915_TILING_Y);
+      assert(devinfo->gen < 6 || depth_mt->tiling == I915_TILING_Y);
       assert(!hiz || depth_mt->tiling == I915_TILING_Y);
 
       depthbuffer_format = brw_depthbuffer_format(brw);
@@ -374,7 +379,8 @@ brw_emit_depth_stencil_hiz(struct brw_context *brw,
    assert(!hiz);
    assert(!separate_stencil);
 
-   const unsigned len = (brw->is_g4x || brw->gen == 5) ? 6 : 5;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   const unsigned len = (devinfo->is_g4x || devinfo->gen == 5) ? 6 : 5;
 
    BEGIN_BATCH(len);
    OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2));
@@ -397,12 +403,12 @@ brw_emit_depth_stencil_hiz(struct brw_context *brw,
              ((height + tile_y - 1) << 19));
    OUT_BATCH(0);
 
-   if (brw->is_g4x || brw->gen >= 5)
+   if (devinfo->is_g4x || devinfo->gen >= 5)
       OUT_BATCH(tile_x | (tile_y << 16));
    else
       assert(tile_x == 0 && tile_y == 0);
 
-   if (brw->gen >= 6)
+   if (devinfo->gen >= 6)
       OUT_BATCH(0);
 
    ADVANCE_BATCH();
@@ -420,11 +426,12 @@ const struct brw_tracked_state brw_depthbuffer = {
 void
 brw_emit_select_pipeline(struct brw_context *brw, enum brw_pipeline pipeline)
 {
-   const bool is_965 = brw->gen == 4 && !brw->is_g4x;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   const bool is_965 = devinfo->gen == 4 && !devinfo->is_g4x;
    const uint32_t _3DSTATE_PIPELINE_SELECT =
       is_965 ? CMD_PIPELINE_SELECT_965 : CMD_PIPELINE_SELECT_GM45;
 
-   if (brw->gen >= 8 && brw->gen < 10) {
+   if (devinfo->gen >= 8 && devinfo->gen < 10) {
       /* From the Broadwell PRM, Volume 2a: Instructions, PIPELINE_SELECT:
        *
        *   Software must clear the COLOR_CALC_STATE Valid field in
@@ -444,7 +451,7 @@ brw_emit_select_pipeline(struct brw_context *brw, enum brw_pipeline pipeline)
       }
    }
 
-   if (brw->gen >= 6) {
+   if (devinfo->gen >= 6) {
       /* From "BXML » GT » MI » vol1a GPU Overview » [Instruction]
        * PIPELINE_SELECT [DevBWR+]":
        *
@@ -456,7 +463,7 @@ brw_emit_select_pipeline(struct brw_context *brw, enum brw_pipeline pipeline)
        *   MI_PIPELINE_SELECT command to change the Pipeline Select Mode.
        */
       const unsigned dc_flush =
-         brw->gen >= 7 ? PIPE_CONTROL_DATA_CACHE_FLUSH : 0;
+         devinfo->gen >= 7 ? PIPE_CONTROL_DATA_CACHE_FLUSH : 0;
 
       brw_emit_pipe_control_flush(brw,
                                   PIPE_CONTROL_RENDER_TARGET_FLUSH |
@@ -489,11 +496,11 @@ brw_emit_select_pipeline(struct brw_context *brw, enum brw_pipeline pipeline)
    /* Select the pipeline */
    BEGIN_BATCH(1);
    OUT_BATCH(_3DSTATE_PIPELINE_SELECT << 16 |
-             (brw->gen >= 9 ? (3 << 8) : 0) |
+             (devinfo->gen >= 9 ? (3 << 8) : 0) |
              (pipeline == BRW_COMPUTE_PIPELINE ? 2 : 0));
    ADVANCE_BATCH();
 
-   if (brw->gen == 7 && !brw->is_haswell &&
+   if (devinfo->gen == 7 && !devinfo->is_haswell &&
        pipeline == BRW_RENDER_PIPELINE) {
       /* From "BXML » GT » MI » vol1a GPU Overview » [Instruction]
        * PIPELINE_SELECT [DevBWR+]":
@@ -524,12 +531,13 @@ brw_emit_select_pipeline(struct brw_context *brw, enum brw_pipeline pipeline)
 void
 brw_upload_invariant_state(struct brw_context *brw)
 {
-   const bool is_965 = brw->gen == 4 && !brw->is_g4x;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   const bool is_965 = devinfo->gen == 4 && !devinfo->is_g4x;
 
    brw_emit_select_pipeline(brw, BRW_RENDER_PIPELINE);
    brw->last_pipeline = BRW_RENDER_PIPELINE;
 
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       BEGIN_BATCH(3);
       OUT_BATCH(CMD_STATE_SIP << 16 | (3 - 2));
       OUT_BATCH(0);
@@ -592,10 +600,11 @@ brw_upload_state_base_address(struct brw_context *brw)
     * address) on this chipset is always set to 0 across X and GL,
     * maybe this isn't required for us in particular.
     */
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
-   if (brw->gen >= 6) {
+   if (devinfo->gen >= 6) {
       const unsigned dc_flush =
-         brw->gen >= 7 ? PIPE_CONTROL_DATA_CACHE_FLUSH : 0;
+         devinfo->gen >= 7 ? PIPE_CONTROL_DATA_CACHE_FLUSH : 0;
 
       /* Emit a render target cache flush.
        *
@@ -624,9 +633,9 @@ brw_upload_state_base_address(struct brw_context *brw)
                                 dc_flush);
    }
 
-   if (brw->gen >= 8) {
-      uint32_t mocs_wb = brw->gen >= 9 ? SKL_MOCS_WB : BDW_MOCS_WB;
-      int pkt_len = brw->gen >= 9 ? 19 : 16;
+   if (devinfo->gen >= 8) {
+      uint32_t mocs_wb = devinfo->gen >= 9 ? SKL_MOCS_WB : BDW_MOCS_WB;
+      int pkt_len = devinfo->gen >= 9 ? 19 : 16;
 
       BEGIN_BATCH(pkt_len);
       OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (pkt_len - 2));
@@ -656,14 +665,14 @@ brw_upload_state_base_address(struct brw_context *brw)
       OUT_BATCH(0xfffff001);
       /* Instruction access upper bound */
       OUT_BATCH(ALIGN(brw->cache.bo->size, 4096) | 1);
-      if (brw->gen >= 9) {
+      if (devinfo->gen >= 9) {
          OUT_BATCH(1);
          OUT_BATCH(0);
          OUT_BATCH(0);
       }
       ADVANCE_BATCH();
-   } else if (brw->gen >= 6) {
-      uint8_t mocs = brw->gen == 7 ? GEN7_MOCS_L3 : 0;
+   } else if (devinfo->gen >= 6) {
+      uint8_t mocs = devinfo->gen == 7 ? GEN7_MOCS_L3 : 0;
 
        BEGIN_BATCH(10);
        OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (10 - 2));
@@ -702,7 +711,7 @@ brw_upload_state_base_address(struct brw_context *brw)
        OUT_BATCH(1); /* Indirect object upper bound */
        OUT_BATCH(1); /* Instruction access upper bound */
        ADVANCE_BATCH();
-   } else if (brw->gen == 5) {
+   } else if (devinfo->gen == 5) {
        BEGIN_BATCH(8);
        OUT_BATCH(CMD_STATE_BASE_ADDRESS << 16 | (8 - 2));
        OUT_BATCH(1); /* General state base address */
@@ -727,7 +736,7 @@ brw_upload_state_base_address(struct brw_context *brw)
        ADVANCE_BATCH();
    }
 
-   if (brw->gen >= 6) {
+   if (devinfo->gen >= 6) {
       brw_emit_pipe_control_flush(brw,
                                   PIPE_CONTROL_INSTRUCTION_INVALIDATE |
                                   PIPE_CONTROL_STATE_CACHE_INVALIDATE |
diff --git a/src/mesa/drivers/dri/i965/brw_performance_query.c b/src/mesa/drivers/dri/i965/brw_performance_query.c
index 06576a54d03..1e710918bcd 100644
--- a/src/mesa/drivers/dri/i965/brw_performance_query.c
+++ b/src/mesa/drivers/dri/i965/brw_performance_query.c
@@ -1557,6 +1557,7 @@ read_sysfs_drm_device_file_uint64(struct brw_context *brw,
 static bool
 init_oa_sys_vars(struct brw_context *brw, const char *sysfs_dev_dir)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    uint64_t min_freq_mhz = 0, max_freq_mhz = 0;
 
    if (!read_sysfs_drm_device_file_uint64(brw, sysfs_dev_dir,
@@ -1572,20 +1573,18 @@ init_oa_sys_vars(struct brw_context *brw, const char *sysfs_dev_dir)
    brw->perfquery.sys_vars.gt_min_freq = min_freq_mhz * 1000000;
    brw->perfquery.sys_vars.gt_max_freq = max_freq_mhz * 1000000;
 
-   if (brw->is_haswell) {
-      const struct gen_device_info *info = &brw->screen->devinfo;
-
+   if (devinfo->is_haswell) {
       brw->perfquery.sys_vars.timestamp_frequency = 12500000;
 
-      if (info->gt == 1) {
+      if (devinfo->gt == 1) {
          brw->perfquery.sys_vars.n_eus = 10;
          brw->perfquery.sys_vars.n_eu_slices = 1;
          brw->perfquery.sys_vars.subslice_mask = 0x1;
-      } else if (info->gt == 2) {
+      } else if (devinfo->gt == 2) {
          brw->perfquery.sys_vars.n_eus = 20;
          brw->perfquery.sys_vars.n_eu_slices = 1;
          brw->perfquery.sys_vars.subslice_mask = 0x3;
-      } else if (info->gt == 3) {
+      } else if (devinfo->gt == 3) {
          brw->perfquery.sys_vars.n_eus = 40;
          brw->perfquery.sys_vars.n_eu_slices = 2;
          brw->perfquery.sys_vars.subslice_mask = 0xf;
@@ -1667,6 +1666,7 @@ static unsigned
 brw_init_perf_query_info(struct gl_context *ctx)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct stat sb;
    char sysfs_dev_dir[128];
 
@@ -1678,7 +1678,7 @@ brw_init_perf_query_info(struct gl_context *ctx)
    /* The existence of this sysctl parameter implies the kernel supports
     * the i915 perf interface.
     */
-   if (brw->is_haswell &&
+   if (devinfo->is_haswell &&
        stat("/proc/sys/dev/i915/perf_stream_paranoid", &sb) == 0 &&
        get_sysfs_dev_dir(brw, sysfs_dev_dir, sizeof(sysfs_dev_dir)) &&
        init_oa_sys_vars(brw, sysfs_dev_dir))
diff --git a/src/mesa/drivers/dri/i965/brw_pipe_control.c b/src/mesa/drivers/dri/i965/brw_pipe_control.c
index a95892c44cf..f19d6d74122 100644
--- a/src/mesa/drivers/dri/i965/brw_pipe_control.c
+++ b/src/mesa/drivers/dri/i965/brw_pipe_control.c
@@ -71,7 +71,9 @@ gen8_add_cs_stall_workaround_bits(uint32_t *flags)
 static uint32_t
 gen7_cs_stall_every_four_pipe_controls(struct brw_context *brw, uint32_t flags)
 {
-   if (brw->gen == 7 && !brw->is_haswell) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen == 7 && !devinfo->is_haswell) {
       if (flags & PIPE_CONTROL_CS_STALL) {
          /* If we're doing a CS stall, reset the counter and carry on. */
          brw->pipe_controls_since_last_cs_stall = 0;
@@ -91,11 +93,13 @@ static void
 brw_emit_pipe_control(struct brw_context *brw, uint32_t flags,
                       struct brw_bo *bo, uint32_t offset, uint64_t imm)
 {
-   if (brw->gen >= 8) {
-      if (brw->gen == 8)
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen >= 8) {
+      if (devinfo->gen == 8)
          gen8_add_cs_stall_workaround_bits(&flags);
 
-      if (brw->gen == 9 &&
+      if (devinfo->gen == 9 &&
           (flags & PIPE_CONTROL_VF_CACHE_INVALIDATE)) {
          /* Hardware workaround: SKL
           *
@@ -118,8 +122,8 @@ brw_emit_pipe_control(struct brw_context *brw, uint32_t flags,
       OUT_BATCH(imm);
       OUT_BATCH(imm >> 32);
       ADVANCE_BATCH();
-   } else if (brw->gen >= 6) {
-      if (brw->gen == 6 &&
+   } else if (devinfo->gen >= 6) {
+      if (devinfo->gen == 6 &&
           (flags & PIPE_CONTROL_RENDER_TARGET_FLUSH)) {
          /* Hardware workaround: SNB B-Spec says:
           *
@@ -135,7 +139,7 @@ brw_emit_pipe_control(struct brw_context *brw, uint32_t flags,
       /* PPGTT/GGTT is selected by DW2 bit 2 on Sandybridge, but DW1 bit 24
        * on later platforms.  We always use PPGTT on Gen7+.
        */
-      unsigned gen6_gtt = brw->gen == 6 ? PIPE_CONTROL_GLOBAL_GTT_WRITE : 0;
+      unsigned gen6_gtt = devinfo->gen == 6 ? PIPE_CONTROL_GLOBAL_GTT_WRITE : 0;
 
       BEGIN_BATCH(5);
       OUT_BATCH(_3DSTATE_PIPE_CONTROL | (5 - 2));
@@ -173,7 +177,9 @@ brw_emit_pipe_control(struct brw_context *brw, uint32_t flags,
 void
 brw_emit_pipe_control_flush(struct brw_context *brw, uint32_t flags)
 {
-   if (brw->gen >= 6 &&
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen >= 6 &&
        (flags & PIPE_CONTROL_CACHE_FLUSH_BITS) &&
        (flags & PIPE_CONTROL_CACHE_INVALIDATE_BITS)) {
       /* A pipe control command with flush and invalidate bits set
@@ -225,14 +231,16 @@ brw_emit_pipe_control_write(struct brw_context *brw, uint32_t flags,
 void
 brw_emit_depth_stall_flushes(struct brw_context *brw)
 {
-   assert(brw->gen >= 6);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   assert(devinfo->gen >= 6);
 
    /* Starting on BDW, these pipe controls are unnecessary.
     *
     *   WM HW will internally manage the draining pipe and flushing of the caches
     *   when this command is issued. The PIPE_CONTROL restrictions are removed.
     */
-   if (brw->gen >= 8)
+   if (devinfo->gen >= 8)
       return;
 
    brw_emit_pipe_control_flush(brw, PIPE_CONTROL_DEPTH_STALL);
@@ -251,7 +259,9 @@ brw_emit_depth_stall_flushes(struct brw_context *brw)
 void
 gen7_emit_vs_workaround_flush(struct brw_context *brw)
 {
-   assert(brw->gen == 7);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   assert(devinfo->gen == 7);
    brw_emit_pipe_control_write(brw,
                                PIPE_CONTROL_WRITE_IMMEDIATE
                                | PIPE_CONTROL_DEPTH_STALL,
@@ -340,12 +350,14 @@ brw_emit_post_sync_nonzero_flush(struct brw_context *brw)
  *
  *  SW can track the completion of the end-of-pipe-synchronization by
  *  using "Notify Enable" and "PostSync Operation - Write Immediate
- *  Data" in the PIPE_CONTROL command. 
+ *  Data" in the PIPE_CONTROL command.
  */
 void
 brw_emit_end_of_pipe_sync(struct brw_context *brw, uint32_t flags)
 {
-   if (brw->gen >= 6) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen >= 6) {
       /* From Sandybridge PRM, volume 2, "1.7.3.1 Writing a Value to Memory":
        *
        *    "The most common action to perform upon reaching a synchronization
@@ -374,7 +386,7 @@ brw_emit_end_of_pipe_sync(struct brw_context *brw, uint32_t flags)
                                   PIPE_CONTROL_WRITE_IMMEDIATE,
                                   brw->workaround_bo, 0, 0);
 
-      if (brw->is_haswell) {
+      if (devinfo->is_haswell) {
          /* Haswell needs addition work-arounds:
           *
           * From Haswell PRM, volume 2, part 1, "End-of-Pipe Synchronization":
@@ -427,7 +439,9 @@ brw_emit_end_of_pipe_sync(struct brw_context *brw, uint32_t flags)
 void
 brw_emit_mi_flush(struct brw_context *brw)
 {
-   if (brw->batch.ring == BLT_RING && brw->gen >= 6) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (brw->batch.ring == BLT_RING && devinfo->gen >= 6) {
       BEGIN_BATCH_BLT(4);
       OUT_BATCH(MI_FLUSH_DW);
       OUT_BATCH(0);
@@ -436,7 +450,7 @@ brw_emit_mi_flush(struct brw_context *brw)
       ADVANCE_BATCH();
    } else {
       int flags = PIPE_CONTROL_NO_WRITE | PIPE_CONTROL_RENDER_TARGET_FLUSH;
-      if (brw->gen >= 6) {
+      if (devinfo->gen >= 6) {
          flags |= PIPE_CONTROL_INSTRUCTION_INVALIDATE |
                   PIPE_CONTROL_CONST_CACHE_INVALIDATE |
                   PIPE_CONTROL_DEPTH_CACHE_FLUSH |
diff --git a/src/mesa/drivers/dri/i965/brw_primitive_restart.c b/src/mesa/drivers/dri/i965/brw_primitive_restart.c
index 3dc221e1cfb..3b696aa9cbc 100644
--- a/src/mesa/drivers/dri/i965/brw_primitive_restart.c
+++ b/src/mesa/drivers/dri/i965/brw_primitive_restart.c
@@ -80,9 +80,10 @@ can_cut_index_handle_prims(struct gl_context *ctx,
                            const struct _mesa_index_buffer *ib)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    /* Otherwise Haswell can do it all. */
-   if (brw->gen >= 8 || brw->is_haswell)
+   if (devinfo->gen >= 8 || devinfo->is_haswell)
       return true;
 
    if (!can_cut_index_handle_restart_index(ctx, ib)) {
diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c
index 94d8d8b978a..b90f6aaec80 100644
--- a/src/mesa/drivers/dri/i965/brw_program.c
+++ b/src/mesa/drivers/dri/i965/brw_program.c
@@ -287,10 +287,11 @@ static void
 brw_memory_barrier(struct gl_context *ctx, GLbitfield barriers)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    unsigned bits = (PIPE_CONTROL_DATA_CACHE_FLUSH |
                     PIPE_CONTROL_NO_WRITE |
                     PIPE_CONTROL_CS_STALL);
-   assert(brw->gen >= 7 && brw->gen <= 10);
+   assert(devinfo->gen >= 7 && devinfo->gen <= 10);
 
    if (barriers & (GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT |
                    GL_ELEMENT_ARRAY_BARRIER_BIT |
@@ -314,7 +315,7 @@ brw_memory_barrier(struct gl_context *ctx, GLbitfield barriers)
    /* Typed surface messages are handled by the render cache on IVB, so we
     * need to flush it too.
     */
-   if (brw->gen == 7 && !brw->is_haswell)
+   if (devinfo->gen == 7 && !devinfo->is_haswell)
       bits |= PIPE_CONTROL_RENDER_TARGET_FLUSH;
 
    brw_emit_pipe_control_flush(brw, bits);
@@ -324,9 +325,10 @@ static void
 brw_blend_barrier(struct gl_context *ctx)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    if (!ctx->Extensions.MESA_shader_framebuffer_fetch) {
-      if (brw->gen >= 6) {
+      if (devinfo->gen >= 6) {
          brw_emit_pipe_control_flush(brw,
                                      PIPE_CONTROL_RENDER_TARGET_FLUSH |
                                      PIPE_CONTROL_CS_STALL);
@@ -667,7 +669,8 @@ brw_setup_tex_for_precompile(struct brw_context *brw,
                              struct brw_sampler_prog_key_data *tex,
                              struct gl_program *prog)
 {
-   const bool has_shader_channel_select = brw->is_haswell || brw->gen >= 8;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   const bool has_shader_channel_select = devinfo->is_haswell || devinfo->gen >= 8;
    unsigned sampler_count = util_last_bit(prog->SamplersUsed);
    for (unsigned i = 0; i < sampler_count; i++) {
       if (!has_shader_channel_select && (prog->ShadowSamplers & (1 << i))) {
diff --git a/src/mesa/drivers/dri/i965/brw_program_cache.c b/src/mesa/drivers/dri/i965/brw_program_cache.c
index 2fd989a41c9..aa3d521b81b 100644
--- a/src/mesa/drivers/dri/i965/brw_program_cache.c
+++ b/src/mesa/drivers/dri/i965/brw_program_cache.c
@@ -213,18 +213,19 @@ static void
 brw_cache_new_bo(struct brw_cache *cache, uint32_t new_size)
 {
    struct brw_context *brw = cache->brw;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_bo *new_bo;
    void *llc_map;
 
    new_bo = brw_bo_alloc(brw->bufmgr, "program cache", new_size, 64);
    if (can_do_exec_capture(brw->screen))
       new_bo->kflags = EXEC_OBJECT_CAPTURE;
-   if (brw->has_llc)
+   if (devinfo->has_llc)
       llc_map = brw_bo_map(brw, new_bo, MAP_READ | MAP_ASYNC);
 
    /* Copy any existing data that needs to be saved. */
    if (cache->next_offset != 0) {
-      if (brw->has_llc) {
+      if (devinfo->has_llc) {
          memcpy(llc_map, cache->map, cache->next_offset);
       } else {
          void *map = brw_bo_map(brw, cache->bo, MAP_READ);
@@ -233,11 +234,11 @@ brw_cache_new_bo(struct brw_cache *cache, uint32_t new_size)
       }
    }
 
-   if (brw->has_llc)
+   if (devinfo->has_llc)
       brw_bo_unmap(cache->bo);
    brw_bo_unreference(cache->bo);
    cache->bo = new_bo;
-   cache->map = brw->has_llc ? llc_map : NULL;
+   cache->map = devinfo->has_llc ? llc_map : NULL;
    cache->bo_used_by_gpu = false;
 
    /* Since we have a new BO in place, we need to signal the units
@@ -256,6 +257,7 @@ brw_lookup_prog(const struct brw_cache *cache,
                 const void *data, unsigned data_size)
 {
    struct brw_context *brw = cache->brw;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    unsigned i;
    const struct brw_cache_item *item;
 
@@ -267,13 +269,13 @@ brw_lookup_prog(const struct brw_cache *cache,
             continue;
 
          void *map;
-         if (!brw->has_llc)
+         if (!devinfo->has_llc)
             map = brw_bo_map(brw, cache->bo, MAP_READ);
          else
             map = cache->map;
 
          ret = memcmp(map + item->offset, data, item->size);
-         if (!brw->has_llc)
+         if (!devinfo->has_llc)
             brw_bo_unmap(cache->bo);
          if (ret)
             continue;
@@ -290,6 +292,7 @@ brw_alloc_item_data(struct brw_cache *cache, uint32_t size)
 {
    uint32_t offset;
    struct brw_context *brw = cache->brw;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    /* Allocate space in the cache BO for our new program. */
    if (cache->next_offset + size > cache->bo->size) {
@@ -304,7 +307,7 @@ brw_alloc_item_data(struct brw_cache *cache, uint32_t size)
    /* If we would block on writing to an in-use program BO, just
     * recreate it.
     */
-   if (!brw->has_llc && cache->bo_used_by_gpu) {
+   if (!devinfo->has_llc && cache->bo_used_by_gpu) {
       perf_debug("Copying busy program cache buffer.\n");
       brw_cache_new_bo(cache, cache->bo->size);
    }
@@ -347,6 +350,7 @@ brw_upload_cache(struct brw_cache *cache,
                  void *out_aux)
 {
    struct brw_context *brw = cache->brw;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item);
    const struct brw_cache_item *matching_data =
       brw_lookup_prog(cache, cache_id, data, data_size);
@@ -373,7 +377,7 @@ brw_upload_cache(struct brw_cache *cache,
       item->offset = brw_alloc_item_data(cache, data_size);
 
       /* Copy data to the buffer */
-      if (brw->has_llc) {
+      if (devinfo->has_llc) {
          memcpy(cache->map + item->offset, data, data_size);
       } else {
          brw_bo_subdata(cache->bo, item->offset, data_size, data);
@@ -404,6 +408,7 @@ brw_upload_cache(struct brw_cache *cache,
 void
 brw_init_caches(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_cache *cache = &brw->cache;
 
    cache->brw = brw;
@@ -416,7 +421,7 @@ brw_init_caches(struct brw_context *brw)
    cache->bo = brw_bo_alloc(brw->bufmgr, "program cache",  4096, 64);
    if (can_do_exec_capture(brw->screen))
       cache->bo->kflags = EXEC_OBJECT_CAPTURE;
-   if (brw->has_llc)
+   if (devinfo->has_llc)
       cache->map = brw_bo_map(brw, cache->bo, MAP_READ | MAP_WRITE | MAP_ASYNC);
 }
 
@@ -491,12 +496,13 @@ brw_program_cache_check_size(struct brw_context *brw)
 static void
 brw_destroy_cache(struct brw_context *brw, struct brw_cache *cache)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    DBG("%s\n", __func__);
 
    /* This can be NULL if context creation failed early on */
    if (cache->bo) {
-      if (brw->has_llc)
+      if (devinfo->has_llc)
          brw_bo_unmap(cache->bo);
       brw_bo_unreference(cache->bo);
       cache->bo = NULL;
@@ -545,11 +551,12 @@ cache_name(enum brw_cache_id cache_id)
 void
 brw_print_program_cache(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    const struct brw_cache *cache = &brw->cache;
    struct brw_cache_item *item;
    void *map;
 
-   if (!brw->has_llc)
+   if (!devinfo->has_llc)
       map = brw_bo_map(brw, cache->bo, MAP_READ);
    else
       map = cache->map;
@@ -562,6 +569,6 @@ brw_print_program_cache(struct brw_context *brw)
       }
    }
 
-   if (!brw->has_llc)
+   if (!devinfo->has_llc)
       brw_bo_unmap(cache->bo);
 }
diff --git a/src/mesa/drivers/dri/i965/brw_queryobj.c b/src/mesa/drivers/dri/i965/brw_queryobj.c
index 04ce9a94cad..308e300958f 100644
--- a/src/mesa/drivers/dri/i965/brw_queryobj.c
+++ b/src/mesa/drivers/dri/i965/brw_queryobj.c
@@ -84,7 +84,9 @@ brw_raw_timestamp_delta(struct brw_context *brw, uint64_t time0, uint64_t time1)
 void
 brw_write_timestamp(struct brw_context *brw, struct brw_bo *query_bo, int idx)
 {
-   if (brw->gen == 6) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen == 6) {
       /* Emit Sandybridge workaround flush: */
       brw_emit_pipe_control_flush(brw,
                                   PIPE_CONTROL_CS_STALL |
@@ -93,7 +95,7 @@ brw_write_timestamp(struct brw_context *brw, struct brw_bo *query_bo, int idx)
 
    uint32_t flags = PIPE_CONTROL_WRITE_TIMESTAMP;
 
-   if (brw->gen == 9 && brw->gt == 4)
+   if (devinfo->gen == 9 && devinfo->gt == 4)
       flags |= PIPE_CONTROL_CS_STALL;
 
    brw_emit_pipe_control_write(brw, flags,
@@ -106,12 +108,13 @@ brw_write_timestamp(struct brw_context *brw, struct brw_bo *query_bo, int idx)
 void
 brw_write_depth_count(struct brw_context *brw, struct brw_bo *query_bo, int idx)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    uint32_t flags = PIPE_CONTROL_WRITE_DEPTH_COUNT | PIPE_CONTROL_DEPTH_STALL;
 
-   if (brw->gen == 9 && brw->gt == 4)
+   if (devinfo->gen == 9 && devinfo->gt == 4)
       flags |= PIPE_CONTROL_CS_STALL;
 
-   if (brw->gen >= 10) {
+   if (devinfo->gen >= 10) {
       /* "Driver must program PIPE_CONTROL with only Depth Stall Enable bit set
        * prior to programming a PIPE_CONTROL with Write PS Depth Count Post sync
        * operation."
@@ -131,11 +134,12 @@ brw_queryobj_get_results(struct gl_context *ctx,
 			 struct brw_query_object *query)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    int i;
    uint64_t *results;
 
-   assert(brw->gen < 6);
+   assert(devinfo->gen < 6);
 
    if (query->bo == NULL)
       return;
@@ -256,9 +260,10 @@ static void
 brw_begin_query(struct gl_context *ctx, struct gl_query_object *q)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_query_object *query = (struct brw_query_object *)q;
 
-   assert(brw->gen < 6);
+   assert(devinfo->gen < 6);
 
    switch (query->Base.Target) {
    case GL_TIME_ELAPSED_EXT:
@@ -327,9 +332,10 @@ static void
 brw_end_query(struct gl_context *ctx, struct gl_query_object *q)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_query_object *query = (struct brw_query_object *)q;
 
-   assert(brw->gen < 6);
+   assert(devinfo->gen < 6);
 
    switch (query->Base.Target) {
    case GL_TIME_ELAPSED_EXT:
@@ -380,9 +386,11 @@ brw_end_query(struct gl_context *ctx, struct gl_query_object *q)
  */
 static void brw_wait_query(struct gl_context *ctx, struct gl_query_object *q)
 {
+   struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_query_object *query = (struct brw_query_object *)q;
 
-   assert(brw_context(ctx)->gen < 6);
+   assert(devinfo->gen < 6);
 
    brw_queryobj_get_results(ctx, query);
    query->Base.Ready = true;
@@ -397,9 +405,10 @@ static void brw_wait_query(struct gl_context *ctx, struct gl_query_object *q)
 static void brw_check_query(struct gl_context *ctx, struct gl_query_object *q)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_query_object *query = (struct brw_query_object *)q;
 
-   assert(brw->gen < 6);
+   assert(devinfo->gen < 6);
 
    /* From the GL_ARB_occlusion_query spec:
     *
@@ -427,8 +436,9 @@ static void
 ensure_bo_has_space(struct gl_context *ctx, struct brw_query_object *query)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
-   assert(brw->gen < 6);
+   assert(devinfo->gen < 6);
 
    if (!query->bo || query->last_index * 2 + 1 >= 4096 / sizeof(uint64_t)) {
 
diff --git a/src/mesa/drivers/dri/i965/brw_sampler_state.c b/src/mesa/drivers/dri/i965/brw_sampler_state.c
new file mode 100644
index 00000000000..f59d9933280
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/brw_sampler_state.c
@@ -0,0 +1,761 @@
+/*
+ Copyright (C) Intel Corp.  2006.  All Rights Reserved.
+ Intel funded Tungsten Graphics to
+ develop this 3D driver.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ **********************************************************************/
+ /*
+  * Authors:
+  *   Keith Whitwell <keithw at vmware.com>
+  */
+
+/**
+ * @file brw_sampler_state.c
+ *
+ * This file contains code for emitting SAMPLER_STATE structures, which
+ * specifies filter modes, wrap modes, border color, and so on.
+ */
+
+#include "brw_context.h"
+#include "brw_state.h"
+#include "brw_defines.h"
+#include "intel_batchbuffer.h"
+#include "intel_mipmap_tree.h"
+
+#include "main/macros.h"
+#include "main/samplerobj.h"
+#include "util/half_float.h"
+
+/**
+ * Emit a 3DSTATE_SAMPLER_STATE_POINTERS_{VS,HS,GS,DS,PS} packet.
+ */
+static void
+gen7_emit_sampler_state_pointers_xs(struct brw_context *brw,
+                                    struct brw_stage_state *stage_state)
+{
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   static const uint16_t packet_headers[] = {
+      [MESA_SHADER_VERTEX] = _3DSTATE_SAMPLER_STATE_POINTERS_VS,
+      [MESA_SHADER_TESS_CTRL] = _3DSTATE_SAMPLER_STATE_POINTERS_HS,
+      [MESA_SHADER_TESS_EVAL] = _3DSTATE_SAMPLER_STATE_POINTERS_DS,
+      [MESA_SHADER_GEOMETRY] = _3DSTATE_SAMPLER_STATE_POINTERS_GS,
+      [MESA_SHADER_FRAGMENT] = _3DSTATE_SAMPLER_STATE_POINTERS_PS,
+   };
+
+   /* Ivybridge requires a workaround flush before VS packets. */
+   if (devinfo->gen == 7 && !devinfo->is_haswell && !devinfo->is_baytrail &&
+       stage_state->stage == MESA_SHADER_VERTEX) {
+      gen7_emit_vs_workaround_flush(brw);
+   }
+
+   BEGIN_BATCH(2);
+   OUT_BATCH(packet_headers[stage_state->stage] << 16 | (2 - 2));
+   OUT_BATCH(stage_state->sampler_offset);
+   ADVANCE_BATCH();
+}
+
+/**
+ * Emit a SAMPLER_STATE structure, given all the fields.
+ */
+void
+brw_emit_sampler_state(struct brw_context *brw,
+                       uint32_t *ss,
+                       uint32_t batch_offset_for_sampler_state,
+                       unsigned min_filter,
+                       unsigned mag_filter,
+                       unsigned mip_filter,
+                       unsigned max_anisotropy,
+                       unsigned address_rounding,
+                       unsigned wrap_s,
+                       unsigned wrap_t,
+                       unsigned wrap_r,
+                       unsigned base_level,
+                       unsigned min_lod,
+                       unsigned max_lod,
+                       int lod_bias,
+                       unsigned shadow_function,
+                       bool non_normalized_coordinates,
+                       uint32_t border_color_offset)
+{
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   ss[0] = BRW_SAMPLER_LOD_PRECLAMP_ENABLE |
+           SET_FIELD(mip_filter, BRW_SAMPLER_MIP_FILTER) |
+           SET_FIELD(mag_filter, BRW_SAMPLER_MAG_FILTER) |
+           SET_FIELD(min_filter, BRW_SAMPLER_MIN_FILTER);
+
+   ss[2] = border_color_offset;
+   if (devinfo->gen < 6) {
+      ss[2] += brw->batch.bo->offset64; /* reloc */
+      brw_emit_reloc(&brw->batch, batch_offset_for_sampler_state + 8,
+                     brw->batch.bo, border_color_offset,
+                     I915_GEM_DOMAIN_SAMPLER, 0);
+   }
+
+   ss[3] = SET_FIELD(max_anisotropy, BRW_SAMPLER_MAX_ANISOTROPY) |
+           SET_FIELD(address_rounding, BRW_SAMPLER_ADDRESS_ROUNDING);
+
+   if (devinfo->gen >= 7) {
+      ss[0] |= SET_FIELD(lod_bias & 0x1fff, GEN7_SAMPLER_LOD_BIAS);
+
+      if (min_filter == BRW_MAPFILTER_ANISOTROPIC)
+         ss[0] |= GEN7_SAMPLER_EWA_ANISOTROPIC_ALGORITHM;
+
+      ss[1] = SET_FIELD(min_lod, GEN7_SAMPLER_MIN_LOD) |
+              SET_FIELD(max_lod, GEN7_SAMPLER_MAX_LOD) |
+              SET_FIELD(shadow_function, GEN7_SAMPLER_SHADOW_FUNCTION);
+
+      ss[3] |= SET_FIELD(wrap_s, BRW_SAMPLER_TCX_WRAP_MODE) |
+               SET_FIELD(wrap_t, BRW_SAMPLER_TCY_WRAP_MODE) |
+               SET_FIELD(wrap_r, BRW_SAMPLER_TCZ_WRAP_MODE);
+
+      if (non_normalized_coordinates)
+         ss[3] |= GEN7_SAMPLER_NON_NORMALIZED_COORDINATES;
+   } else {
+      ss[0] |= SET_FIELD(lod_bias & 0x7ff, GEN4_SAMPLER_LOD_BIAS) |
+               SET_FIELD(shadow_function, GEN4_SAMPLER_SHADOW_FUNCTION);
+
+      /* This field has existed since the original i965, but is declared MBZ
+       * until Sandy Bridge.  According to the PRM:
+       *
+       *    "This was added to match OpenGL semantics"
+       *
+       * In particular, OpenGL allowed you to offset by 0.5 in certain cases
+       * to get slightly better filtering.  On Ivy Bridge and above, it
+       * appears that this is added to RENDER_SURFACE_STATE::SurfaceMinLOD so
+       * the right value is 0.0 or 0.5 (if you want the wacky behavior).  On
+       * Sandy Bridge, however, this sum does not seem to occur and you have
+       * to set it to the actual base level of the texture.
+       */
+      if (devinfo->gen == 6)
+         ss[0] |= SET_FIELD(base_level, BRW_SAMPLER_BASE_MIPLEVEL);
+
+      if (devinfo->gen == 6 && min_filter != mag_filter)
+         ss[0] |= GEN6_SAMPLER_MIN_MAG_NOT_EQUAL;
+
+      ss[1] = SET_FIELD(min_lod, GEN4_SAMPLER_MIN_LOD) |
+              SET_FIELD(max_lod, GEN4_SAMPLER_MAX_LOD) |
+              SET_FIELD(wrap_s, BRW_SAMPLER_TCX_WRAP_MODE) |
+              SET_FIELD(wrap_t, BRW_SAMPLER_TCY_WRAP_MODE) |
+              SET_FIELD(wrap_r, BRW_SAMPLER_TCZ_WRAP_MODE);
+
+      if (devinfo->gen >= 6 && non_normalized_coordinates)
+         ss[3] |= GEN6_SAMPLER_NON_NORMALIZED_COORDINATES;
+   }
+}
+
+static uint32_t
+translate_wrap_mode(struct brw_context *brw, GLenum wrap, bool using_nearest)
+{
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   switch (wrap) {
+   case GL_REPEAT:
+      return BRW_TEXCOORDMODE_WRAP;
+   case GL_CLAMP:
+      /* GL_CLAMP is the weird mode where coordinates are clamped to
+       * [0.0, 1.0], so linear filtering of coordinates outside of
+       * [0.0, 1.0] give you half edge texel value and half border
+       * color.
+       *
+       * Gen8+ supports this natively.
+       */
+      if (devinfo->gen >= 8)
+         return GEN8_TEXCOORDMODE_HALF_BORDER;
+
+      /* On Gen4-7.5, we clamp the coordinates in the fragment shader
+       * and set clamp_border here, which gets the result desired.
+       * We just use clamp(_to_edge) for nearest, because for nearest
+       * clamping to 1.0 gives border color instead of the desired
+       * edge texels.
+       */
+      if (using_nearest)
+	 return BRW_TEXCOORDMODE_CLAMP;
+      else
+	 return BRW_TEXCOORDMODE_CLAMP_BORDER;
+   case GL_CLAMP_TO_EDGE:
+      return BRW_TEXCOORDMODE_CLAMP;
+   case GL_CLAMP_TO_BORDER:
+      return BRW_TEXCOORDMODE_CLAMP_BORDER;
+   case GL_MIRRORED_REPEAT:
+      return BRW_TEXCOORDMODE_MIRROR;
+   case GL_MIRROR_CLAMP_TO_EDGE:
+      return BRW_TEXCOORDMODE_MIRROR_ONCE;
+   default:
+      return BRW_TEXCOORDMODE_WRAP;
+   }
+}
+
+/**
+ * Return true if the given wrap mode requires the border color to exist.
+ */
+static bool
+wrap_mode_needs_border_color(unsigned wrap_mode)
+{
+   return wrap_mode == BRW_TEXCOORDMODE_CLAMP_BORDER ||
+          wrap_mode == GEN8_TEXCOORDMODE_HALF_BORDER;
+}
+
+static bool
+has_component(mesa_format format, int i)
+{
+   if (_mesa_is_format_color_format(format))
+      return _mesa_format_has_color_component(format, i);
+
+   /* depth and stencil have only one component */
+   return i == 0;
+}
+
+/**
+ * Upload SAMPLER_BORDER_COLOR_STATE.
+ */
+static void
+upload_default_color(struct brw_context *brw,
+                     const struct gl_sampler_object *sampler,
+                     mesa_format format, GLenum base_format,
+                     bool is_integer_format, bool is_stencil_sampling,
+                     uint32_t *sdc_offset)
+{
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   union gl_color_union color;
+
+   switch (base_format) {
+   case GL_DEPTH_COMPONENT:
+      /* GL specs that border color for depth textures is taken from the
+       * R channel, while the hardware uses A.  Spam R into all the
+       * channels for safety.
+       */
+      color.ui[0] = sampler->BorderColor.ui[0];
+      color.ui[1] = sampler->BorderColor.ui[0];
+      color.ui[2] = sampler->BorderColor.ui[0];
+      color.ui[3] = sampler->BorderColor.ui[0];
+      break;
+   case GL_ALPHA:
+      color.ui[0] = 0u;
+      color.ui[1] = 0u;
+      color.ui[2] = 0u;
+      color.ui[3] = sampler->BorderColor.ui[3];
+      break;
+   case GL_INTENSITY:
+      color.ui[0] = sampler->BorderColor.ui[0];
+      color.ui[1] = sampler->BorderColor.ui[0];
+      color.ui[2] = sampler->BorderColor.ui[0];
+      color.ui[3] = sampler->BorderColor.ui[0];
+      break;
+   case GL_LUMINANCE:
+      color.ui[0] = sampler->BorderColor.ui[0];
+      color.ui[1] = sampler->BorderColor.ui[0];
+      color.ui[2] = sampler->BorderColor.ui[0];
+      color.ui[3] = float_as_int(1.0);
+      break;
+   case GL_LUMINANCE_ALPHA:
+      color.ui[0] = sampler->BorderColor.ui[0];
+      color.ui[1] = sampler->BorderColor.ui[0];
+      color.ui[2] = sampler->BorderColor.ui[0];
+      color.ui[3] = sampler->BorderColor.ui[3];
+      break;
+   default:
+      color.ui[0] = sampler->BorderColor.ui[0];
+      color.ui[1] = sampler->BorderColor.ui[1];
+      color.ui[2] = sampler->BorderColor.ui[2];
+      color.ui[3] = sampler->BorderColor.ui[3];
+      break;
+   }
+
+   /* In some cases we use an RGBA surface format for GL RGB textures,
+    * where we've initialized the A channel to 1.0.  We also have to set
+    * the border color alpha to 1.0 in that case.
+    */
+   if (base_format == GL_RGB)
+      color.ui[3] = float_as_int(1.0);
+
+   if (devinfo->gen >= 8) {
+      /* On Broadwell, the border color is represented as four 32-bit floats,
+       * integers, or unsigned values, interpreted according to the surface
+       * format.  This matches the sampler->BorderColor union exactly; just
+       * memcpy the values.
+       */
+      uint32_t *sdc = brw_state_batch(brw, 4 * 4, 64, sdc_offset);
+      memcpy(sdc, color.ui, 4 * 4);
+   } else if (devinfo->is_haswell && (is_integer_format || is_stencil_sampling)) {
+      /* Haswell's integer border color support is completely insane:
+       * SAMPLER_BORDER_COLOR_STATE is 20 DWords.  The first four are
+       * for float colors.  The next 12 DWords are MBZ and only exist to
+       * pad it out to a 64 byte cacheline boundary.  DWords 16-19 then
+       * contain integer colors; these are only used if SURFACE_STATE
+       * has the "Integer Surface Format" bit set.  Even then, the
+       * arrangement of the RGBA data devolves into madness.
+       */
+      uint32_t *sdc = brw_state_batch(brw, 20 * 4, 512, sdc_offset);
+      memset(sdc, 0, 20 * 4);
+      sdc = &sdc[16];
+
+      bool stencil = format == MESA_FORMAT_S_UINT8 || is_stencil_sampling;
+      const int bits_per_channel =
+         _mesa_get_format_bits(format, stencil ? GL_STENCIL_BITS : GL_RED_BITS);
+
+      /* From the Haswell PRM, "Command Reference: Structures", Page 36:
+       * "If any color channel is missing from the surface format,
+       *  corresponding border color should be programmed as zero and if
+       *  alpha channel is missing, corresponding Alpha border color should
+       *  be programmed as 1."
+       */
+      unsigned c[4] = { 0, 0, 0, 1 };
+      for (int i = 0; i < 4; i++) {
+         if (has_component(format, i))
+            c[i] = color.ui[i];
+      }
+
+      switch (bits_per_channel) {
+      case 8:
+         /* Copy RGBA in order. */
+         for (int i = 0; i < 4; i++)
+            ((uint8_t *) sdc)[i] = c[i];
+         break;
+      case 10:
+         /* R10G10B10A2_UINT is treated like a 16-bit format. */
+      case 16:
+         ((uint16_t *) sdc)[0] = c[0]; /* R -> DWord 0, bits 15:0  */
+         ((uint16_t *) sdc)[1] = c[1]; /* G -> DWord 0, bits 31:16 */
+         /* DWord 1 is Reserved/MBZ! */
+         ((uint16_t *) sdc)[4] = c[2]; /* B -> DWord 2, bits 15:0  */
+         ((uint16_t *) sdc)[5] = c[3]; /* A -> DWord 3, bits 31:16 */
+         break;
+      case 32:
+         if (base_format == GL_RG) {
+            /* Careful inspection of the tables reveals that for RG32 formats,
+             * the green channel needs to go where blue normally belongs.
+             */
+            sdc[0] = c[0];
+            sdc[2] = c[1];
+            sdc[3] = 1;
+         } else {
+            /* Copy RGBA in order. */
+            for (int i = 0; i < 4; i++)
+               sdc[i] = c[i];
+         }
+         break;
+      default:
+         assert(!"Invalid number of bits per channel in integer format.");
+         break;
+      }
+   } else if (devinfo->gen == 5 || devinfo->gen == 6) {
+      struct gen5_sampler_default_color *sdc;
+
+      sdc = brw_state_batch(brw, sizeof(*sdc), 32, sdc_offset);
+
+      memset(sdc, 0, sizeof(*sdc));
+
+      UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[0], color.f[0]);
+      UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[1], color.f[1]);
+      UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[2], color.f[2]);
+      UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[3], color.f[3]);
+
+      UNCLAMPED_FLOAT_TO_USHORT(sdc->us[0], color.f[0]);
+      UNCLAMPED_FLOAT_TO_USHORT(sdc->us[1], color.f[1]);
+      UNCLAMPED_FLOAT_TO_USHORT(sdc->us[2], color.f[2]);
+      UNCLAMPED_FLOAT_TO_USHORT(sdc->us[3], color.f[3]);
+
+      UNCLAMPED_FLOAT_TO_SHORT(sdc->s[0], color.f[0]);
+      UNCLAMPED_FLOAT_TO_SHORT(sdc->s[1], color.f[1]);
+      UNCLAMPED_FLOAT_TO_SHORT(sdc->s[2], color.f[2]);
+      UNCLAMPED_FLOAT_TO_SHORT(sdc->s[3], color.f[3]);
+
+      sdc->hf[0] = _mesa_float_to_half(color.f[0]);
+      sdc->hf[1] = _mesa_float_to_half(color.f[1]);
+      sdc->hf[2] = _mesa_float_to_half(color.f[2]);
+      sdc->hf[3] = _mesa_float_to_half(color.f[3]);
+
+      sdc->b[0] = sdc->s[0] >> 8;
+      sdc->b[1] = sdc->s[1] >> 8;
+      sdc->b[2] = sdc->s[2] >> 8;
+      sdc->b[3] = sdc->s[3] >> 8;
+
+      sdc->f[0] = color.f[0];
+      sdc->f[1] = color.f[1];
+      sdc->f[2] = color.f[2];
+      sdc->f[3] = color.f[3];
+   } else {
+      float *sdc = brw_state_batch(brw, 4 * 4, 32, sdc_offset);
+      memcpy(sdc, color.f, 4 * 4);
+   }
+}
+
+/**
+ * Sets the sampler state for a single unit based off of the sampler key
+ * entry.
+ */
+static void
+brw_update_sampler_state(struct brw_context *brw,
+                         GLenum target, bool tex_cube_map_seamless,
+                         GLfloat tex_unit_lod_bias,
+                         mesa_format format, GLenum base_format,
+                         const struct gl_texture_object *texObj,
+                         const struct gl_sampler_object *sampler,
+                         uint32_t *sampler_state,
+                         uint32_t batch_offset_for_sampler_state)
+{
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   unsigned min_filter, mag_filter, mip_filter;
+
+   /* Select min and mip filters. */
+   switch (sampler->MinFilter) {
+   case GL_NEAREST:
+      min_filter = BRW_MAPFILTER_NEAREST;
+      mip_filter = BRW_MIPFILTER_NONE;
+      break;
+   case GL_LINEAR:
+      min_filter = BRW_MAPFILTER_LINEAR;
+      mip_filter = BRW_MIPFILTER_NONE;
+      break;
+   case GL_NEAREST_MIPMAP_NEAREST:
+      min_filter = BRW_MAPFILTER_NEAREST;
+      mip_filter = BRW_MIPFILTER_NEAREST;
+      break;
+   case GL_LINEAR_MIPMAP_NEAREST:
+      min_filter = BRW_MAPFILTER_LINEAR;
+      mip_filter = BRW_MIPFILTER_NEAREST;
+      break;
+   case GL_NEAREST_MIPMAP_LINEAR:
+      min_filter = BRW_MAPFILTER_NEAREST;
+      mip_filter = BRW_MIPFILTER_LINEAR;
+      break;
+   case GL_LINEAR_MIPMAP_LINEAR:
+      min_filter = BRW_MAPFILTER_LINEAR;
+      mip_filter = BRW_MIPFILTER_LINEAR;
+      break;
+   default:
+      unreachable("not reached");
+   }
+
+   /* Select mag filter. */
+   if (sampler->MagFilter == GL_LINEAR)
+      mag_filter = BRW_MAPFILTER_LINEAR;
+   else
+      mag_filter = BRW_MAPFILTER_NEAREST;
+
+   /* Enable anisotropic filtering if desired. */
+   unsigned max_anisotropy = BRW_ANISORATIO_2;
+   if (sampler->MaxAnisotropy > 1.0f) {
+      if (min_filter == BRW_MAPFILTER_LINEAR)
+         min_filter = BRW_MAPFILTER_ANISOTROPIC;
+      if (mag_filter == BRW_MAPFILTER_LINEAR)
+         mag_filter = BRW_MAPFILTER_ANISOTROPIC;
+
+      if (sampler->MaxAnisotropy > 2.0f) {
+	 max_anisotropy =
+            MIN2((sampler->MaxAnisotropy - 2) / 2, BRW_ANISORATIO_16);
+      }
+   }
+
+   /* Set address rounding bits if not using nearest filtering. */
+   unsigned address_rounding = 0;
+   if (min_filter != BRW_MAPFILTER_NEAREST) {
+      address_rounding |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN |
+                          BRW_ADDRESS_ROUNDING_ENABLE_V_MIN |
+                          BRW_ADDRESS_ROUNDING_ENABLE_R_MIN;
+   }
+   if (mag_filter != BRW_MAPFILTER_NEAREST) {
+      address_rounding |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG |
+                          BRW_ADDRESS_ROUNDING_ENABLE_V_MAG |
+                          BRW_ADDRESS_ROUNDING_ENABLE_R_MAG;
+   }
+
+   bool either_nearest =
+      sampler->MinFilter == GL_NEAREST || sampler->MagFilter == GL_NEAREST;
+   unsigned wrap_s = translate_wrap_mode(brw, sampler->WrapS, either_nearest);
+   unsigned wrap_t = translate_wrap_mode(brw, sampler->WrapT, either_nearest);
+   unsigned wrap_r = translate_wrap_mode(brw, sampler->WrapR, either_nearest);
+
+   if (target == GL_TEXTURE_CUBE_MAP ||
+       target == GL_TEXTURE_CUBE_MAP_ARRAY) {
+      /* Cube maps must use the same wrap mode for all three coordinate
+       * dimensions.  Prior to Haswell, only CUBE and CLAMP are valid.
+       *
+       * Ivybridge and Baytrail seem to have problems with CUBE mode and
+       * integer formats.  Fall back to CLAMP for now.
+       */
+      if ((tex_cube_map_seamless || sampler->CubeMapSeamless) &&
+          !(devinfo->gen == 7 && !devinfo->is_haswell && texObj->_IsIntegerFormat)) {
+	 wrap_s = BRW_TEXCOORDMODE_CUBE;
+	 wrap_t = BRW_TEXCOORDMODE_CUBE;
+	 wrap_r = BRW_TEXCOORDMODE_CUBE;
+      } else {
+	 wrap_s = BRW_TEXCOORDMODE_CLAMP;
+	 wrap_t = BRW_TEXCOORDMODE_CLAMP;
+	 wrap_r = BRW_TEXCOORDMODE_CLAMP;
+      }
+   } else if (target == GL_TEXTURE_1D) {
+      /* There's a bug in 1D texture sampling - it actually pays
+       * attention to the wrap_t value, though it should not.
+       * Override the wrap_t value here to GL_REPEAT to keep
+       * any nonexistent border pixels from floating in.
+       */
+      wrap_t = BRW_TEXCOORDMODE_WRAP;
+   }
+
+   /* Set shadow function. */
+   unsigned shadow_function = 0;
+   if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
+      shadow_function =
+	 intel_translate_shadow_compare_func(sampler->CompareFunc);
+   }
+
+   const int lod_bits = devinfo->gen >= 7 ? 8 : 6;
+   const float hw_max_lod = devinfo->gen >= 7 ? 14 : 13;
+   const unsigned base_level =
+      U_FIXED(CLAMP(texObj->MinLevel + texObj->BaseLevel, 0, hw_max_lod), 1);
+   const unsigned min_lod =
+      U_FIXED(CLAMP(sampler->MinLod, 0, hw_max_lod), lod_bits);
+   const unsigned max_lod =
+      U_FIXED(CLAMP(sampler->MaxLod, 0, hw_max_lod), lod_bits);
+   const int lod_bias =
+      S_FIXED(CLAMP(tex_unit_lod_bias + sampler->LodBias, -16, 15), lod_bits);
+
+   /* Upload the border color if necessary.  If not, just point it at
+    * offset 0 (the start of the batch) - the color should be ignored,
+    * but that address won't fault in case something reads it anyway.
+    */
+   uint32_t border_color_offset = 0;
+   if (wrap_mode_needs_border_color(wrap_s) ||
+       wrap_mode_needs_border_color(wrap_t) ||
+       wrap_mode_needs_border_color(wrap_r)) {
+      upload_default_color(brw, sampler, format, base_format,
+                           texObj->_IsIntegerFormat, texObj->StencilSampling,
+                           &border_color_offset);
+   }
+
+   const bool non_normalized_coords = target == GL_TEXTURE_RECTANGLE;
+
+   brw_emit_sampler_state(brw,
+                          sampler_state,
+                          batch_offset_for_sampler_state,
+                          min_filter, mag_filter, mip_filter,
+                          max_anisotropy,
+                          address_rounding,
+                          wrap_s, wrap_t, wrap_r,
+                          base_level, min_lod, max_lod, lod_bias,
+                          shadow_function,
+                          non_normalized_coords,
+                          border_color_offset);
+}
+
+static void
+update_sampler_state(struct brw_context *brw,
+                     int unit,
+                     uint32_t *sampler_state,
+                     uint32_t batch_offset_for_sampler_state)
+{
+   struct gl_context *ctx = &brw->ctx;
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   const struct gl_texture_object *texObj = texUnit->_Current;
+   const struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
+
+   /* These don't use samplers at all. */
+   if (texObj->Target == GL_TEXTURE_BUFFER)
+      return;
+
+   struct gl_texture_image *firstImage = texObj->Image[0][texObj->BaseLevel];
+   brw_update_sampler_state(brw, texObj->Target, ctx->Texture.CubeMapSeamless,
+                            texUnit->LodBias,
+                            firstImage->TexFormat, firstImage->_BaseFormat,
+                            texObj, sampler,
+                            sampler_state, batch_offset_for_sampler_state);
+}
+
+static void
+brw_upload_sampler_state_table(struct brw_context *brw,
+                               struct gl_program *prog,
+                               struct brw_stage_state *stage_state)
+{
+   struct gl_context *ctx = &brw->ctx;
+   uint32_t sampler_count = stage_state->sampler_count;
+
+   GLbitfield SamplersUsed = prog->SamplersUsed;
+
+   if (sampler_count == 0)
+      return;
+
+   /* SAMPLER_STATE is 4 DWords on all platforms. */
+   const int dwords = 4;
+   const int size_in_bytes = dwords * sizeof(uint32_t);
+
+   uint32_t *sampler_state = brw_state_batch(brw,
+                                             sampler_count * size_in_bytes,
+                                             32, &stage_state->sampler_offset);
+   memset(sampler_state, 0, sampler_count * size_in_bytes);
+
+   uint32_t batch_offset_for_sampler_state = stage_state->sampler_offset;
+
+   for (unsigned s = 0; s < sampler_count; s++) {
+      if (SamplersUsed & (1 << s)) {
+         const unsigned unit = prog->SamplerUnits[s];
+         if (ctx->Texture.Unit[unit]._Current) {
+            update_sampler_state(brw, unit, sampler_state,
+                                     batch_offset_for_sampler_state);
+         }
+      }
+
+      sampler_state += dwords;
+      batch_offset_for_sampler_state += size_in_bytes;
+   }
+
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen >= 7 && stage_state->stage != MESA_SHADER_COMPUTE) {
+      /* Emit a 3DSTATE_SAMPLER_STATE_POINTERS_XS packet. */
+      gen7_emit_sampler_state_pointers_xs(brw, stage_state);
+   } else {
+      /* Flag that the sampler state table pointer has changed; later atoms
+       * will handle it.
+       */
+      brw->ctx.NewDriverState |= BRW_NEW_SAMPLER_STATE_TABLE;
+   }
+}
+
+static void
+brw_upload_fs_samplers(struct brw_context *brw)
+{
+   /* BRW_NEW_FRAGMENT_PROGRAM */
+   struct gl_program *fs = (struct gl_program *) brw->fragment_program;
+   brw_upload_sampler_state_table(brw, fs, &brw->wm.base);
+}
+
+const struct brw_tracked_state brw_fs_samplers = {
+   .dirty = {
+      .mesa = _NEW_TEXTURE,
+      .brw = BRW_NEW_BATCH |
+             BRW_NEW_BLORP |
+             BRW_NEW_FRAGMENT_PROGRAM,
+   },
+   .emit = brw_upload_fs_samplers,
+};
+
+static void
+brw_upload_vs_samplers(struct brw_context *brw)
+{
+   /* BRW_NEW_VERTEX_PROGRAM */
+   struct gl_program *vs = (struct gl_program *) brw->vertex_program;
+   brw_upload_sampler_state_table(brw, vs, &brw->vs.base);
+}
+
+
+const struct brw_tracked_state brw_vs_samplers = {
+   .dirty = {
+      .mesa = _NEW_TEXTURE,
+      .brw = BRW_NEW_BATCH |
+             BRW_NEW_BLORP |
+             BRW_NEW_VERTEX_PROGRAM,
+   },
+   .emit = brw_upload_vs_samplers,
+};
+
+
+static void
+brw_upload_gs_samplers(struct brw_context *brw)
+{
+   /* BRW_NEW_GEOMETRY_PROGRAM */
+   struct gl_program *gs = (struct gl_program *) brw->geometry_program;
+   if (!gs)
+      return;
+
+   brw_upload_sampler_state_table(brw, gs, &brw->gs.base);
+}
+
+
+const struct brw_tracked_state brw_gs_samplers = {
+   .dirty = {
+      .mesa = _NEW_TEXTURE,
+      .brw = BRW_NEW_BATCH |
+             BRW_NEW_BLORP |
+             BRW_NEW_GEOMETRY_PROGRAM,
+   },
+   .emit = brw_upload_gs_samplers,
+};
+
+
+static void
+brw_upload_tcs_samplers(struct brw_context *brw)
+{
+   /* BRW_NEW_TESS_PROGRAMS */
+   struct gl_program *tcs = (struct gl_program *) brw->tess_ctrl_program;
+   if (!tcs)
+      return;
+
+   brw_upload_sampler_state_table(brw, tcs, &brw->tcs.base);
+}
+
+
+const struct brw_tracked_state brw_tcs_samplers = {
+   .dirty = {
+      .mesa = _NEW_TEXTURE,
+      .brw = BRW_NEW_BATCH |
+             BRW_NEW_BLORP |
+             BRW_NEW_TESS_PROGRAMS,
+   },
+   .emit = brw_upload_tcs_samplers,
+};
+
+
+static void
+brw_upload_tes_samplers(struct brw_context *brw)
+{
+   /* BRW_NEW_TESS_PROGRAMS */
+   struct gl_program *tes = (struct gl_program *) brw->tess_eval_program;
+   if (!tes)
+      return;
+
+   brw_upload_sampler_state_table(brw, tes, &brw->tes.base);
+}
+
+
+const struct brw_tracked_state brw_tes_samplers = {
+   .dirty = {
+      .mesa = _NEW_TEXTURE,
+      .brw = BRW_NEW_BATCH |
+             BRW_NEW_BLORP |
+             BRW_NEW_TESS_PROGRAMS,
+   },
+   .emit = brw_upload_tes_samplers,
+};
+
+static void
+brw_upload_cs_samplers(struct brw_context *brw)
+{
+   /* BRW_NEW_COMPUTE_PROGRAM */
+   struct gl_program *cs = (struct gl_program *) brw->compute_program;
+   if (!cs)
+      return;
+
+   brw_upload_sampler_state_table(brw, cs, &brw->cs.base);
+}
+
+const struct brw_tracked_state brw_cs_samplers = {
+   .dirty = {
+      .mesa = _NEW_TEXTURE,
+      .brw = BRW_NEW_BATCH |
+             BRW_NEW_BLORP |
+             BRW_NEW_COMPUTE_PROGRAM,
+   },
+   .emit = brw_upload_cs_samplers,
+};
diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c
index 926597b6258..419fe10d79d 100644
--- a/src/mesa/drivers/dri/i965/brw_state_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_state_upload.c
@@ -48,6 +48,8 @@
 static void
 brw_upload_initial_gpu_state(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* On platforms with hardware contexts, we can set our initial GPU state
     * right away rather than doing it via state atoms.  This saves a small
     * amount of overhead on every draw call.
@@ -55,13 +57,13 @@ brw_upload_initial_gpu_state(struct brw_context *brw)
    if (!brw->hw_ctx)
       return;
 
-   if (brw->gen == 6)
+   if (devinfo->gen == 6)
       brw_emit_post_sync_nonzero_flush(brw);
 
    brw_upload_invariant_state(brw);
 
    /* Recommended optimization for Victim Cache eviction in pixel backend. */
-   if (brw->gen >= 9) {
+   if (devinfo->gen >= 9) {
       BEGIN_BATCH(3);
       OUT_BATCH(MI_LOAD_REGISTER_IMM | (3 - 2));
       OUT_BATCH(GEN7_CACHE_MODE_1);
@@ -72,7 +74,7 @@ brw_upload_initial_gpu_state(struct brw_context *brw)
       ADVANCE_BATCH();
    }
 
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       gen8_emit_3dstate_sample_pattern(brw);
 
       BEGIN_BATCH(5);
@@ -129,6 +131,7 @@ brw_copy_pipeline_atoms(struct brw_context *brw,
 
 void brw_init_state( struct brw_context *brw )
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
 
    /* Force the first brw_select_pipeline to emit pipeline select */
@@ -136,21 +139,21 @@ void brw_init_state( struct brw_context *brw )
 
    brw_init_caches(brw);
 
-   if (brw->gen >= 10)
+   if (devinfo->gen >= 10)
       gen10_init_atoms(brw);
-   else if (brw->gen >= 9)
+   else if (devinfo->gen >= 9)
       gen9_init_atoms(brw);
-   else if (brw->gen >= 8)
+   else if (devinfo->gen >= 8)
       gen8_init_atoms(brw);
-   else if (brw->is_haswell)
+   else if (devinfo->is_haswell)
       gen75_init_atoms(brw);
-   else if (brw->gen >= 7)
+   else if (devinfo->gen >= 7)
       gen7_init_atoms(brw);
-   else if (brw->gen >= 6)
+   else if (devinfo->gen >= 6)
       gen6_init_atoms(brw);
-   else if (brw->gen >= 5)
+   else if (devinfo->gen >= 5)
       gen5_init_atoms(brw);
-   else if (brw->is_g4x)
+   else if (devinfo->is_g4x)
       gen45_init_atoms(brw);
    else
       gen4_init_atoms(brw);
@@ -353,13 +356,14 @@ static inline void
 brw_upload_programs(struct brw_context *brw,
                     enum brw_pipeline pipeline)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
 
    if (pipeline == BRW_RENDER_PIPELINE) {
       brw_upload_vs_prog(brw);
       brw_upload_tess_programs(brw);
 
-      if (brw->gen < 6)
+      if (devinfo->gen < 6)
          brw_upload_ff_gs_prog(brw);
       else
          brw_upload_gs_prog(brw);
@@ -394,7 +398,7 @@ brw_upload_programs(struct brw_context *brw,
 
       brw_upload_wm_prog(brw);
 
-      if (brw->gen < 6) {
+      if (devinfo->gen < 6) {
          brw_upload_clip_prog(brw);
          brw_upload_sf_prog(brw);
       }
@@ -426,6 +430,7 @@ static inline void
 brw_upload_pipeline_state(struct brw_context *brw,
                           enum brw_pipeline pipeline)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    int i;
    static int dirty_count = 0;
@@ -488,7 +493,7 @@ brw_upload_pipeline_state(struct brw_context *brw,
       return;
 
    /* Emit Sandybridge workaround flushes on every primitive, for safety. */
-   if (brw->gen == 6)
+   if (devinfo->gen == 6)
       brw_emit_post_sync_nonzero_flush(brw);
 
    brw_upload_programs(brw, pipeline);
diff --git a/src/mesa/drivers/dri/i965/brw_surface_formats.c b/src/mesa/drivers/dri/i965/brw_surface_formats.c
index a2bc1ded6db..879cb424533 100644
--- a/src/mesa/drivers/dri/i965/brw_surface_formats.c
+++ b/src/mesa/drivers/dri/i965/brw_surface_formats.c
@@ -412,6 +412,7 @@ bool
 brw_render_target_supported(struct brw_context *brw,
 			    struct gl_renderbuffer *rb)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    mesa_format format = rb->Format;
 
    /* Many integer formats are promoted to RGBA (like XRGB8888 is), which means
@@ -429,10 +430,10 @@ brw_render_target_supported(struct brw_context *brw,
    /* Under some conditions, MSAA is not supported for formats whose width is
     * more than 64 bits.
     */
-   if (brw->gen < 8 &&
+   if (devinfo->gen < 8 &&
        rb->NumSamples > 0 && _mesa_get_format_bytes(format) > 8) {
       /* Gen6: MSAA on >64 bit formats is unsupported. */
-      if (brw->gen <= 6)
+      if (devinfo->gen <= 6)
          return false;
 
       /* Gen7: 8x MSAA on >64 bit formats is unsupported. */
@@ -515,13 +516,15 @@ translate_tex_format(struct brw_context *brw,
 uint32_t
 brw_depth_format(struct brw_context *brw, mesa_format format)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    switch (format) {
    case MESA_FORMAT_Z_UNORM16:
       return BRW_DEPTHFORMAT_D16_UNORM;
    case MESA_FORMAT_Z_FLOAT32:
       return BRW_DEPTHFORMAT_D32_FLOAT;
    case MESA_FORMAT_Z24_UNORM_X8_UINT:
-      if (brw->gen >= 6) {
+      if (devinfo->gen >= 6) {
          return BRW_DEPTHFORMAT_D24_UNORM_X8_UINT;
       } else {
          /* Use D24_UNORM_S8, not D24_UNORM_X8.
diff --git a/src/mesa/drivers/dri/i965/brw_tcs.c b/src/mesa/drivers/dri/i965/brw_tcs.c
index 72c5872bcfd..056cd084e37 100644
--- a/src/mesa/drivers/dri/i965/brw_tcs.c
+++ b/src/mesa/drivers/dri/i965/brw_tcs.c
@@ -292,6 +292,7 @@ void
 brw_tcs_populate_key(struct brw_context *brw,
                      struct brw_tcs_prog_key *key)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_program *tcp = (struct brw_program *) brw->tess_ctrl_program;
    struct brw_program *tep = (struct brw_program *) brw->tess_eval_program;
    struct gl_program *tes_prog = &tep->program;
@@ -307,7 +308,7 @@ brw_tcs_populate_key(struct brw_context *brw,
       per_patch_slots |= prog->info.patch_outputs_written;
    }
 
-   if (brw->gen < 8 || !tcp)
+   if (devinfo->gen < 8 || !tcp)
       key->input_vertices = brw->ctx.TessCtrlProgram.patch_vertices;
    key->outputs_written = per_vertex_slots;
    key->patch_outputs_written = per_patch_slots;
@@ -316,7 +317,7 @@ brw_tcs_populate_key(struct brw_context *brw,
     * based on the domain the DS is expecting to tessellate.
     */
    key->tes_primitive_mode = tep->program.info.tess.primitive_mode;
-   key->quads_workaround = brw->gen < 9 &&
+   key->quads_workaround = devinfo->gen < 9 &&
                            tep->program.info.tess.primitive_mode == GL_QUADS &&
                            tep->program.info.tess.spacing == TESS_SPACING_EQUAL;
 
@@ -364,6 +365,7 @@ brw_tcs_precompile(struct gl_context *ctx,
                    struct gl_program *prog)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_tcs_prog_key key;
    uint32_t old_prog_offset = brw->tcs.base.prog_offset;
    struct brw_stage_prog_data *old_prog_data = brw->tcs.base.prog_data;
@@ -379,14 +381,14 @@ brw_tcs_precompile(struct gl_context *ctx,
    brw_setup_tex_for_precompile(brw, &key.tex, prog);
 
    /* Guess that the input and output patches have the same dimensionality. */
-   if (brw->gen < 8)
+   if (devinfo->gen < 8)
       key.input_vertices = prog->info.tess.tcs_vertices_out;
 
    struct brw_program *btep;
    if (tes) {
       btep = brw_program(tes->Program);
       key.tes_primitive_mode = tes->Program->info.tess.primitive_mode;
-      key.quads_workaround = brw->gen < 9 &&
+      key.quads_workaround = devinfo->gen < 9 &&
                              tes->Program->info.tess.primitive_mode == GL_QUADS &&
                              tes->Program->info.tess.spacing == TESS_SPACING_EQUAL;
    } else {
diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c
index d06d6547975..2fb23f6381e 100644
--- a/src/mesa/drivers/dri/i965/brw_tex_layout.c
+++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c
@@ -66,7 +66,9 @@ intel_horizontal_texture_alignment_unit(struct brw_context *brw,
     * "Surface Horizontal Alignment" field to HALIGN_4 or HALIGN_8.
     */
 
-   if (brw->gen >= 7 && mt->format == MESA_FORMAT_Z_UNORM16)
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen >= 7 && mt->format == MESA_FORMAT_Z_UNORM16)
       return 8;
 
    return 4;
@@ -97,7 +99,9 @@ intel_vertical_texture_alignment_unit(struct brw_context *brw,
    /* Broadwell only supports VALIGN of 4, 8, and 16.  The BSpec says 4
     * should always be used, except for stencil buffers, which should be 8.
     */
-   if (brw->gen >= 8)
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen >= 8)
       return 4;
 
    if (mt->num_samples > 1)
@@ -105,13 +109,13 @@ intel_vertical_texture_alignment_unit(struct brw_context *brw,
 
    GLenum base_format = _mesa_get_format_base_format(mt->format);
 
-   if (brw->gen >= 6 &&
+   if (devinfo->gen >= 6 &&
        (base_format == GL_DEPTH_COMPONENT ||
 	base_format == GL_DEPTH_STENCIL)) {
       return 4;
    }
 
-   if (brw->gen == 7) {
+   if (devinfo->gen == 7) {
       /* On Gen7, we prefer a vertical alignment of 4 when possible, because
        * that allows Y tiled render targets.
        *
@@ -301,8 +305,10 @@ brw_miptree_get_horizontal_slice_pitch(const struct brw_context *brw,
                                        const struct intel_mipmap_tree *mt,
                                        unsigned level)
 {
-   if ((brw->gen < 9 && mt->target == GL_TEXTURE_3D) ||
-       (brw->gen == 4 && mt->target == GL_TEXTURE_CUBE_MAP)) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if ((devinfo->gen < 9 && mt->target == GL_TEXTURE_3D) ||
+       (devinfo->gen == 4 && mt->target == GL_TEXTURE_CUBE_MAP)) {
       return ALIGN_NPOT(minify(mt->physical_width0, level), mt->halign);
    } else {
       return 0;
@@ -314,9 +320,11 @@ brw_miptree_get_vertical_slice_pitch(const struct brw_context *brw,
                                      const struct intel_mipmap_tree *mt,
                                      unsigned level)
 {
-   assert(mt->array_layout != GEN6_HIZ_STENCIL || brw->gen == 6);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
-   if (brw->gen >= 9) {
+   assert(mt->array_layout != GEN6_HIZ_STENCIL || devinfo->gen == 6);
+
+   if (devinfo->gen >= 9) {
       /* ALL_SLICES_AT_EACH_LOD isn't supported on Gen8+ but this code will
        * effectively end up with a packed qpitch anyway whenever
        * mt->first_level == mt->last_level.
@@ -344,7 +352,7 @@ brw_miptree_get_vertical_slice_pitch(const struct brw_context *brw,
       return qpitch;
 
    } else if (mt->target == GL_TEXTURE_3D ||
-              (brw->gen == 4 && mt->target == GL_TEXTURE_CUBE_MAP) ||
+              (devinfo->gen == 4 && mt->target == GL_TEXTURE_CUBE_MAP) ||
               mt->array_layout == ALL_SLICES_AT_EACH_LOD) {
       return ALIGN_NPOT(minify(mt->physical_height0, level), mt->valign);
 
@@ -361,7 +369,7 @@ brw_miptree_get_vertical_slice_pitch(const struct brw_context *brw,
       const unsigned h0 = ALIGN_NPOT(mt->physical_height0, mt->valign);
       const unsigned h1 = ALIGN_NPOT(minify(mt->physical_height0, 1), mt->valign);
 
-      return h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->valign;
+      return h0 + h1 + (devinfo->gen >= 7 ? 12 : 11) * mt->valign;
    }
 }
 
@@ -381,11 +389,13 @@ bool
 gen9_use_linear_1d_layout(const struct brw_context *brw,
                           const struct intel_mipmap_tree *mt)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* On Gen9+ the mipmap levels of a 1D surface are all laid out in a
     * horizontal line. This isn't done for depth/stencil buffers however
     * because those will be using a tiled layout
     */
-   if (brw->gen >= 9 &&
+   if (devinfo->gen >= 9 &&
        (mt->target == GL_TEXTURE_1D ||
         mt->target == GL_TEXTURE_1D_ARRAY)) {
       GLenum base_format = _mesa_get_format_base_format(mt->format);
@@ -403,6 +413,7 @@ static void
 brw_miptree_layout_texture_array(struct brw_context *brw,
 				 struct intel_mipmap_tree *mt)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    unsigned height = mt->physical_height0;
    bool layout_1d = gen9_use_linear_1d_layout(brw, mt);
    int physical_qpitch;
@@ -427,7 +438,7 @@ brw_miptree_layout_texture_array(struct brw_context *brw,
       /* Unlike previous generations the qpitch is a multiple of the
        * compressed block size on Gen9 so physical_qpitch matches mt->qpitch.
        */
-      physical_qpitch = (mt->compressed && brw->gen < 9 ? mt->qpitch / 4 :
+      physical_qpitch = (mt->compressed && devinfo->gen < 9 ? mt->qpitch / 4 :
                          mt->qpitch);
    }
 
@@ -561,8 +572,10 @@ brw_miptree_choose_tiling(struct brw_context *brw,
       return I915_TILING_NONE;
    }
 
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* Pre-gen6 doesn't have BLORP to handle Y-tiling, so use X-tiling. */
-   if (brw->gen < 6)
+   if (devinfo->gen < 6)
       return I915_TILING_X;
 
    /* From the Sandybridge PRM, Volume 1, Part 2, page 32:
@@ -571,7 +584,7 @@ brw_miptree_choose_tiling(struct brw_context *brw,
     * 128 bits per pixel translates to 16 bytes per pixel. This is necessary
     * all the way back to 965, but is permitted on Gen7+.
     */
-   if (brw->gen < 7 && mt->cpp >= 16)
+   if (devinfo->gen < 7 && mt->cpp >= 16)
       return I915_TILING_X;
 
    /* From the Ivy Bridge PRM, Vol4 Part1 2.12.2.1 (SURFACE_STATE for most
@@ -586,7 +599,7 @@ brw_miptree_choose_tiling(struct brw_context *brw,
     * to know that ahead of time.  And besides, since we use a vertical
     * alignment of 4 as often as we can, this shouldn't happen very often.
     */
-   if (brw->gen == 7 && mt->valign == 2 &&
+   if (devinfo->gen == 7 && mt->valign == 2 &&
        brw->mesa_format_supports_render[mt->format]) {
       return I915_TILING_X;
    }
@@ -598,9 +611,11 @@ static void
 intel_miptree_set_total_width_height(struct brw_context *brw,
                                      struct intel_mipmap_tree *mt)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    switch (mt->target) {
    case GL_TEXTURE_CUBE_MAP:
-      if (brw->gen == 4) {
+      if (devinfo->gen == 4) {
          /* Gen4 stores cube maps as 3D textures. */
          assert(mt->physical_depth0 == 6);
          brw_miptree_layout_texture_3d(brw, mt);
@@ -611,7 +626,7 @@ intel_miptree_set_total_width_height(struct brw_context *brw,
       break;
 
    case GL_TEXTURE_3D:
-      if (brw->gen >= 9)
+      if (devinfo->gen >= 9)
          brw_miptree_layout_texture_array(brw, mt);
       else
          brw_miptree_layout_texture_3d(brw, mt);
@@ -652,6 +667,8 @@ intel_miptree_set_alignment(struct brw_context *brw,
                             struct intel_mipmap_tree *mt,
                             uint32_t layout_flags)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /**
     * From the "Alignment Unit Size" section of various specs, namely:
     * - Gen3 Spec: "Memory Data Formats" Volume,         Section 1.20.1.4
@@ -693,13 +710,13 @@ intel_miptree_set_alignment(struct brw_context *brw,
        * pick is 4 so we effectively have to align to 4 times the block
        * size
        */
-      if (brw->gen >= 9) {
+      if (devinfo->gen >= 9) {
          mt->halign *= 4;
          mt->valign *= 4;
       }
    } else if (mt->format == MESA_FORMAT_S_UINT8) {
       mt->halign = 8;
-      mt->valign = brw->gen >= 7 ? 8 : 4;
+      mt->valign = devinfo->gen >= 7 ? 8 : 4;
    } else {
       mt->halign =
          intel_horizontal_texture_alignment_unit(brw, mt, layout_flags);
@@ -721,7 +738,9 @@ brw_miptree_layout(struct brw_context *brw,
    /* On Gen9+ the alignment values are expressed in multiples of the block
     * size
     */
-   if (brw->gen >= 9) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen >= 9) {
       unsigned int i, j;
       _mesa_get_format_block_size(mt->format, &i, &j);
       mt->halign /= i;
@@ -733,4 +752,3 @@ brw_miptree_layout(struct brw_context *brw,
 
    return true;
 }
-
diff --git a/src/mesa/drivers/dri/i965/brw_urb.c b/src/mesa/drivers/dri/i965/brw_urb.c
index 18daf5137bd..af68b9706b4 100644
--- a/src/mesa/drivers/dri/i965/brw_urb.c
+++ b/src/mesa/drivers/dri/i965/brw_urb.c
@@ -116,6 +116,8 @@ void
 brw_calculate_urb_fence(struct brw_context *brw, unsigned csize,
                         unsigned vsize, unsigned sfsize)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    if (csize < limits[CS].min_entry_size)
       csize = limits[CS].min_entry_size;
 
@@ -145,7 +147,7 @@ brw_calculate_urb_fence(struct brw_context *brw, unsigned csize,
 
       brw->urb.constrained = 0;
 
-      if (brw->gen == 5) {
+      if (devinfo->gen == 5) {
          brw->urb.nr_vs_entries = 128;
          brw->urb.nr_sf_entries = 48;
          if (check_urb_layout(brw)) {
@@ -155,7 +157,7 @@ brw_calculate_urb_fence(struct brw_context *brw, unsigned csize,
             brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries;
             brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries;
          }
-      } else if (brw->is_g4x) {
+      } else if (devinfo->is_g4x) {
 	 brw->urb.nr_vs_entries = 64;
 	 if (check_urb_layout(brw)) {
 	    goto done;
diff --git a/src/mesa/drivers/dri/i965/brw_vs.c b/src/mesa/drivers/dri/i965/brw_vs.c
index 33f2ac19cbc..9d42af2cfd6 100644
--- a/src/mesa/drivers/dri/i965/brw_vs.c
+++ b/src/mesa/drivers/dri/i965/brw_vs.c
@@ -74,12 +74,13 @@ brw_vs_outputs_written(struct brw_context *brw, struct brw_vs_prog_key *key,
                        GLbitfield64 user_varyings)
 {
    GLbitfield64 outputs_written = user_varyings;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    if (key->copy_edgeflag) {
       outputs_written |= BITFIELD64_BIT(VARYING_SLOT_EDGE);
    }
 
-   if (brw->gen < 6) {
+   if (devinfo->gen < 6) {
       /* Put dummy slots into the VUE for the SF to put the replaced
        * point sprite coords in.  We shouldn't need these dummy slots,
        * which take up precious URB space, but it would mean that the SF
@@ -300,6 +301,7 @@ void
 brw_vs_populate_key(struct brw_context *brw,
                     struct brw_vs_prog_key *key)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    /* BRW_NEW_VERTEX_PROGRAM */
    struct brw_program *vp = (struct brw_program *)brw->vertex_program;
@@ -319,7 +321,7 @@ brw_vs_populate_key(struct brw_context *brw,
          _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1;
    }
 
-   if (brw->gen < 6) {
+   if (devinfo->gen < 6) {
       /* _NEW_POLYGON */
       key->copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL ||
                             ctx->Polygon.BackMode != GL_FILL);
@@ -341,7 +343,7 @@ brw_vs_populate_key(struct brw_context *brw,
    brw_populate_sampler_prog_key_data(ctx, prog, &key->tex);
 
    /* BRW_NEW_VS_ATTRIB_WORKAROUNDS */
-   if (brw->gen < 8 && !brw->is_haswell) {
+   if (devinfo->gen < 8 && !devinfo->is_haswell) {
       memcpy(key->gl_attrib_wa_flags, brw->vb.attrib_wa_flags,
              sizeof(brw->vb.attrib_wa_flags));
    }
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c
index a93f4c50379..4b311bd2ecc 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.c
+++ b/src/mesa/drivers/dri/i965/brw_wm.c
@@ -301,6 +301,7 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx,
                                    struct brw_sampler_prog_key_data *key)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    GLbitfield mask = prog->SamplersUsed;
 
    while (mask) {
@@ -323,10 +324,10 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx,
          /* Haswell handles texture swizzling as surface format overrides
           * (except for GL_ALPHA); all other platforms need MOVs in the shader.
           */
-         if (alpha_depth || (brw->gen < 8 && !brw->is_haswell))
+         if (alpha_depth || (devinfo->gen < 8 && !devinfo->is_haswell))
             key->swizzles[s] = brw_get_texture_swizzle(ctx, t);
 
-         if (brw->gen < 8 &&
+         if (devinfo->gen < 8 &&
              sampler->MinFilter != GL_NEAREST &&
              sampler->MagFilter != GL_NEAREST) {
             if (sampler->WrapS == GL_CLAMP)
@@ -338,7 +339,7 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx,
          }
 
          /* gather4 for RG32* is broken in multiple ways on Gen7. */
-         if (brw->gen == 7 && prog->nir->info.uses_texture_gather) {
+         if (devinfo->gen == 7 && prog->nir->info.uses_texture_gather) {
             switch (img->InternalFormat) {
             case GL_RG32I:
             case GL_RG32UI: {
@@ -352,7 +353,7 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx,
                 * leaving normal texture swizzling to SCS.
                 */
                unsigned src_swizzle =
-                  brw->is_haswell ? t->_Swizzle : key->swizzles[s];
+                  devinfo->is_haswell ? t->_Swizzle : key->swizzles[s];
                for (int i = 0; i < 4; i++) {
                   unsigned src_comp = GET_SWZ(src_swizzle, i);
                   if (src_comp == SWIZZLE_ONE || src_comp == SWIZZLE_W) {
@@ -367,7 +368,7 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx,
                 * request blue.  Haswell can use SCS for this, but Ivybridge
                 * needs a shader workaround.
                 */
-               if (!brw->is_haswell)
+               if (!devinfo->is_haswell)
                   key->gather_channel_quirk_mask |= 1 << s;
                break;
             }
@@ -376,7 +377,7 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx,
          /* Gen6's gather4 is broken for UINT/SINT; we treat them as
           * UNORM/FLOAT instead and fix it in the shader.
           */
-         if (brw->gen == 6 && prog->nir->info.uses_texture_gather) {
+         if (devinfo->gen == 6 && prog->nir->info.uses_texture_gather) {
             key->gen6_gather_wa[s] = gen6_gather_workaround(img->InternalFormat);
          }
 
@@ -390,13 +391,13 @@ brw_populate_sampler_prog_key_data(struct gl_context *ctx,
          /* From gen9 onwards some single sampled buffers can also be
           * compressed. These don't need ld2dms sampling along with mcs fetch.
           */
-         if (brw->gen >= 7 &&
+         if (devinfo->gen >= 7 &&
              intel_tex->mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS &&
              intel_tex->mt->num_samples > 1) {
             key->compressed_multisample_layout_mask |= 1 << s;
 
             if (intel_tex->mt->num_samples >= 16) {
-               assert(brw->gen >= 9);
+               assert(devinfo->gen >= 9);
                key->msaa_16 |= 1 << s;
             }
          }
@@ -445,6 +446,7 @@ brw_wm_state_dirty(const struct brw_context *brw)
 void
 brw_wm_populate_key(struct brw_context *brw, struct brw_wm_prog_key *key)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    /* BRW_NEW_FRAGMENT_PROGRAM */
    const struct brw_program *fp = brw_program_const(brw->fragment_program);
@@ -456,7 +458,7 @@ brw_wm_populate_key(struct brw_context *brw, struct brw_wm_prog_key *key)
 
    /* Build the index for table lookup
     */
-   if (brw->gen < 6) {
+   if (devinfo->gen < 6) {
       /* _NEW_COLOR */
       if (prog->info.fs.uses_discard || ctx->Color.AlphaEnabled) {
          lookup |= BRW_WM_IZ_PS_KILL_ALPHATEST_BIT;
@@ -516,7 +518,7 @@ brw_wm_populate_key(struct brw_context *brw, struct brw_wm_prog_key *key)
    key->high_quality_derivatives =
       ctx->Hint.FragmentShaderDerivative == GL_NICEST;
 
-   if (brw->gen < 6)
+   if (devinfo->gen < 6)
       key->stats_wm = brw->stats_wm;
 
    /* _NEW_LIGHT */
@@ -552,7 +554,7 @@ brw_wm_populate_key(struct brw_context *brw, struct brw_wm_prog_key *key)
    }
 
    /* BRW_NEW_VUE_MAP_GEOM_OUT */
-   if (brw->gen < 6 || _mesa_bitcount_64(prog->info.inputs_read &
+   if (devinfo->gen < 6 || _mesa_bitcount_64(prog->info.inputs_read &
                                          BRW_FS_VARYING_INPUT_MASK) > 16) {
       key->input_slots_valid = brw->vue_map_geom_out.slots_valid;
    }
@@ -563,7 +565,7 @@ brw_wm_populate_key(struct brw_context *brw, struct brw_wm_prog_key *key)
     * like GL requires.  Fix that by building the alpha test into the
     * shader, and we'll skip enabling the fixed function alpha test.
     */
-   if (brw->gen < 6 && ctx->DrawBuffer->_NumColorDrawBuffers > 1 &&
+   if (devinfo->gen < 6 && ctx->DrawBuffer->_NumColorDrawBuffers > 1 &&
        ctx->Color.AlphaEnabled) {
       key->alpha_test_func = ctx->Color.AlphaFunc;
       key->alpha_test_ref = ctx->Color.AlphaRef;
@@ -602,6 +604,7 @@ bool
 brw_fs_precompile(struct gl_context *ctx, struct gl_program *prog)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_wm_prog_key key;
 
    struct brw_program *bfp = brw_program(prog);
@@ -610,7 +613,7 @@ brw_fs_precompile(struct gl_context *ctx, struct gl_program *prog)
 
    uint64_t outputs_written = prog->info.outputs_written;
 
-   if (brw->gen < 6) {
+   if (devinfo->gen < 6) {
       if (prog->info.fs.uses_discard)
          key.iz_lookup |= BRW_WM_IZ_PS_KILL_ALPHATEST_BIT;
 
@@ -622,7 +625,7 @@ brw_fs_precompile(struct gl_context *ctx, struct gl_program *prog)
       key.iz_lookup |= BRW_WM_IZ_DEPTH_WRITE_ENABLE_BIT;
    }
 
-   if (brw->gen < 6 || _mesa_bitcount_64(prog->info.inputs_read &
+   if (devinfo->gen < 6 || _mesa_bitcount_64(prog->info.inputs_read &
                                          BRW_FS_VARYING_INPUT_MASK) > 16) {
       key.input_slots_valid = prog->info.inputs_read | VARYING_BIT_POS;
    }
@@ -643,7 +646,7 @@ brw_fs_precompile(struct gl_context *ctx, struct gl_program *prog)
    struct brw_stage_prog_data *old_prog_data = brw->wm.base.prog_data;
 
    struct brw_vue_map vue_map;
-   if (brw->gen < 6) {
+   if (devinfo->gen < 6) {
       brw_compute_vue_map(&brw->screen->devinfo, &vue_map,
                           prog->info.inputs_read | VARYING_BIT_POS,
                           false);
diff --git a/src/mesa/drivers/dri/i965/brw_wm_state.c b/src/mesa/drivers/dri/i965/brw_wm_state.c
index 69bbeb26d44..c13c3604e04 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_state.c
@@ -151,7 +151,7 @@ brw_upload_wm_unit(struct brw_context *brw)
    /* BRW_NEW_PUSH_CONSTANT_ALLOCATION */
    wm->thread3.const_urb_entry_read_offset = brw->curbe.wm_start * 2;
 
-   if (brw->gen == 5)
+   if (devinfo->gen == 5)
       wm->wm4.sampler_count = 0; /* hardware requirement */
    else {
       wm->wm4.sampler_count = (brw->wm.base.sampler_count + 1) / 4;
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 3615c1805ec..6f73c5644e0 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -81,6 +81,7 @@ brw_emit_surface_state(struct brw_context *brw,
                        uint32_t mocs, uint32_t *surf_offset, int surf_index,
                        unsigned read_domains, unsigned write_domains)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    uint32_t tile_x = mt->level[0].slice[0].x_offset;
    uint32_t tile_y = mt->level[0].slice[0].y_offset;
    uint32_t offset = mt->offset;
@@ -104,7 +105,7 @@ brw_emit_surface_state(struct brw_context *brw,
        * texel of the level instead of relying on the usual base level/layer
        * controls.
        */
-      assert(brw->has_surface_tile_offset);
+      assert(devinfo->has_surface_tile_offset);
       assert(view.levels == 1 && view.array_len == 1);
       assert(tile_x == 0 && tile_y == 0);
 
@@ -200,11 +201,12 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
                                 uint32_t flags, unsigned unit /* unused */,
                                 uint32_t surf_index)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
    struct intel_mipmap_tree *mt = irb->mt;
 
-   if (brw->gen < 9) {
+   if (devinfo->gen < 9) {
       assert(!(flags & INTEL_AUX_BUFFER_DISABLED));
    }
 
@@ -233,7 +235,7 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
 
    uint32_t offset;
    brw_emit_surface_state(brw, mt, flags, mt->target, view,
-                          rb_mocs[brw->gen],
+                          rb_mocs[devinfo->gen],
                           &offset, surf_index,
                           I915_GEM_DOMAIN_RENDER,
                           I915_GEM_DOMAIN_RENDER);
@@ -568,14 +570,15 @@ brw_update_texture_surface(struct gl_context *ctx,
                                                     sampler->sRGBDecode);
 
       /* Implement gen6 and gen7 gather work-around */
+      const struct gen_device_info *devinfo = &brw->screen->devinfo;
       bool need_green_to_blue = false;
       if (for_gather) {
-         if (brw->gen == 7 && (format == ISL_FORMAT_R32G32_FLOAT ||
+         if (devinfo->gen == 7 && (format == ISL_FORMAT_R32G32_FLOAT ||
                                format == ISL_FORMAT_R32G32_SINT ||
                                format == ISL_FORMAT_R32G32_UINT)) {
             format = ISL_FORMAT_R32G32_FLOAT_LD;
-            need_green_to_blue = brw->is_haswell;
-         } else if (brw->gen == 6) {
+            need_green_to_blue = devinfo->is_haswell;
+         } else if (devinfo->gen == 6) {
             /* Sandybridge's gather4 message is broken for integer formats.
              * To work around this, we pretend the surface is UNORM for
              * 8 or 16-bit formats, and emit shader instructions to recover
@@ -606,14 +609,14 @@ brw_update_texture_surface(struct gl_context *ctx,
       }
 
       if (obj->StencilSampling && firstImage->_BaseFormat == GL_DEPTH_STENCIL) {
-         if (brw->gen <= 7) {
+         if (devinfo->gen <= 7) {
             assert(mt->r8stencil_mt && !mt->stencil_mt->r8stencil_needs_update);
             mt = mt->r8stencil_mt;
          } else {
             mt = mt->stencil_mt;
          }
          format = ISL_FORMAT_R8_UINT;
-      } else if (brw->gen <= 7 && mt->format == MESA_FORMAT_S_UINT8) {
+      } else if (devinfo->gen <= 7 && mt->format == MESA_FORMAT_S_UINT8) {
          assert(mt->r8stencil_mt && !mt->r8stencil_needs_update);
          mt = mt->r8stencil_mt;
          format = ISL_FORMAT_R8_UINT;
@@ -645,7 +648,7 @@ brw_update_texture_surface(struct gl_context *ctx,
       const int flags = brw_disable_aux_surface(brw, mt, &view) ?
                            INTEL_AUX_BUFFER_DISABLED : 0;
       brw_emit_surface_state(brw, mt, flags, mt->target, view,
-                             tex_mocs[brw->gen],
+                             tex_mocs[devinfo->gen],
                              surf_offset, surf_index,
                              I915_GEM_DOMAIN_SAMPLER, 0);
    }
@@ -661,6 +664,7 @@ brw_emit_buffer_surface_state(struct brw_context *brw,
                               unsigned pitch,
                               bool rw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    uint32_t *dw = brw_state_batch(brw,
                                   brw->isl_dev.ss.size,
                                   brw->isl_dev.ss.align,
@@ -671,7 +675,7 @@ brw_emit_buffer_surface_state(struct brw_context *brw,
                          .size = buffer_size,
                          .format = surface_format,
                          .stride = pitch,
-                         .mocs = tex_mocs[brw->gen]);
+                         .mocs = tex_mocs[devinfo->gen]);
 
    if (bo) {
       brw_emit_reloc(&brw->batch, *out_offset + brw->isl_dev.ss.addr_offset,
@@ -949,9 +953,11 @@ brw_emit_null_surface_state(struct brw_context *brw,
       multisampling_state = brw_get_surface_num_multisamples(samples);
    }
 
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    surf[0] = (surface_type << BRW_SURFACE_TYPE_SHIFT |
 	      ISL_FORMAT_B8G8R8A8_UNORM << BRW_SURFACE_FORMAT_SHIFT);
-   if (brw->gen < 6) {
+   if (devinfo->gen < 6) {
       surf[0] |= (1 << BRW_SURFACE_WRITEDISABLE_R_SHIFT |
 		  1 << BRW_SURFACE_WRITEDISABLE_G_SHIFT |
 		  1 << BRW_SURFACE_WRITEDISABLE_B_SHIFT |
@@ -988,6 +994,7 @@ gen4_update_renderbuffer_surface(struct brw_context *brw,
                                  uint32_t flags, unsigned unit,
                                  uint32_t surf_index)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
    struct intel_mipmap_tree *mt = irb->mt;
@@ -1002,7 +1009,7 @@ gen4_update_renderbuffer_surface(struct brw_context *brw,
    assert(!(flags & INTEL_RENDERBUFFER_LAYERED));
    assert(!(flags & INTEL_AUX_BUFFER_DISABLED));
 
-   if (rb->TexImage && !brw->has_surface_tile_offset) {
+   if (rb->TexImage && !devinfo->has_surface_tile_offset) {
       intel_renderbuffer_get_tile_offsets(irb, &tile_x, &tile_y);
 
       if (tile_x != 0 || tile_y != 0) {
@@ -1042,7 +1049,7 @@ gen4_update_renderbuffer_surface(struct brw_context *brw,
 
    surf[4] = brw_get_surface_num_multisamples(mt->num_samples);
 
-   assert(brw->has_surface_tile_offset || (tile_x == 0 && tile_y == 0));
+   assert(devinfo->has_surface_tile_offset || (tile_x == 0 && tile_y == 0));
    /* Note that the low bits of these fields are missing, so
     * there's the possibility of getting in trouble.
     */
@@ -1052,7 +1059,7 @@ gen4_update_renderbuffer_surface(struct brw_context *brw,
 	      (tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT |
 	      (mt->valign == 4 ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0));
 
-   if (brw->gen < 6) {
+   if (devinfo->gen < 6) {
       /* _NEW_COLOR */
       if (!ctx->Color.ColorLogicOpEnabled && !ctx->Color._AdvancedBlendMode &&
           (ctx->Color.BlendEnabled & (1 << unit)))
@@ -1160,6 +1167,7 @@ const struct brw_tracked_state gen6_renderbuffer_surfaces = {
 static void
 update_renderbuffer_read_surfaces(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    const struct gl_context *ctx = &brw->ctx;
 
    /* BRW_NEW_FS_PROG_DATA */
@@ -1223,7 +1231,7 @@ update_renderbuffer_read_surfaces(struct brw_context *brw)
             const int flags = brw->draw_aux_buffer_disabled[i] ?
                                  INTEL_AUX_BUFFER_DISABLED : 0;
             brw_emit_surface_state(brw, irb->mt, flags, target, view,
-                                   tex_mocs[brw->gen],
+                                   tex_mocs[devinfo->gen],
                                    surf_offset, surf_index,
                                    I915_GEM_DOMAIN_SAMPLER, 0);
 
@@ -1289,6 +1297,8 @@ update_stage_texture_surfaces(struct brw_context *brw,
 static void
 brw_update_texture_surfaces(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* BRW_NEW_VERTEX_PROGRAM */
    struct gl_program *vs = (struct gl_program *) brw->vertex_program;
 
@@ -1312,7 +1322,7 @@ brw_update_texture_surfaces(struct brw_context *brw)
    /* emit alternate set of surface state for gather. this
     * allows the surface format to be overriden for only the
     * gather4 messages. */
-   if (brw->gen < 8) {
+   if (devinfo->gen < 8) {
       if (vs && vs->nir->info.uses_texture_gather)
          update_stage_texture_surfaces(brw, vs, &brw->vs.base, true, 0);
       if (tcs && tcs->nir->info.uses_texture_gather)
@@ -1355,6 +1365,8 @@ const struct brw_tracked_state brw_texture_surfaces = {
 static void
 brw_update_cs_texture_surfaces(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* BRW_NEW_COMPUTE_PROGRAM */
    struct gl_program *cs = (struct gl_program *) brw->compute_program;
 
@@ -1365,7 +1377,7 @@ brw_update_cs_texture_surfaces(struct brw_context *brw)
     * allows the surface format to be overriden for only the
     * gather4 messages.
     */
-   if (brw->gen < 8) {
+   if (devinfo->gen < 8) {
       if (cs && cs->nir->info.uses_texture_gather)
          update_stage_texture_surfaces(brw, cs, &brw->cs.base, true, 0);
    }
@@ -1760,12 +1772,13 @@ update_image_surface(struct brw_context *brw,
             };
 
             const int surf_index = surf_offset - &brw->wm.base.surf_offset[0];
+            const struct gen_device_info *devinfo = &brw->screen->devinfo;
             assert(!intel_miptree_has_color_unresolved(mt,
                                                        view.base_level, 1,
                                                        view.base_array_layer,
                                                        view.array_len));
             brw_emit_surface_state(brw, mt, INTEL_AUX_BUFFER_DISABLED,
-                                   mt->target, view, tex_mocs[brw->gen],
+                                   mt->target, view, tex_mocs[devinfo->gen],
                                    surf_offset, surf_index,
                                    I915_GEM_DOMAIN_SAMPLER,
                                    access == GL_READ_ONLY ? 0 :
diff --git a/src/mesa/drivers/dri/i965/gen6_constant_state.c b/src/mesa/drivers/dri/i965/gen6_constant_state.c
index f3927c5dba2..9521199549a 100644
--- a/src/mesa/drivers/dri/i965/gen6_constant_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_constant_state.c
@@ -63,8 +63,9 @@ gen6_upload_push_constants(struct brw_context *brw,
 
       int i;
       const int size = prog_data->nr_params * sizeof(gl_constant_value);
+      const struct gen_device_info *devinfo = &brw->screen->devinfo;
       gl_constant_value *param;
-      if (brw->gen >= 8 || brw->is_haswell) {
+      if (devinfo->gen >= 8 || devinfo->is_haswell) {
          param = intel_upload_space(brw, size, 32, &brw->curbe.curbe_bo,
                                     &stage_state->push_const_offset);
       } else {
diff --git a/src/mesa/drivers/dri/i965/gen6_queryobj.c b/src/mesa/drivers/dri/i965/gen6_queryobj.c
index 8e639cfeef4..e7300038cba 100644
--- a/src/mesa/drivers/dri/i965/gen6_queryobj.c
+++ b/src/mesa/drivers/dri/i965/gen6_queryobj.c
@@ -80,9 +80,11 @@ static void
 write_primitives_generated(struct brw_context *brw,
                            struct brw_bo *query_bo, int stream, int idx)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    brw_emit_mi_flush(brw);
 
-   if (brw->gen >= 7 && stream > 0) {
+   if (devinfo->gen >= 7 && stream > 0) {
       brw_store_register_mem64(brw, query_bo,
                                GEN7_SO_PRIM_STORAGE_NEEDED(stream),
                                idx * sizeof(uint64_t));
@@ -96,9 +98,11 @@ static void
 write_xfb_primitives_written(struct brw_context *brw,
                              struct brw_bo *bo, int stream, int idx)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    brw_emit_mi_flush(brw);
 
-   if (brw->gen >= 7) {
+   if (devinfo->gen >= 7) {
       brw_store_register_mem64(brw, bo, GEN7_SO_NUM_PRIMS_WRITTEN(stream),
                                idx * sizeof(uint64_t));
    } else {
@@ -113,6 +117,7 @@ write_xfb_overflow_streams(struct gl_context *ctx,
                            int idx)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    brw_emit_mi_flush(brw);
 
@@ -120,7 +125,7 @@ write_xfb_overflow_streams(struct gl_context *ctx,
       int w_idx = 4 * i + idx;
       int g_idx = 4 * i + idx + 2;
 
-      if (brw->gen >= 7) {
+      if (devinfo->gen >= 7) {
          brw_store_register_mem64(brw, bo,
                                   GEN7_SO_NUM_PRIMS_WRITTEN(stream + i),
                                   g_idx * sizeof(uint64_t));
@@ -192,11 +197,12 @@ emit_pipeline_stat(struct brw_context *brw, struct brw_bo *bo,
       GS_INVOCATION_COUNT /* This one is special... */
    };
    STATIC_ASSERT(ARRAY_SIZE(target_to_register) == MAX_PIPELINE_STATISTICS);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    uint32_t reg = target_to_register[pipeline_target_to_index(target)];
    /* Gen6 GS code counts full primitives, that is, it won't count individual
     * triangles in a triangle strip. Use CL_INVOCATION_COUNT for that.
     */
-   if (brw->gen == 6 && target == GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB)
+   if (devinfo->gen == 6 && target == GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB)
       reg = CL_INVOCATION_COUNT;
    assert(reg != 0);
 
@@ -217,6 +223,7 @@ gen6_queryobj_get_results(struct gl_context *ctx,
                           struct brw_query_object *query)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    if (query->bo == NULL)
       return;
@@ -289,7 +296,7 @@ gen6_queryobj_get_results(struct gl_context *ctx,
        * and correctly emitted the number of pixel shader invocations, but,
        * whomever forgot to undo the multiply by 4.
        */
-      if (brw->gen == 8 || brw->is_haswell)
+      if (devinfo->gen == 8 || devinfo->is_haswell)
          query->Base.Result /= 4;
       break;
 
diff --git a/src/mesa/drivers/dri/i965/gen6_sol.c b/src/mesa/drivers/dri/i965/gen6_sol.c
index b4824b67e5b..d350e77dc99 100644
--- a/src/mesa/drivers/dri/i965/gen6_sol.c
+++ b/src/mesa/drivers/dri/i965/gen6_sol.c
@@ -280,6 +280,7 @@ void
 brw_save_primitives_written_counters(struct brw_context *brw,
                                      struct brw_transform_feedback_object *obj)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    const struct gl_context *ctx = &brw->ctx;
    const int streams = ctx->Const.MaxVertexStreams;
 
@@ -295,7 +296,7 @@ brw_save_primitives_written_counters(struct brw_context *brw,
    brw_emit_mi_flush(brw);
 
    /* Emit MI_STORE_REGISTER_MEM commands to write the values. */
-   if (brw->gen >= 7) {
+   if (devinfo->gen >= 7) {
       for (int i = 0; i < streams; i++) {
          int offset = (obj->prim_count_buffer_index + i) * sizeof(uint64_t);
          brw_store_register_mem64(brw, obj->prim_count_bo,
@@ -384,6 +385,7 @@ brw_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
 			     struct gl_transform_feedback_object *obj)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    const struct gl_program *prog;
    const struct gl_transform_feedback_info *linked_xfb_info;
    struct gl_transform_feedback_object *xfb_obj =
@@ -391,7 +393,7 @@ brw_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
    struct brw_transform_feedback_object *brw_obj =
       (struct brw_transform_feedback_object *) xfb_obj;
 
-   assert(brw->gen == 6);
+   assert(devinfo->gen == 6);
 
    if (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]) {
       /* BRW_NEW_GEOMETRY_PROGRAM */
diff --git a/src/mesa/drivers/dri/i965/gen7_l3_state.c b/src/mesa/drivers/dri/i965/gen7_l3_state.c
index 536c00c4543..39fbb973e72 100644
--- a/src/mesa/drivers/dri/i965/gen7_l3_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_l3_state.c
@@ -69,6 +69,7 @@ get_pipeline_state_l3_weights(const struct brw_context *brw)
 static void
 setup_l3_config(struct brw_context *brw, const struct gen_l3_config *cfg)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    const bool has_dc = cfg->n[GEN_L3P_DC] || cfg->n[GEN_L3P_ALL];
    const bool has_is = cfg->n[GEN_L3P_IS] || cfg->n[GEN_L3P_RO] ||
                        cfg->n[GEN_L3P_ALL];
@@ -116,7 +117,7 @@ setup_l3_config(struct brw_context *brw, const struct gen_l3_config *cfg)
                                PIPE_CONTROL_NO_WRITE |
                                PIPE_CONTROL_CS_STALL);
 
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       assert(!cfg->n[GEN_L3P_IS] && !cfg->n[GEN_L3P_C] && !cfg->n[GEN_L3P_T]);
 
       BEGIN_BATCH(3);
@@ -140,11 +141,11 @@ setup_l3_config(struct brw_context *brw, const struct gen_l3_config *cfg)
        * client (URB for all validated configurations) set to the
        * lower-bandwidth 2-bank address hashing mode.
        */
-      const bool urb_low_bw = has_slm && !brw->is_baytrail;
+      const bool urb_low_bw = has_slm && !devinfo->is_baytrail;
       assert(!urb_low_bw || cfg->n[GEN_L3P_URB] == cfg->n[GEN_L3P_SLM]);
 
       /* Minimum number of ways that can be allocated to the URB. */
-      const unsigned n0_urb = (brw->is_baytrail ? 32 : 0);
+      const unsigned n0_urb = (devinfo->is_baytrail ? 32 : 0);
       assert(cfg->n[GEN_L3P_URB] >= n0_urb);
 
       BEGIN_BATCH(7);
@@ -152,8 +153,8 @@ setup_l3_config(struct brw_context *brw, const struct gen_l3_config *cfg)
 
       /* Demote any clients with no ways assigned to LLC. */
       OUT_BATCH(GEN7_L3SQCREG1);
-      OUT_BATCH((brw->is_haswell ? HSW_L3SQCREG1_SQGHPCI_DEFAULT :
-                 brw->is_baytrail ? VLV_L3SQCREG1_SQGHPCI_DEFAULT :
+      OUT_BATCH((devinfo->is_haswell ? HSW_L3SQCREG1_SQGHPCI_DEFAULT :
+                 devinfo->is_baytrail ? VLV_L3SQCREG1_SQGHPCI_DEFAULT :
                  IVB_L3SQCREG1_SQGHPCI_DEFAULT) |
                 (has_dc ? 0 : GEN7_L3SQCREG1_CONV_DC_UC) |
                 (has_is ? 0 : GEN7_L3SQCREG1_CONV_IS_UC) |
diff --git a/src/mesa/drivers/dri/i965/gen7_misc_state.c b/src/mesa/drivers/dri/i965/gen7_misc_state.c
index 6c69fa8ba59..9b6af405bc9 100644
--- a/src/mesa/drivers/dri/i965/gen7_misc_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_misc_state.c
@@ -166,7 +166,8 @@ gen7_emit_depth_stencil_hiz(struct brw_context *brw,
       ADVANCE_BATCH();
    } else {
       stencil_mt->r8stencil_needs_update = true;
-      const int enabled = brw->is_haswell ? HSW_STENCIL_ENABLED : 0;
+      const struct gen_device_info *devinfo = &brw->screen->devinfo;
+      const int enabled = devinfo->is_haswell ? HSW_STENCIL_ENABLED : 0;
 
       BEGIN_BATCH(3);
       OUT_BATCH(GEN7_3DSTATE_STENCIL_BUFFER << 16 | (3 - 2));
diff --git a/src/mesa/drivers/dri/i965/gen7_sol_state.c b/src/mesa/drivers/dri/i965/gen7_sol_state.c
index f54b370cd40..c48005224b7 100644
--- a/src/mesa/drivers/dri/i965/gen7_sol_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_sol_state.c
@@ -40,10 +40,11 @@ gen7_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
                               struct gl_transform_feedback_object *obj)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_transform_feedback_object *brw_obj =
       (struct brw_transform_feedback_object *) obj;
 
-   assert(brw->gen == 7);
+   assert(devinfo->gen == 7);
 
    /* We're about to lose the information needed to compute the number of
     * vertices written during the last Begin/EndTransformFeedback section,
@@ -107,13 +108,14 @@ gen7_pause_transform_feedback(struct gl_context *ctx,
                               struct gl_transform_feedback_object *obj)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_transform_feedback_object *brw_obj =
       (struct brw_transform_feedback_object *) obj;
 
    /* Flush any drawing so that the counters have the right values. */
    brw_emit_mi_flush(brw);
 
-   assert(brw->gen == 7);
+   assert(devinfo->gen == 7);
 
    /* Save the SOL buffer offset register values. */
    for (int i = 0; i < 4; i++) {
@@ -139,10 +141,11 @@ gen7_resume_transform_feedback(struct gl_context *ctx,
                                struct gl_transform_feedback_object *obj)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_transform_feedback_object *brw_obj =
       (struct brw_transform_feedback_object *) obj;
 
-   assert(brw->gen == 7);
+   assert(devinfo->gen == 7);
 
    /* Reload the SOL buffer offset registers. */
    for (int i = 0; i < 4; i++) {
diff --git a/src/mesa/drivers/dri/i965/gen7_urb.c b/src/mesa/drivers/dri/i965/gen7_urb.c
index 525c9c4d3da..d29c62505bf 100644
--- a/src/mesa/drivers/dri/i965/gen7_urb.c
+++ b/src/mesa/drivers/dri/i965/gen7_urb.c
@@ -62,6 +62,8 @@
 static void
 gen7_allocate_push_constants(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* BRW_NEW_GEOMETRY_PROGRAM */
    bool gs_present = brw->geometry_program;
 
@@ -70,7 +72,7 @@ gen7_allocate_push_constants(struct brw_context *brw)
 
    unsigned avail_size = 16;
    unsigned multiplier =
-      (brw->gen >= 8 || (brw->is_haswell && brw->gt == 3)) ? 2 : 1;
+      (devinfo->gen >= 8 || (devinfo->is_haswell && devinfo->gt == 3)) ? 2 : 1;
 
    int stages = 2 + gs_present + 2 * tess_present;
 
@@ -139,7 +141,8 @@ gen7_emit_push_constant_state(struct brw_context *brw, unsigned vs_size,
     *
     * No such restriction exists for Haswell or Baytrail.
     */
-   if (brw->gen < 8 && !brw->is_haswell && !brw->is_baytrail)
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   if (devinfo->gen < 8 && !devinfo->is_haswell && !devinfo->is_baytrail)
       gen7_emit_cs_stall_flush(brw);
 }
 
@@ -174,7 +177,7 @@ gen7_upload_urb(struct brw_context *brw, unsigned vs_size,
 {
    const struct gen_device_info *devinfo = &brw->screen->devinfo;
    const int push_size_kB =
-      (brw->gen >= 8 || (brw->is_haswell && brw->gt == 3)) ? 32 : 16;
+      (devinfo->gen >= 8 || (devinfo->is_haswell && devinfo->gt == 3)) ? 32 : 16;
 
    /* BRW_NEW_{VS,TCS,TES,GS}_PROG_DATA */
    struct brw_vue_prog_data *prog_data[4] = {
@@ -219,12 +222,12 @@ gen7_upload_urb(struct brw_context *brw, unsigned vs_size,
    gen_get_urb_config(devinfo, 1024 * push_size_kB, 1024 * brw->urb.size,
                       tess_present, gs_present, entry_size, entries, start);
 
-   if (brw->gen == 7 && !brw->is_haswell && !brw->is_baytrail)
+   if (devinfo->gen == 7 && !devinfo->is_haswell && !devinfo->is_baytrail)
       gen7_emit_vs_workaround_flush(brw);
 
    BEGIN_BATCH(8);
    for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) {
-      assert(brw->gen != 10 || entry_size[i] % 3);
+      assert(devinfo->gen != 10 || entry_size[i] % 3);
       OUT_BATCH((_3DSTATE_URB_VS + i) << 16 | (2 - 2));
       OUT_BATCH(entries[i] |
                 ((entry_size[i] - 1) << GEN7_URB_ENTRY_SIZE_SHIFT) |
diff --git a/src/mesa/drivers/dri/i965/gen8_depth_state.c b/src/mesa/drivers/dri/i965/gen8_depth_state.c
index 52c6dd0787d..b4744d52e28 100644
--- a/src/mesa/drivers/dri/i965/gen8_depth_state.c
+++ b/src/mesa/drivers/dri/i965/gen8_depth_state.c
@@ -49,7 +49,8 @@ emit_depth_packets(struct brw_context *brw,
                    uint32_t lod,
                    uint32_t min_array_element)
 {
-   uint32_t mocs_wb = brw->gen >= 9 ? SKL_MOCS_WB : BDW_MOCS_WB;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   uint32_t mocs_wb = devinfo->gen >= 9 ? SKL_MOCS_WB : BDW_MOCS_WB;
 
    /* Skip repeated NULL depth/stencil emits (think 2D rendering). */
    if (!depth_mt && !stencil_mt && brw->no_depth_or_stencil) {
@@ -154,6 +155,7 @@ gen8_emit_depth_stencil_hiz(struct brw_context *brw,
                             uint32_t width, uint32_t height,
                             uint32_t tile_x, uint32_t tile_y)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_context *ctx = &brw->ctx;
    struct gl_framebuffer *fb = ctx->DrawBuffer;
    uint32_t surftype;
@@ -194,7 +196,7 @@ gen8_emit_depth_stencil_hiz(struct brw_context *brw,
       break;
    case GL_TEXTURE_1D_ARRAY:
    case GL_TEXTURE_1D:
-      if (brw->gen >= 9) {
+      if (devinfo->gen >= 9) {
          /* WaDisable1DDepthStencil. Skylake+ doesn't support 1D depth
           * textures but it does allow pretending it's a 2D texture
           * instead.
@@ -365,9 +367,10 @@ gen8_write_pma_stall_bits(struct brw_context *brw, uint32_t pma_stall_bits)
 static void
 gen8_emit_pma_stall_workaround(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    uint32_t bits = 0;
 
-   if (brw->gen >= 9)
+   if (devinfo->gen >= 9)
       return;
 
    if (pma_fix_enable(brw))
diff --git a/src/mesa/drivers/dri/i965/genX_state_upload.c b/src/mesa/drivers/dri/i965/genX_state_upload.c
index 3f8a7265db9..99482d2d634 100644
--- a/src/mesa/drivers/dri/i965/genX_state_upload.c
+++ b/src/mesa/drivers/dri/i965/genX_state_upload.c
@@ -468,6 +468,7 @@ upload_format_size(uint32_t upload_format)
 static void
 genX(emit_vertices)(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    uint32_t *dw;
 
    brw_prepare_vertices(brw);
@@ -600,7 +601,7 @@ genX(emit_vertices)(struct brw_context *brw)
           * vertex element may poke over the end of the buffer by 2 bytes.
           */
          const unsigned padding =
-            (GEN_GEN <= 7 && !brw->is_baytrail && !brw->is_haswell) * 2;
+            (GEN_GEN <= 7 && !devinfo->is_baytrail && !devinfo->is_haswell) * 2;
          const unsigned end = buffer->offset + buffer->size + padding;
          dw = genX(emit_vertex_buffer_state)(brw, dw, i, buffer->bo,
                                              buffer->offset,
@@ -1513,7 +1514,8 @@ genX(upload_sf)(struct brw_context *brw)
 
       /* _NEW_LINE */
 #if GEN_GEN == 8
-      if (brw->is_cherryview)
+      const struct gen_device_info *devinfo = &brw->screen->devinfo;
+      if (devinfo->is_cherryview)
          sf.CHVLineWidth = brw_get_line_width(brw);
       else
          sf.LineWidth = brw_get_line_width(brw);
@@ -2363,7 +2365,7 @@ genX(upload_gs_state)(struct brw_context *brw)
     * whole fixed function pipeline" means to emit a PIPE_CONTROL with the "CS
     * Stall" bit set.
     */
-   if (brw->gt == 2 && brw->gs.enabled != active)
+   if (devinfo->gt == 2 && brw->gs.enabled != active)
       gen7_emit_cs_stall_flush(brw);
 #endif
 
@@ -2782,7 +2784,8 @@ genX(upload_vs_push_constants)(struct brw_context *brw)
    gen6_upload_push_constants(brw, &vp->program, prog_data, stage_state);
 
 #if GEN_GEN >= 7
-   if (GEN_GEN == 7 && !GEN_IS_HASWELL && !brw->is_baytrail)
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   if (GEN_GEN == 7 && !GEN_IS_HASWELL && !devinfo->is_baytrail)
       gen7_emit_vs_workaround_flush(brw);
 
    upload_constant_state(brw, stage_state, true /* active */,
@@ -4269,6 +4272,7 @@ genX(upload_default_color)(struct brw_context *brw,
                            bool is_integer_format, bool is_stencil_sampling,
                            uint32_t *sdc_offset)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    union gl_color_union color;
 
    switch (base_format) {
@@ -4322,9 +4326,9 @@ genX(upload_default_color)(struct brw_context *brw,
       color.ui[3] = float_as_int(1.0);
 
    int alignment = 32;
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       alignment = 64;
-   } else if (brw->is_haswell && (is_integer_format || is_stencil_sampling)) {
+   } else if (devinfo->is_haswell && (is_integer_format || is_stencil_sampling)) {
       alignment = 512;
    }
 
diff --git a/src/mesa/drivers/dri/i965/hsw_queryobj.c b/src/mesa/drivers/dri/i965/hsw_queryobj.c
index b81ab3b6f88..43b88ee011f 100644
--- a/src/mesa/drivers/dri/i965/hsw_queryobj.c
+++ b/src/mesa/drivers/dri/i965/hsw_queryobj.c
@@ -293,6 +293,7 @@ hsw_result_to_gpr0(struct gl_context *ctx, struct brw_query_object *query,
                    GLenum pname, GLenum ptype)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    assert(query->bo);
    assert(pname != GL_QUERY_TARGET);
@@ -366,7 +367,7 @@ hsw_result_to_gpr0(struct gl_context *ctx, struct brw_query_object *query,
        * and correctly emitted the number of pixel shader invocations, but,
        * whomever forgot to undo the multiply by 4.
        */
-      if (brw->gen == 8 || brw->is_haswell)
+      if (devinfo->gen == 8 || devinfo->is_haswell)
          shr_gpr0_by_2_bits(brw);
       break;
    case GL_TIME_ELAPSED:
@@ -439,9 +440,10 @@ store_query_result_reg(struct brw_context *brw, struct brw_bo *bo,
                        uint32_t offset, GLenum ptype, uint32_t reg,
                        const bool pipelined)
 {
-   uint32_t cmd_size = brw->gen >= 8 ? 4 : 3;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   uint32_t cmd_size = devinfo->gen >= 8 ? 4 : 3;
    uint32_t dwords = (ptype == GL_INT || ptype == GL_UNSIGNED_INT) ? 1 : 2;
-   assert(brw->gen >= 6);
+   assert(devinfo->gen >= 6);
 
    BEGIN_BATCH(dwords * cmd_size);
    for (int i = 0; i < dwords; i++) {
@@ -449,7 +451,7 @@ store_query_result_reg(struct brw_context *brw, struct brw_bo *bo,
                 (pipelined ? MI_STORE_REGISTER_MEM_PREDICATE : 0) |
                 (cmd_size - 2));
       OUT_BATCH(reg + 4 * i);
-      if (brw->gen >= 8) {
+      if (devinfo->gen >= 8) {
          OUT_RELOC64(bo, I915_GEM_DOMAIN_INSTRUCTION,
                      I915_GEM_DOMAIN_INSTRUCTION, offset + 4 * i);
       } else {
diff --git a/src/mesa/drivers/dri/i965/hsw_sol.c b/src/mesa/drivers/dri/i965/hsw_sol.c
index b0dd150b7df..05817a80347 100644
--- a/src/mesa/drivers/dri/i965/hsw_sol.c
+++ b/src/mesa/drivers/dri/i965/hsw_sol.c
@@ -163,13 +163,14 @@ hsw_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
                               struct gl_transform_feedback_object *obj)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_transform_feedback_object *brw_obj =
       (struct brw_transform_feedback_object *) obj;
 
    brw_obj->primitive_mode = mode;
 
    /* Reset the SO buffer offsets to 0. */
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       brw_obj->zero_offsets = true;
    } else {
       BEGIN_BATCH(1 + 2 * BRW_MAX_XFB_STREAMS);
@@ -197,10 +198,11 @@ hsw_pause_transform_feedback(struct gl_context *ctx,
                               struct gl_transform_feedback_object *obj)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_transform_feedback_object *brw_obj =
       (struct brw_transform_feedback_object *) obj;
 
-   if (brw->is_haswell) {
+   if (devinfo->is_haswell) {
       /* Flush any drawing so that the counters have the right values. */
       brw_emit_mi_flush(brw);
 
@@ -228,10 +230,11 @@ hsw_resume_transform_feedback(struct gl_context *ctx,
                                struct gl_transform_feedback_object *obj)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct brw_transform_feedback_object *brw_obj =
       (struct brw_transform_feedback_object *) obj;
 
-   if (brw->is_haswell) {
+   if (devinfo->is_haswell) {
       /* Reload the SOL buffer offset registers. */
       for (int i = 0; i < BRW_MAX_XFB_STREAMS; i++) {
          BEGIN_BATCH(3);
diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.c b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
index 62d2fe8ef35..d9400370a9a 100644
--- a/src/mesa/drivers/dri/i965/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
@@ -121,7 +121,8 @@ intel_batchbuffer_reset(struct intel_batchbuffer *batch,
 static void
 intel_batchbuffer_reset_and_clear_render_cache(struct brw_context *brw)
 {
-   intel_batchbuffer_reset(&brw->batch, brw->bufmgr, brw->has_llc);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   intel_batchbuffer_reset(&brw->batch, brw->bufmgr, devinfo->has_llc);
    brw_render_cache_set_clear(brw);
 }
 
@@ -174,9 +175,11 @@ void
 intel_batchbuffer_require_space(struct brw_context *brw, GLuint sz,
                                 enum brw_gpu_ring ring)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* If we're switching rings, implicitly flush the batch. */
    if (unlikely(ring != brw->batch.ring) && brw->batch.ring != UNKNOWN_RING &&
-       brw->gen >= 6) {
+       devinfo->gen >= 6) {
       intel_batchbuffer_flush(brw);
    }
 
@@ -233,6 +236,7 @@ decode_structs(struct brw_context *brw, struct gen_spec *spec,
 static void
 do_batch_dump(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct intel_batchbuffer *batch = &brw->batch;
    struct gen_spec *spec = gen_spec_load(&brw->screen->devinfo);
 
@@ -350,10 +354,10 @@ do_batch_dump(struct brw_context *brw)
                         gtt_offset, p[1] & ~0x3fu, 8 * 4, color);
          break;
       case _3DSTATE_CC_STATE_POINTERS:
-         if (brw->gen >= 7) {
+         if (devinfo->gen >= 7) {
             decode_struct(brw, spec, "COLOR_CALC_STATE", data,
                           gtt_offset, p[1] & ~0x3fu, color);
-         } else if (brw->gen == 6) {
+         } else if (devinfo->gen == 6) {
             decode_structs(brw, spec, "BLEND_STATE", data,
                            gtt_offset, p[1] & ~0x3fu, 2 * 4, color);
             decode_struct(brw, spec, "DEPTH_STENCIL_STATE", data,
@@ -431,6 +435,8 @@ brw_new_batch(struct brw_context *brw)
 static void
 brw_finish_batch(struct brw_context *brw)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* Capture the closing pipeline statistics register values necessary to
     * support query objects (in the non-hardware context world).
     */
@@ -441,10 +447,10 @@ brw_finish_batch(struct brw_context *brw)
        * assume that the L3 cache is configured according to the hardware
        * defaults.
        */
-      if (brw->gen >= 7)
+      if (devinfo->gen >= 7)
          gen7_restore_default_l3_config(brw);
 
-      if (brw->is_haswell) {
+      if (devinfo->is_haswell) {
          /* From the Haswell PRM, Volume 2b, Command Reference: Instructions,
           * 3DSTATE_CC_STATE_POINTERS > "Note":
           *
@@ -615,11 +621,12 @@ execbuffer(int fd,
 static int
 do_flush_locked(struct brw_context *brw, int in_fence_fd, int *out_fence_fd)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    __DRIscreen *dri_screen = brw->screen->driScrnPriv;
    struct intel_batchbuffer *batch = &brw->batch;
    int ret = 0;
 
-   if (brw->has_llc) {
+   if (devinfo->has_llc) {
       brw_bo_unmap(batch->bo);
    } else {
       ret = brw_bo_subdata(batch->bo, 0, 4 * USED_BATCH(*batch), batch->map);
@@ -632,9 +639,10 @@ do_flush_locked(struct brw_context *brw, int in_fence_fd, int *out_fence_fd)
    }
 
    if (!brw->screen->no_hw) {
+      const struct gen_device_info *devinfo = &brw->screen->devinfo;
       int flags;
 
-      if (brw->gen >= 6 && batch->ring == BLT_RING) {
+      if (devinfo->gen >= 6 && batch->ring == BLT_RING) {
          flags = I915_EXEC_BLT;
       } else {
          flags = I915_EXEC_RENDER;
@@ -811,12 +819,13 @@ load_sized_register_mem(struct brw_context *brw,
                         uint32_t offset,
                         int size)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    int i;
 
    /* MI_LOAD_REGISTER_MEM only exists on Gen7+. */
-   assert(brw->gen >= 7);
+   assert(devinfo->gen >= 7);
 
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       BEGIN_BATCH(4 * size);
       for (i = 0; i < size; i++) {
          OUT_BATCH(GEN7_MI_LOAD_REGISTER_MEM | (4 - 2));
@@ -862,9 +871,10 @@ void
 brw_store_register_mem32(struct brw_context *brw,
                          struct brw_bo *bo, uint32_t reg, uint32_t offset)
 {
-   assert(brw->gen >= 6);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(devinfo->gen >= 6);
 
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       BEGIN_BATCH(4);
       OUT_BATCH(MI_STORE_REGISTER_MEM | (4 - 2));
       OUT_BATCH(reg);
@@ -888,12 +898,13 @@ void
 brw_store_register_mem64(struct brw_context *brw,
                          struct brw_bo *bo, uint32_t reg, uint32_t offset)
 {
-   assert(brw->gen >= 6);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(devinfo->gen >= 6);
 
    /* MI_STORE_REGISTER_MEM only stores a single 32-bit value, so to
     * read a full 64-bit register, we need to do two of them.
     */
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       BEGIN_BATCH(8);
       OUT_BATCH(MI_STORE_REGISTER_MEM | (4 - 2));
       OUT_BATCH(reg);
@@ -924,7 +935,8 @@ brw_store_register_mem64(struct brw_context *brw,
 void
 brw_load_register_imm32(struct brw_context *brw, uint32_t reg, uint32_t imm)
 {
-   assert(brw->gen >= 6);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(devinfo->gen >= 6);
 
    BEGIN_BATCH(3);
    OUT_BATCH(MI_LOAD_REGISTER_IMM | (3 - 2));
@@ -939,7 +951,8 @@ brw_load_register_imm32(struct brw_context *brw, uint32_t reg, uint32_t imm)
 void
 brw_load_register_imm64(struct brw_context *brw, uint32_t reg, uint64_t imm)
 {
-   assert(brw->gen >= 6);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(devinfo->gen >= 6);
 
    BEGIN_BATCH(5);
    OUT_BATCH(MI_LOAD_REGISTER_IMM | (5 - 2));
@@ -956,7 +969,8 @@ brw_load_register_imm64(struct brw_context *brw, uint32_t reg, uint64_t imm)
 void
 brw_load_register_reg(struct brw_context *brw, uint32_t src, uint32_t dest)
 {
-   assert(brw->gen >= 8 || brw->is_haswell);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(devinfo->gen >= 8 || devinfo->is_haswell);
 
    BEGIN_BATCH(3);
    OUT_BATCH(MI_LOAD_REGISTER_REG | (3 - 2));
@@ -971,7 +985,8 @@ brw_load_register_reg(struct brw_context *brw, uint32_t src, uint32_t dest)
 void
 brw_load_register_reg64(struct brw_context *brw, uint32_t src, uint32_t dest)
 {
-   assert(brw->gen >= 8 || brw->is_haswell);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(devinfo->gen >= 8 || devinfo->is_haswell);
 
    BEGIN_BATCH(6);
    OUT_BATCH(MI_LOAD_REGISTER_REG | (3 - 2));
@@ -990,11 +1005,12 @@ void
 brw_store_data_imm32(struct brw_context *brw, struct brw_bo *bo,
                      uint32_t offset, uint32_t imm)
 {
-   assert(brw->gen >= 6);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(devinfo->gen >= 6);
 
    BEGIN_BATCH(4);
    OUT_BATCH(MI_STORE_DATA_IMM | (4 - 2));
-   if (brw->gen >= 8)
+   if (devinfo->gen >= 8)
       OUT_RELOC64(bo, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
                   offset);
    else {
@@ -1013,11 +1029,12 @@ void
 brw_store_data_imm64(struct brw_context *brw, struct brw_bo *bo,
                      uint32_t offset, uint64_t imm)
 {
-   assert(brw->gen >= 6);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(devinfo->gen >= 6);
 
    BEGIN_BATCH(5);
    OUT_BATCH(MI_STORE_DATA_IMM | (5 - 2));
-   if (brw->gen >= 8)
+   if (devinfo->gen >= 8)
       OUT_RELOC64(bo, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
                   offset);
    else {
diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.h b/src/mesa/drivers/dri/i965/intel_batchbuffer.h
index 2783ba3c0fb..a711e1e0c5d 100644
--- a/src/mesa/drivers/dri/i965/intel_batchbuffer.h
+++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.h
@@ -78,7 +78,9 @@ static inline uint32_t
 brw_program_reloc(struct brw_context *brw, uint32_t state_offset,
 		  uint32_t prog_offset)
 {
-   if (brw->gen >= 5) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->gen >= 5) {
       /* Using state base address. */
       return prog_offset;
    }
diff --git a/src/mesa/drivers/dri/i965/intel_blit.c b/src/mesa/drivers/dri/i965/intel_blit.c
index e79e02a0752..7030080f0e1 100644
--- a/src/mesa/drivers/dri/i965/intel_blit.c
+++ b/src/mesa/drivers/dri/i965/intel_blit.c
@@ -101,7 +101,8 @@ set_blitter_tiling(struct brw_context *brw,
                    bool dst_y_tiled, bool src_y_tiled,
                    uint32_t *__map)
 {
-   assert(brw->gen >= 6);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(devinfo->gen >= 6);
 
    /* Idle the blitter before we update how tiling is interpreted. */
    OUT_BATCH(MI_FLUSH_DW);
@@ -442,7 +443,8 @@ alignment_valid(struct brw_context *brw, unsigned offset, uint32_t tiling)
       return (offset & 4095) == 0;
 
    /* On Gen8+, linear buffers must be cacheline-aligned. */
-   if (brw->gen >= 8)
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   if (devinfo->gen >= 8)
       return (offset & 63) == 0;
 
    return true;
@@ -493,6 +495,7 @@ intelEmitCopyBlit(struct brw_context *brw,
 		  GLshort w, GLshort h,
 		  GLenum logic_op)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    GLuint CMD, BR13;
    int dst_y2 = dst_y + h;
    int dst_x2 = dst_x + w;
@@ -501,7 +504,7 @@ intelEmitCopyBlit(struct brw_context *brw,
    uint32_t src_tile_w, src_tile_h;
    uint32_t dst_tile_w, dst_tile_h;
 
-   if ((dst_y_tiled || src_y_tiled) && brw->gen < 6)
+   if ((dst_y_tiled || src_y_tiled) && devinfo->gen < 6)
       return false;
 
    const unsigned bo_sizes = dst_buffer->size + src_buffer->size;
@@ -513,7 +516,7 @@ intelEmitCopyBlit(struct brw_context *brw,
    if (!brw_batch_has_aperture_space(brw, bo_sizes))
       return false;
 
-   unsigned length = brw->gen >= 8 ? 10 : 8;
+   unsigned length = devinfo->gen >= 8 ? 10 : 8;
 
    intel_batchbuffer_require_space(brw, length * 4, BLT_RING);
    DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n",
@@ -586,7 +589,7 @@ intelEmitCopyBlit(struct brw_context *brw,
    OUT_BATCH(BR13 | (uint16_t)dst_pitch);
    OUT_BATCH(SET_FIELD(dst_y, BLT_Y) | SET_FIELD(dst_x, BLT_X));
    OUT_BATCH(SET_FIELD(dst_y2, BLT_Y) | SET_FIELD(dst_x2, BLT_X));
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       OUT_RELOC64(dst_buffer,
                   I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                   dst_offset);
@@ -597,7 +600,7 @@ intelEmitCopyBlit(struct brw_context *brw,
    }
    OUT_BATCH(SET_FIELD(src_y, BLT_Y) | SET_FIELD(src_x, BLT_X));
    OUT_BATCH((uint16_t)src_pitch);
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       OUT_RELOC64(src_buffer,
                   I915_GEM_DOMAIN_RENDER, 0,
                   src_offset);
@@ -627,6 +630,7 @@ intelEmitImmediateColorExpandBlit(struct brw_context *brw,
 				  GLshort w, GLshort h,
 				  GLenum logic_op)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    int dwords = ALIGN(src_size, 8) / 4;
    uint32_t opcode, br13, blit_cmd;
 
@@ -647,7 +651,7 @@ intelEmitImmediateColorExpandBlit(struct brw_context *brw,
        __func__,
        dst_buffer, dst_pitch, dst_offset, x, y, w, h, src_size, dwords);
 
-   unsigned xy_setup_blt_length = brw->gen >= 8 ? 10 : 8;
+   unsigned xy_setup_blt_length = devinfo->gen >= 8 ? 10 : 8;
    intel_batchbuffer_require_space(brw, (xy_setup_blt_length * 4) +
                                         (3 * 4) + dwords * 4, BLT_RING);
 
@@ -671,7 +675,7 @@ intelEmitImmediateColorExpandBlit(struct brw_context *brw,
    OUT_BATCH(br13);
    OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */
    OUT_BATCH((100 << 16) | 100); /* clip x2, y2 */
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       OUT_RELOC64(dst_buffer,
                   I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                   dst_offset);
@@ -683,7 +687,7 @@ intelEmitImmediateColorExpandBlit(struct brw_context *brw,
    OUT_BATCH(0); /* bg */
    OUT_BATCH(fg_color); /* fg */
    OUT_BATCH(0); /* pattern base addr */
-   if (brw->gen >= 8)
+   if (devinfo->gen >= 8)
       OUT_BATCH(0);
 
    OUT_BATCH(blit_cmd | ((3 - 2) + dwords));
@@ -765,6 +769,7 @@ intel_miptree_set_alpha_to_one(struct brw_context *brw,
                               struct intel_mipmap_tree *mt,
                               int x, int y, int width, int height)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    uint32_t BR13, CMD;
    int pitch, cpp;
 
@@ -788,7 +793,7 @@ intel_miptree_set_alpha_to_one(struct brw_context *brw,
    if (!brw_batch_has_aperture_space(brw, mt->bo->size))
       intel_batchbuffer_flush(brw);
 
-   unsigned length = brw->gen >= 8 ? 7 : 6;
+   unsigned length = devinfo->gen >= 8 ? 7 : 6;
    bool dst_y_tiled = mt->tiling == I915_TILING_Y;
 
    /* We need to split the blit into chunks that each fit within the blitter's
@@ -816,7 +821,7 @@ intel_miptree_set_alpha_to_one(struct brw_context *brw,
                    SET_FIELD(x + chunk_x, BLT_X));
          OUT_BATCH(SET_FIELD(y + chunk_y + chunk_h, BLT_Y) |
                    SET_FIELD(x + chunk_x + chunk_w, BLT_X));
-         if (brw->gen >= 8) {
+         if (devinfo->gen >= 8) {
             OUT_RELOC64(mt->bo,
                         I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                         offset);
diff --git a/src/mesa/drivers/dri/i965/intel_copy_image.c b/src/mesa/drivers/dri/i965/intel_copy_image.c
index 2ebd8d7528b..39ba7a9af59 100644
--- a/src/mesa/drivers/dri/i965/intel_copy_image.c
+++ b/src/mesa/drivers/dri/i965/intel_copy_image.c
@@ -42,7 +42,8 @@ copy_miptrees(struct brw_context *brw,
               int dst_x, int dst_y, int dst_z, unsigned dst_level,
               int src_width, int src_height)
 {
-   if (brw->gen <= 5) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   if (devinfo->gen <= 5) {
       /* On gen4-5, try BLT first.
        *
        * Gen4-5 have a single ring for both 3D and BLT operations, so there's
diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c
index 7921b12c16a..9a94d4df203 100644
--- a/src/mesa/drivers/dri/i965/intel_extensions.c
+++ b/src/mesa/drivers/dri/i965/intel_extensions.c
@@ -37,8 +37,9 @@ void
 intelInitExtensions(struct gl_context *ctx)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
-   assert(brw->gen >= 4);
+   assert(devinfo->gen >= 4);
 
    ctx->Extensions.ARB_arrays_of_arrays = true;
    ctx->Extensions.ARB_buffer_storage = true;
@@ -133,13 +134,13 @@ intelInitExtensions(struct gl_context *ctx)
    ctx->Extensions.OES_texture_half_float = true;
    ctx->Extensions.OES_texture_half_float_linear = true;
 
-   if (brw->gen >= 8)
+   if (devinfo->gen >= 8)
       ctx->Const.GLSLVersion = 450;
-   else if (brw->is_haswell && can_do_pipelined_register_writes(brw->screen))
+   else if (devinfo->is_haswell && can_do_pipelined_register_writes(brw->screen))
       ctx->Const.GLSLVersion = 450;
-   else if (brw->gen >= 7 && can_do_pipelined_register_writes(brw->screen))
+   else if (devinfo->gen >= 7 && can_do_pipelined_register_writes(brw->screen))
       ctx->Const.GLSLVersion = 420;
-   else if (brw->gen >= 6)
+   else if (devinfo->gen >= 6)
       ctx->Const.GLSLVersion = 330;
    else
       ctx->Const.GLSLVersion = 120;
@@ -148,21 +149,21 @@ intelInitExtensions(struct gl_context *ctx)
    ctx->Extensions.EXT_shader_integer_mix = ctx->Const.GLSLVersion >= 130;
    ctx->Extensions.MESA_shader_integer_functions = ctx->Const.GLSLVersion >= 130;
 
-   if (brw->is_g4x || brw->gen >= 5) {
+   if (devinfo->is_g4x || devinfo->gen >= 5) {
       ctx->Extensions.MESA_shader_framebuffer_fetch_non_coherent = true;
       ctx->Extensions.KHR_blend_equation_advanced = true;
    }
 
-   if (brw->gen >= 5) {
+   if (devinfo->gen >= 5) {
       ctx->Extensions.ARB_texture_query_levels = ctx->Const.GLSLVersion >= 130;
       ctx->Extensions.ARB_texture_query_lod = true;
       ctx->Extensions.EXT_timer_query = true;
    }
 
-   if (brw->gen == 6)
+   if (devinfo->gen == 6)
       ctx->Extensions.ARB_transform_feedback2 = true;
 
-   if (brw->gen >= 6) {
+   if (devinfo->gen >= 6) {
       ctx->Extensions.ARB_blend_func_extended =
          !driQueryOptionb(&brw->optionCache, "disable_blend_func_extended");
       ctx->Extensions.ARB_conditional_render_inverted = true;
@@ -204,7 +205,7 @@ intelInitExtensions(struct gl_context *ctx)
 
    brw->predicate.supported = false;
 
-   if (brw->gen >= 7) {
+   if (devinfo->gen >= 7) {
       ctx->Extensions.ARB_conservative_depth = true;
       ctx->Extensions.ARB_derivative_control = true;
       ctx->Extensions.ARB_framebuffer_no_attachments = true;
@@ -236,7 +237,7 @@ intelInitExtensions(struct gl_context *ctx)
              ctx->Const.MaxComputeWorkGroupSize[0] >= 1024) {
             ctx->Extensions.ARB_compute_shader = true;
             ctx->Extensions.ARB_ES3_1_compatibility =
-               brw->gen >= 8 || brw->is_haswell;
+               devinfo->gen >= 8 || devinfo->is_haswell;
          }
 
          if (can_do_predicate_writes(brw->screen))
@@ -244,7 +245,7 @@ intelInitExtensions(struct gl_context *ctx)
       }
    }
 
-   if (brw->gen >= 8 || brw->is_haswell) {
+   if (devinfo->gen >= 8 || devinfo->is_haswell) {
       ctx->Extensions.ARB_stencil_texturing = true;
       ctx->Extensions.ARB_texture_stencil8 = true;
       ctx->Extensions.OES_geometry_shader = true;
@@ -252,7 +253,7 @@ intelInitExtensions(struct gl_context *ctx)
       ctx->Extensions.OES_viewport_array = true;
    }
 
-   if (brw->gen >= 8 || brw->is_haswell || brw->is_baytrail) {
+   if (devinfo->gen >= 8 || devinfo->is_haswell || devinfo->is_baytrail) {
       ctx->Extensions.ARB_robust_buffer_access_behavior = true;
    }
 
@@ -260,7 +261,7 @@ intelInitExtensions(struct gl_context *ctx)
       ctx->Extensions.ARB_query_buffer_object = true;
    }
 
-   if (brw->gen >= 8 || brw->is_baytrail) {
+   if (devinfo->gen >= 8 || devinfo->is_baytrail) {
       /* For now, we only enable OES_copy_image on platforms that support
        * ETC2 natively in hardware.  We would need more hacks to support it
        * elsewhere.
@@ -268,12 +269,12 @@ intelInitExtensions(struct gl_context *ctx)
       ctx->Extensions.OES_copy_image = true;
    }
 
-   if (brw->gen >= 8) {
+   if (devinfo->gen >= 8) {
       ctx->Extensions.ARB_gpu_shader_int64 = true;
       ctx->Extensions.ARB_ES3_2_compatibility = true;
    }
 
-   if (brw->gen >= 9) {
+   if (devinfo->gen >= 9) {
       ctx->Extensions.ANDROID_extension_pack_es31a = true;
       ctx->Extensions.ARB_shader_stencil_export = true;
       ctx->Extensions.KHR_blend_equation_advanced_coherent = true;
@@ -284,10 +285,10 @@ intelInitExtensions(struct gl_context *ctx)
       ctx->Extensions.ARB_post_depth_coverage = true;
    }
 
-   if (brw->is_broxton)
+   if (gen_device_info_is_9lp(devinfo))
       ctx->Extensions.KHR_texture_compression_astc_hdr = true;
 
-   if (brw->gen >= 6)
+   if (devinfo->gen >= 6)
       ctx->Extensions.INTEL_performance_query = true;
 
    if (ctx->API == API_OPENGL_CORE)
diff --git a/src/mesa/drivers/dri/i965/intel_fbo.c b/src/mesa/drivers/dri/i965/intel_fbo.c
index f84cea13225..d21f1bef64b 100644
--- a/src/mesa/drivers/dri/i965/intel_fbo.c
+++ b/src/mesa/drivers/dri/i965/intel_fbo.c
@@ -270,7 +270,8 @@ intel_renderbuffer_format(struct gl_context * ctx, GLenum internalFormat)
       if (brw->has_separate_stencil) {
 	 return MESA_FORMAT_S_UINT8;
       } else {
-	 assert(!brw->must_use_separate_stencil);
+         const struct gen_device_info *devinfo = &brw->screen->devinfo;
+	 assert(!devinfo->must_use_separate_stencil);
 	 return MESA_FORMAT_Z24_UNORM_S8_UINT;
       }
    }
@@ -651,6 +652,7 @@ static void
 intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct intel_renderbuffer *depthRb =
       intel_get_renderbuffer(fb, BUFFER_DEPTH);
    struct intel_renderbuffer *stencilRb =
@@ -671,7 +673,7 @@ intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
    }
 
    if (depth_mt && stencil_mt) {
-      if (brw->gen >= 6) {
+      if (devinfo->gen >= 6) {
          unsigned d_width, d_height, d_depth;
          unsigned s_width, s_height, s_depth;
 
@@ -739,7 +741,7 @@ intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
                            "instead of S8\n",
                            _mesa_get_format_name(stencil_mt->format));
 	 }
-	 if (brw->gen < 7 && !intel_renderbuffer_has_hiz(depthRb)) {
+	 if (devinfo->gen < 7 && !intel_renderbuffer_has_hiz(depthRb)) {
 	    /* Before Gen7, separate depth and stencil buffers can be used
 	     * only if HiZ is enabled. From the Sandybridge PRM, Volume 2,
 	     * Part 1, Bit 3DSTATE_DEPTH_BUFFER.SeparateStencilBufferEnable:
@@ -901,6 +903,7 @@ intel_blit_framebuffer(struct gl_context *ctx,
                        GLbitfield mask, GLenum filter)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    /* Page 679 of OpenGL 4.4 spec says:
     *    "Added BlitFramebuffer to commands affected by conditional rendering in
@@ -909,7 +912,7 @@ intel_blit_framebuffer(struct gl_context *ctx,
    if (!_mesa_check_conditional_render(ctx))
       return;
 
-   if (brw->gen < 6) {
+   if (devinfo->gen < 6) {
       /* On gen4-5, try BLT first.
        *
        * Gen4-5 have a single ring for both 3D and BLT operations, so there's
@@ -939,7 +942,7 @@ intel_blit_framebuffer(struct gl_context *ctx,
    if (mask == 0x0)
       return;
 
-   if (brw->gen >= 8 && (mask & GL_STENCIL_BUFFER_BIT)) {
+   if (devinfo->gen >= 8 && (mask & GL_STENCIL_BUFFER_BIT)) {
       assert(!"Invalid blit");
    }
 
@@ -1039,7 +1042,8 @@ brw_render_cache_set_check_flush(struct brw_context *brw, struct brw_bo *bo)
    if (!_mesa_set_search(brw->render_cache, bo))
       return;
 
-   if (brw->gen >= 6) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   if (devinfo->gen >= 6) {
       brw_emit_pipe_control_flush(brw,
                                   PIPE_CONTROL_DEPTH_CACHE_FLUSH |
                                   PIPE_CONTROL_RENDER_TARGET_FLUSH |
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
index 7996ca7cc92..5aa268cfdf5 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
@@ -66,8 +66,10 @@ static enum intel_msaa_layout
 compute_msaa_layout(struct brw_context *brw, mesa_format format,
                     enum intel_aux_disable aux_disable)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* Prior to Gen7, all MSAA surfaces used IMS layout. */
-   if (brw->gen < 7)
+   if (devinfo->gen < 7)
       return INTEL_MSAA_LAYOUT_IMS;
 
    /* In Gen7, IMS layout is only used for depth and stencil buffers. */
@@ -88,7 +90,7 @@ compute_msaa_layout(struct brw_context *brw, mesa_format format,
        * would require converting between CMS and UMS MSAA layouts on the fly,
        * which is expensive.
        */
-      if (brw->gen == 7 && _mesa_get_format_datatype(format) == GL_INT) {
+      if (devinfo->gen == 7 && _mesa_get_format_datatype(format) == GL_INT) {
          return INTEL_MSAA_LAYOUT_UMS;
       } else if (aux_disable & INTEL_AUX_DISABLE_MCS) {
          /* We can't use the CMS layout because it uses an aux buffer, the MCS
@@ -105,6 +107,8 @@ bool
 intel_tiling_supports_non_msrt_mcs(const struct brw_context *brw,
                                    unsigned tiling)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render
     * Target(s)", beneath the "Fast Color Clear" bullet (p326):
     *
@@ -112,9 +116,9 @@ intel_tiling_supports_non_msrt_mcs(const struct brw_context *brw,
     *
     * Gen9 changes the restriction to Y-tile only.
     */
-   if (brw->gen >= 9)
+   if (devinfo->gen >= 9)
       return tiling == I915_TILING_Y;
-   else if (brw->gen >= 7)
+   else if (devinfo->gen >= 7)
       return tiling != I915_TILING_NONE;
    else
       return false;
@@ -145,8 +149,10 @@ bool
 intel_miptree_supports_non_msrt_fast_clear(struct brw_context *brw,
                                            const struct intel_mipmap_tree *mt)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* MCS support does not exist prior to Gen7 */
-   if (brw->gen < 7)
+   if (devinfo->gen < 7)
       return false;
 
    if (mt->aux_disable & INTEL_AUX_DISABLE_MCS)
@@ -198,7 +204,7 @@ intel_miptree_supports_non_msrt_fast_clear(struct brw_context *brw,
     * surfaces are supported with MCS buffer layout with these alignments in
     * the RT space: Horizontal Alignment = 128 and Vertical Alignment = 64.
     */
-   if (brw->gen < 8 && (mip_mapped || arrayed))
+   if (devinfo->gen < 8 && (mip_mapped || arrayed))
       return false;
 
    /* There's no point in using an MCS buffer if the surface isn't in a
@@ -207,7 +213,7 @@ intel_miptree_supports_non_msrt_fast_clear(struct brw_context *brw,
    if (!brw->mesa_format_supports_render[mt->format])
       return false;
 
-   if (brw->gen >= 9) {
+   if (devinfo->gen >= 9) {
       mesa_format linear_format = _mesa_get_srgb_format_linear(mt->format);
       const enum isl_format isl_format =
          brw_isl_format_for_mesa_format(linear_format);
@@ -225,8 +231,10 @@ bool
 intel_miptree_is_lossless_compressed(const struct brw_context *brw,
                                      const struct intel_mipmap_tree *mt)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* Only available from Gen9 onwards. */
-   if (brw->gen < 9)
+   if (devinfo->gen < 9)
       return false;
 
    /* Compression always requires auxiliary buffer. */
@@ -324,6 +332,7 @@ intel_miptree_create_layout(struct brw_context *brw,
                             GLuint num_samples,
                             uint32_t layout_flags)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
    if (!mt)
       return NULL;
@@ -354,7 +363,7 @@ intel_miptree_create_layout(struct brw_context *brw,
    mt->msaa_layout = INTEL_MSAA_LAYOUT_NONE;
    mt->refcount = 1;
 
-   if (brw->gen == 6 && format == MESA_FORMAT_S_UINT8)
+   if (devinfo->gen == 6 && format == MESA_FORMAT_S_UINT8)
       layout_flags |= MIPTREE_LAYOUT_GEN6_HIZ_STENCIL;
 
    int depth_multiply = 1;
@@ -419,7 +428,7 @@ intel_miptree_create_layout(struct brw_context *brw,
           */
          switch (num_samples) {
          case 2:
-            assert(brw->gen >= 8);
+            assert(devinfo->gen >= 8);
             width0 = ALIGN(width0, 2) * 2;
             height0 = ALIGN(height0, 2);
             break;
@@ -464,7 +473,7 @@ intel_miptree_create_layout(struct brw_context *brw,
     * TODO: can we use it elsewhere?
     * TODO: also disable this on Gen8 and pick the qpitch value like Gen9
     */
-   if (brw->gen >= 9) {
+   if (devinfo->gen >= 9) {
       mt->array_layout = ALL_LOD_IN_EACH_SLICE;
    } else {
       switch (mt->msaa_layout) {
@@ -488,11 +497,11 @@ intel_miptree_create_layout(struct brw_context *brw,
 
    if (!(layout_flags & MIPTREE_LAYOUT_FOR_BO) &&
        _mesa_get_format_base_format(format) == GL_DEPTH_STENCIL &&
-       (brw->must_use_separate_stencil ||
+       (devinfo->must_use_separate_stencil ||
 	(brw->has_separate_stencil &&
          intel_miptree_wants_hiz_buffer(brw, mt)))) {
       uint32_t stencil_flags = MIPTREE_LAYOUT_ACCELERATED_UPLOAD;
-      if (brw->gen == 6) {
+      if (devinfo->gen == 6) {
          stencil_flags |= MIPTREE_LAYOUT_TILING_ANY;
       }
 
@@ -540,13 +549,13 @@ intel_miptree_create_layout(struct brw_context *brw,
     *  6   |      ?         |        ?
     */
    if (intel_miptree_supports_non_msrt_fast_clear(brw, mt)) {
-      if (brw->gen >= 9 || (brw->gen == 8 && num_samples <= 1))
+      if (devinfo->gen >= 9 || (devinfo->gen == 8 && num_samples <= 1))
          layout_flags |= MIPTREE_LAYOUT_FORCE_HALIGN16;
-   } else if (brw->gen >= 9 && num_samples > 1) {
+   } else if (devinfo->gen >= 9 && num_samples > 1) {
       layout_flags |= MIPTREE_LAYOUT_FORCE_HALIGN16;
    } else {
       const UNUSED bool is_lossless_compressed_aux =
-         brw->gen >= 9 && num_samples == 1 &&
+         devinfo->gen >= 9 && num_samples == 1 &&
          mt->format == MESA_FORMAT_R_UINT32;
 
       /* For now, nothing else has this requirement */
@@ -576,7 +585,8 @@ intel_lower_compressed_format(struct brw_context *brw, mesa_format format)
    /* No need to lower ETC formats on these platforms,
     * they are supported natively.
     */
-   if (brw->gen >= 8 || brw->is_baytrail)
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   if (devinfo->gen >= 8 || devinfo->is_baytrail)
       return format;
 
    switch (format) {
@@ -704,7 +714,7 @@ make_surface(struct brw_context *brw, GLenum target, mesa_format format,
       .levels = last_level - first_level + 1,
       .array_len = target == GL_TEXTURE_3D ? 1 : depth0,
       .samples = MAX2(num_samples, 1),
-      .usage = isl_usage_flags, 
+      .usage = isl_usage_flags,
       .tiling_flags = 1u << isl_tiling
    };
 
@@ -750,7 +760,8 @@ miptree_create(struct brw_context *brw,
                GLuint num_samples,
                uint32_t layout_flags)
 {
-   if (brw->gen == 6 && format == MESA_FORMAT_S_UINT8)
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   if (devinfo->gen == 6 && format == MESA_FORMAT_S_UINT8)
       return make_surface(brw, target, format, first_level, last_level,
                           width0, height0, depth0, num_samples, ISL_TILING_W,
                           ISL_SURF_USAGE_STENCIL_BIT |
@@ -814,6 +825,7 @@ intel_miptree_create(struct brw_context *brw,
                      GLuint num_samples,
                      uint32_t layout_flags)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct intel_mipmap_tree *mt = miptree_create(
                                      brw, target, format,
                                      first_level, last_level,
@@ -824,7 +836,7 @@ intel_miptree_create(struct brw_context *brw,
     * BLT engine to support it.  Prior to Sandybridge, the BLT paths can't
     * handle Y-tiling, so we need to fall back to X.
     */
-   if (brw->gen < 6 && mt->bo->size >= brw->max_gtt_map_object_size &&
+   if (devinfo->gen < 6 && mt->bo->size >= brw->max_gtt_map_object_size &&
        mt->tiling == I915_TILING_Y) {
       const uint32_t alloc_flags =
          (layout_flags & MIPTREE_LAYOUT_ACCELERATED_UPLOAD) ?
@@ -864,7 +876,7 @@ intel_miptree_create(struct brw_context *brw,
    if (intel_tiling_supports_non_msrt_mcs(brw, mt->tiling) &&
        intel_miptree_supports_non_msrt_fast_clear(brw, mt)) {
       mt->aux_disable &= ~INTEL_AUX_DISABLE_CCS;
-      assert(brw->gen < 8 || mt->halign == 16 || num_samples <= 1);
+      assert(devinfo->gen < 8 || mt->halign == 16 || num_samples <= 1);
 
       /* On Gen9+ clients are not currently capable of consuming compressed
        * single-sampled buffers. Disabling compression allows us to skip
@@ -873,7 +885,7 @@ intel_miptree_create(struct brw_context *brw,
       const bool lossless_compression_disabled = INTEL_DEBUG & DEBUG_NO_RBC;
       const bool is_lossless_compressed =
          unlikely(!lossless_compression_disabled) &&
-         brw->gen >= 9 && !mt->is_scanout &&
+         devinfo->gen >= 9 && !mt->is_scanout &&
          intel_miptree_supports_lossless_compressed(brw, mt);
 
       if (is_lossless_compressed) {
@@ -895,11 +907,12 @@ intel_miptree_create_for_bo(struct brw_context *brw,
                             int pitch,
                             uint32_t layout_flags)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct intel_mipmap_tree *mt;
    uint32_t tiling, swizzle;
    const GLenum target = depth > 1 ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D;
 
-   if (brw->gen == 6 && format == MESA_FORMAT_S_UINT8) {
+   if (devinfo->gen == 6 && format == MESA_FORMAT_S_UINT8) {
       mt = make_surface(brw, target, MESA_FORMAT_S_UINT8,
                         0, 0, width, height, depth, 1, ISL_TILING_W,
                         ISL_SURF_USAGE_STENCIL_BIT |
@@ -1667,7 +1680,8 @@ intel_miptree_alloc_mcs(struct brw_context *brw,
                         struct intel_mipmap_tree *mt,
                         GLuint num_samples)
 {
-   assert(brw->gen >= 7); /* MCS only used on Gen7+ */
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(devinfo->gen >= 7); /* MCS only used on Gen7+ */
    assert(mt->mcs_buf == NULL);
    assert((mt->aux_disable & INTEL_AUX_DISABLE_MCS) == 0);
 
@@ -1748,7 +1762,7 @@ intel_miptree_alloc_non_msrt_mcs(struct brw_context *brw,
       free(aux_state);
       return false;
    }
-  
+
    mt->aux_state = aux_state;
 
    /* From Gen9 onwards single-sampled (non-msrt) auxiliary buffers are
@@ -1784,7 +1798,8 @@ intel_miptree_level_enable_hiz(struct brw_context *brw,
 {
    assert(mt->hiz_buf);
 
-   if (brw->gen >= 8 || brw->is_haswell) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   if (devinfo->gen >= 8 || devinfo->is_haswell) {
       uint32_t width = minify(mt->physical_width0, level);
       uint32_t height = minify(mt->physical_height0, level);
 
@@ -1809,7 +1824,10 @@ bool
 intel_miptree_wants_hiz_buffer(struct brw_context *brw,
                                struct intel_mipmap_tree *mt)
 {
-   if (!brw->has_hiz)
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (!devinfo->has_hiz_and_separate_stencil ||
+       INTEL_DEBUG & DEBUG_NO_HIZ)
       return false;
 
    if (mt->hiz_buf != NULL)
@@ -1877,7 +1895,8 @@ intel_miptree_sample_with_hiz(struct brw_context *brw,
    /* It's unclear how well supported sampling from the hiz buffer is on GEN8,
     * so keep things conservative for now and never enable it unless we're SKL+.
     */
-   if (brw->gen < 9) {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   if (devinfo->gen < 9) {
       return false;
    }
 
@@ -1957,12 +1976,13 @@ intel_miptree_check_color_resolve(const struct brw_context *brw,
                                   const struct intel_mipmap_tree *mt,
                                   unsigned level, unsigned layer)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
    if ((mt->aux_disable & INTEL_AUX_DISABLE_CCS) || !mt->mcs_buf)
       return;
 
    /* Fast color clear is supported for mipmapped surfaces only on Gen8+. */
-   assert(brw->gen >= 8 ||
+   assert(devinfo->gen >= 8 ||
           (level == 0 && mt->first_level == 0 && mt->last_level == 0));
 
    /* Compression of arrayed msaa surfaces is supported. */
@@ -1970,7 +1990,7 @@ intel_miptree_check_color_resolve(const struct brw_context *brw,
       return;
 
    /* Fast color clear is supported for non-msaa arrays only on Gen8+. */
-   assert(brw->gen >= 8 || (layer == 0 && mt->logical_depth0 == 1));
+   assert(devinfo->gen >= 8 || (layer == 0 && mt->logical_depth0 == 1));
 
    (void)level;
    (void)layer;
@@ -2278,7 +2298,7 @@ miptree_layer_range_length(const struct intel_mipmap_tree *mt, uint32_t level,
       total_num_layers = mt->surf.dim == ISL_SURF_DIM_3D ?
          minify(mt->surf.phys_level0_sa.depth, level) :
          mt->surf.phys_level0_sa.array_len;
-   else 
+   else
       total_num_layers = mt->level[level].depth;
 
    assert(start_layer < total_num_layers);
@@ -2520,13 +2540,15 @@ intel_miptree_prepare_render(struct brw_context *brw,
                              uint32_t start_layer, uint32_t layer_count,
                              bool srgb_enabled)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    /* If FRAMEBUFFER_SRGB is used on Gen9+ then we need to resolve any of
     * the single-sampled color renderbuffers because the CCS buffer isn't
     * supported for SRGB formats. This only matters if FRAMEBUFFER_SRGB is
     * enabled because otherwise the surface state will be programmed with
     * the linear equivalent format anyway.
     */
-   if (brw->gen == 9 && srgb_enabled && mt->num_samples <= 1 &&
+   if (devinfo->gen == 9 && srgb_enabled && mt->num_samples <= 1 &&
        _mesa_get_srgb_format_linear(mt->format) != mt->format) {
 
       /* Lossless compression is not supported for SRGB formats, it
@@ -2545,7 +2567,7 @@ intel_miptree_prepare_render(struct brw_context *brw,
    if (layer_count > 1 &&
        !(mt->aux_disable & INTEL_AUX_DISABLE_CCS) &&
        !intel_miptree_is_lossless_compressed(brw, mt)) {
-      assert(brw->gen >= 8);
+      assert(devinfo->gen >= 8);
 
       intel_miptree_prepare_access(brw, mt, level, 1, start_layer, layer_count,
                                    false, false);
@@ -2761,17 +2783,18 @@ void
 intel_update_r8stencil(struct brw_context *brw,
                        struct intel_mipmap_tree *mt)
 {
-   assert(brw->gen >= 7);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(devinfo->gen >= 7);
    struct intel_mipmap_tree *src =
       mt->format == MESA_FORMAT_S_UINT8 ? mt : mt->stencil_mt;
-   if (!src || brw->gen >= 8 || !src->r8stencil_needs_update)
+   if (!src || devinfo->gen >= 8 || !src->r8stencil_needs_update)
       return;
 
    if (!mt->r8stencil_mt) {
       const uint32_t r8stencil_flags =
          MIPTREE_LAYOUT_ACCELERATED_UPLOAD | MIPTREE_LAYOUT_TILING_Y |
          MIPTREE_LAYOUT_DISABLE_AUX;
-      assert(brw->gen > 6); /* Handle MIPTREE_LAYOUT_GEN6_HIZ_STENCIL */
+      assert(devinfo->gen > 6); /* Handle MIPTREE_LAYOUT_GEN6_HIZ_STENCIL */
       mt->r8stencil_mt = intel_miptree_create(brw,
                                               src->target,
                                               MESA_FORMAT_R_UINT8,
@@ -3377,7 +3400,9 @@ use_intel_mipree_map_blit(struct brw_context *brw,
                           unsigned int level,
                           unsigned int slice)
 {
-   if (brw->has_llc &&
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   if (devinfo->has_llc &&
       /* It's probably not worth swapping to the blit ring because of
        * all the overhead involved.
        */
@@ -3385,9 +3410,9 @@ use_intel_mipree_map_blit(struct brw_context *brw,
        !mt->compressed &&
        (mt->tiling == I915_TILING_X ||
         /* Prior to Sandybridge, the blitter can't handle Y tiling */
-        (brw->gen >= 6 && mt->tiling == I915_TILING_Y) ||
+        (devinfo->gen >= 6 && mt->tiling == I915_TILING_Y) ||
         /* Fast copy blit on skl+ supports all tiling formats. */
-        brw->gen >= 9) &&
+        devinfo->gen >= 9) &&
        can_blit_slice(mt, level, slice))
       return true;
 
@@ -3583,6 +3608,8 @@ intel_miptree_get_isl_surf(struct brw_context *brw,
                            const struct intel_mipmap_tree *mt,
                            struct isl_surf *surf)
 {
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
    surf->dim = get_isl_surf_dim(mt->target);
    surf->dim_layout = get_isl_dim_layout(&brw->screen->devinfo,
                                          mt->tiling, mt->target,
@@ -3618,7 +3645,7 @@ intel_miptree_get_isl_surf(struct brw_context *brw,
 
    surf->format = translate_tex_format(brw, mt->format, false);
 
-   if (brw->gen >= 9) {
+   if (devinfo->gen >= 9) {
       if (surf->dim == ISL_SURF_DIM_1D && surf->tiling == ISL_TILING_LINEAR) {
          /* For gen9 1-D surfaces, intel_mipmap_tree has a bogus alignment. */
          surf->image_alignment_el = isl_extent3d(64, 1, 1);
@@ -3666,7 +3693,7 @@ intel_miptree_get_isl_surf(struct brw_context *brw,
    case ISL_DIM_LAYOUT_GEN4_2D:
    case ISL_DIM_LAYOUT_GEN4_3D:
    case ISL_DIM_LAYOUT_GEN6_STENCIL_HIZ:
-      if (brw->gen >= 9) {
+      if (devinfo->gen >= 9) {
          surf->array_pitch_el_rows = mt->qpitch;
       } else {
          unsigned bw, bh;
@@ -3699,7 +3726,7 @@ intel_miptree_get_isl_surf(struct brw_context *brw,
       break;
    case GL_STENCIL_INDEX:
       surf->usage = ISL_SURF_USAGE_STENCIL_BIT;
-      if (brw->gen >= 8)
+      if (devinfo->gen >= 8)
          surf->usage |= ISL_SURF_USAGE_TEXTURE_BIT;
       break;
    case GL_DEPTH_STENCIL:
@@ -3734,7 +3761,8 @@ intel_miptree_get_aux_isl_usage(const struct brw_context *brw,
    }
 
    if (intel_miptree_is_lossless_compressed(brw, mt)) {
-      assert(brw->gen >= 9);
+      const struct gen_device_info *devinfo = &brw->screen->devinfo;
+      assert(devinfo->gen >= 9);
       return ISL_AUX_USAGE_CCS_E;
    }
 
diff --git a/src/mesa/drivers/dri/i965/intel_pixel_read.c b/src/mesa/drivers/dri/i965/intel_pixel_read.c
index 871559edf9e..9f7c4cf75e2 100644
--- a/src/mesa/drivers/dri/i965/intel_pixel_read.c
+++ b/src/mesa/drivers/dri/i965/intel_pixel_read.c
@@ -72,6 +72,7 @@ intel_readpixels_tiled_memcpy(struct gl_context * ctx,
                               const struct gl_pixelstore_attrib *pack)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
 
    /* This path supports reading from color buffers only */
@@ -91,7 +92,7 @@ intel_readpixels_tiled_memcpy(struct gl_context * ctx,
     * a 2D BGRA, RGBA, L8 or A8 texture. It could be generalized to support
     * more types.
     */
-   if (!brw->has_llc ||
+   if (!devinfo->has_llc ||
        !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
        pixels == NULL ||
        _mesa_is_bufferobj(pack->BufferObj) ||
@@ -141,7 +142,7 @@ intel_readpixels_tiled_memcpy(struct gl_context * ctx,
     * parts of the memory aren't swizzled at all. Userspace just can't handle
     * that.
     */
-   if (brw->gen < 5 && brw->has_swizzling)
+   if (devinfo->gen < 5 && brw->has_swizzling)
       return false;
 
    /* Since we are going to read raw data to the miptree, we need to resolve
diff --git a/src/mesa/drivers/dri/i965/intel_tex.c b/src/mesa/drivers/dri/i965/intel_tex.c
index 1751f109f77..13653c537d5 100644
--- a/src/mesa/drivers/dri/i965/intel_tex.c
+++ b/src/mesa/drivers/dri/i965/intel_tex.c
@@ -364,8 +364,9 @@ static void
 intel_texture_barrier(struct gl_context *ctx)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
 
-   if (brw->gen >= 6) {
+   if (devinfo->gen >= 6) {
       brw_emit_pipe_control_flush(brw,
                                   PIPE_CONTROL_DEPTH_CACHE_FLUSH |
                                   PIPE_CONTROL_RENDER_TARGET_FLUSH |
diff --git a/src/mesa/drivers/dri/i965/intel_tex_image.c b/src/mesa/drivers/dri/i965/intel_tex_image.c
index b1fe8dd584e..b19cb8b9c68 100644
--- a/src/mesa/drivers/dri/i965/intel_tex_image.c
+++ b/src/mesa/drivers/dri/i965/intel_tex_image.c
@@ -36,7 +36,7 @@
  * Choose the original base level dimension when shifted dimensions agree.
  * Otherwise assume real resize is intended and use the new shifted value.
  */
-static unsigned 
+static unsigned
 get_base_dim(unsigned old_base_dim, unsigned new_level_dim, unsigned level)
 {
    const unsigned old_level_dim = old_base_dim >> level;
@@ -295,7 +295,8 @@ create_mt_for_dri_image(struct brw_context *brw,
     * for EGL images from non-tile aligned sufaces in gen4 hw and earlier which has
     * trouble resolving back to destination image due to alignment issues.
     */
-   if (!brw->has_surface_tile_offset &&
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   if (!devinfo->has_surface_tile_offset &&
        (draw_x != 0 || draw_y != 0)) {
       _mesa_error(&brw->ctx, GL_INVALID_OPERATION, __func__);
       intel_miptree_release(&mt);
@@ -480,6 +481,7 @@ intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
                                   const struct gl_pixelstore_attrib *packing)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct intel_texture_image *image = intel_texture_image(texImage);
    int dst_pitch;
 
@@ -498,7 +500,7 @@ intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
     * with _mesa_image_row_stride. However, before removing the restrictions
     * we need tests.
     */
-   if (!brw->has_llc ||
+   if (!devinfo->has_llc ||
        !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
        !(texImage->TexObject->Target == GL_TEXTURE_2D ||
          texImage->TexObject->Target == GL_TEXTURE_RECTANGLE) ||
@@ -543,7 +545,7 @@ intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
     * parts of the memory aren't swizzled at all. Userspace just can't handle
     * that.
     */
-   if (brw->gen < 5 && brw->has_swizzling)
+   if (devinfo->gen < 5 && brw->has_swizzling)
       return false;
 
    int level = texImage->Level + texImage->TexObject->MinLevel;
@@ -718,7 +720,8 @@ intelCompressedTexSubImage(struct gl_context *ctx, GLuint dims,
    bool is_linear_astc = _mesa_is_astc_format(gl_format) &&
                         !_mesa_is_srgb_format(gl_format);
    struct brw_context *brw = (struct brw_context*) ctx;
-   if (brw->gen == 9 && is_linear_astc)
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   if (devinfo->gen == 9 && is_linear_astc)
       flush_astc_denorms(ctx, dims, texImage,
                          xoffset, yoffset, zoffset,
                          width, height, depth);
diff --git a/src/mesa/drivers/dri/i965/intel_tex_subimage.c b/src/mesa/drivers/dri/i965/intel_tex_subimage.c
index da5b3f0d302..f67ef0d23d5 100644
--- a/src/mesa/drivers/dri/i965/intel_tex_subimage.c
+++ b/src/mesa/drivers/dri/i965/intel_tex_subimage.c
@@ -80,6 +80,7 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
                                bool for_glTexImage)
 {
    struct brw_context *brw = brw_context(ctx);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
    struct intel_texture_image *image = intel_texture_image(texImage);
    int src_pitch;
 
@@ -98,7 +99,7 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
     * with _mesa_image_row_stride. However, before removing the restrictions
     * we need tests.
     */
-   if (!brw->has_llc ||
+   if (!devinfo->has_llc ||
        !(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) ||
        !(texImage->TexObject->Target == GL_TEXTURE_2D ||
          texImage->TexObject->Target == GL_TEXTURE_RECTANGLE) ||
@@ -142,7 +143,7 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
     * parts of the memory aren't swizzled at all. Userspace just can't handle
     * that.
     */
-   if (brw->gen < 5 && brw->has_swizzling)
+   if (devinfo->gen < 5 && brw->has_swizzling)
       return false;
 
    int level = texImage->Level + texImage->TexObject->MinLevel;
diff --git a/src/mesa/drivers/dri/i965/intel_tex_validate.c b/src/mesa/drivers/dri/i965/intel_tex_validate.c
index 08cf3bf7dc1..50fd9553a15 100644
--- a/src/mesa/drivers/dri/i965/intel_tex_validate.c
+++ b/src/mesa/drivers/dri/i965/intel_tex_validate.c
@@ -111,7 +111,8 @@ intel_finalize_mipmap_tree(struct brw_context *brw, GLuint unit)
     *
     * FINISHME: Avoid doing this.
     */
-   assert(!tObj->Immutable || brw->gen < 6);
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+   assert(!tObj->Immutable || devinfo->gen < 6);
 
    firstImage = intel_texture_image(tObj->Image[0][tObj->BaseLevel]);
 
-- 
2.11.0



More information about the mesa-dev mailing list