nir: Add a flag to lower_io to force "sample" interpolation
[mesa.git] / src / mesa / drivers / dri / i965 / brw_vs_surface_state.c
index b29e414a54eea6dbebdfec2215b7658ec2a3f567..387a54bdb0b4fc346ca0a0887e7fa0b71377d361 100644 (file)
@@ -1,6 +1,6 @@
 /*
  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
 /*
  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
- Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ Intel funded Tungsten Graphics to
  develop this 3D driver.
 
  Permission is hereby granted, free of charge, to any person obtaining
  develop this 3D driver.
 
  Permission is hereby granted, free of charge, to any person obtaining
  **********************************************************************/
  /*
   * Authors:
  **********************************************************************/
  /*
   * Authors:
-  *   Keith Whitwell <keith@tungstengraphics.com>
+  *   Keith Whitwell <keithw@vmware.com>
   */
 
 #include "main/mtypes.h"
 #include "program/prog_parameter.h"
   */
 
 #include "main/mtypes.h"
 #include "program/prog_parameter.h"
+#include "main/shaderapi.h"
 
 #include "brw_context.h"
 #include "brw_state.h"
 
 #include "brw_context.h"
 #include "brw_state.h"
+#include "intel_buffer_objects.h"
 
 
-/* Creates a new VS constant buffer reflecting the current VS program's
- * constants, if needed by the VS program.
+/**
+ * Creates a temporary BO containing the pull constant data for the shader
+ * stage, and the SURFACE_STATE struct that points at it.
  *
  *
- * Otherwise, constants go through the CURBEs using the brw_constant_buffer
- * state atom.
+ * Pull constants are GLSL uniforms (and other constant data) beyond what we
+ * could fit as push constants, or that have variable-index array access
+ * (which is easiest to support using pull constants, and avoids filling
+ * register space with mostly-unused data).
+ *
+ * Compare this path to brw_curbe.c for gen4/5 push constants, and
+ * gen6_vs_state.c for gen6+ push constants.
  */
  */
-static void
-brw_upload_vs_pull_constants(struct brw_context *brw)
+void
+brw_upload_pull_constants(struct brw_context *brw,
+                          GLbitfield64 brw_new_constbuf,
+                          const struct gl_program *prog,
+                          struct brw_stage_state *stage_state,
+                          const struct brw_stage_prog_data *prog_data)
 {
 {
-   struct gl_context *ctx = &brw->intel.ctx;
-   struct intel_context *intel = &brw->intel;
-   /* BRW_NEW_VERTEX_PROGRAM */
-   struct brw_vertex_program *vp =
-      (struct brw_vertex_program *) brw->vertex_program;
-   const struct gl_program_parameter_list *params = vp->program.Base.Parameters;
-   int i;
+   unsigned i;
+   uint32_t surf_index = prog_data->binding_table.pull_constants_start;
 
 
-   if (vp->program.IsNVProgram)
-      _mesa_load_tracked_matrices(ctx);
+   if (!prog_data->nr_pull_params) {
+      if (stage_state->surf_offset[surf_index]) {
+        stage_state->surf_offset[surf_index] = 0;
+        brw->ctx.NewDriverState |= brw_new_constbuf;
+      }
+      return;
+   }
 
    /* Updates the ParamaterValues[i] pointers for all parameters of the
     * basic type of PROGRAM_STATE_VAR.
     */
 
    /* Updates the ParamaterValues[i] pointers for all parameters of the
     * basic type of PROGRAM_STATE_VAR.
     */
-   _mesa_load_state_parameters(&brw->intel.ctx, vp->program.Base.Parameters);
-
-   /* CACHE_NEW_VS_PROG */
-   if (!brw->vs.prog_data->nr_pull_params) {
-      if (brw->vs.const_bo) {
-        drm_intel_bo_unreference(brw->vs.const_bo);
-        brw->vs.const_bo = NULL;
-        brw->vs.surf_offset[SURF_INDEX_VERT_CONST_BUFFER] = 0;
-        brw->state.dirty.brw |= BRW_NEW_VS_CONSTBUF;
-      }
-      return;
-   }
+   _mesa_load_state_parameters(&brw->ctx, prog->Parameters);
 
 
-   /* _NEW_PROGRAM_CONSTANTS */
-   drm_intel_bo_unreference(brw->vs.const_bo);
-   brw->vs.const_bo = drm_intel_bo_alloc(intel->bufmgr, "vp_const_buffer",
-                                        brw->vs.prog_data->nr_pull_params * 4,
-                                        64);
-
-   drm_intel_gem_bo_map_gtt(brw->vs.const_bo);
-   for (i = 0; i < brw->vs.prog_data->nr_pull_params; i++) {
-      memcpy(brw->vs.const_bo->virtual + i * 4,
-            brw->vs.prog_data->pull_param[i],
-            4);
+   /* BRW_NEW_*_PROG_DATA | _NEW_PROGRAM_CONSTANTS */
+   uint32_t size = prog_data->nr_pull_params * 4;
+   drm_intel_bo *const_bo = NULL;
+   uint32_t const_offset;
+   gl_constant_value *constants = intel_upload_space(brw, size, 64,
+                                                     &const_bo, &const_offset);
+
+   STATIC_ASSERT(sizeof(gl_constant_value) == sizeof(float));
+
+   for (i = 0; i < prog_data->nr_pull_params; i++) {
+      constants[i] = *prog_data->pull_param[i];
    }
 
    if (0) {
    }
 
    if (0) {
-      for (i = 0; i < params->NumParameters; i++) {
-        float *row = (float *)brw->vs.const_bo->virtual + i * 4;
-        printf("vs const surface %3d: %4.3f %4.3f %4.3f %4.3f\n",
-               i, row[0], row[1], row[2], row[3]);
+      for (i = 0; i < ALIGN(prog_data->nr_pull_params, 4) / 4; i++) {
+        const gl_constant_value *row = &constants[i * 4];
+        fprintf(stderr, "const surface %3d: %4.3f %4.3f %4.3f %4.3f\n",
+                 i, row[0].f, row[1].f, row[2].f, row[3].f);
       }
    }
 
       }
    }
 
-   drm_intel_gem_bo_unmap_gtt(brw->vs.const_bo);
+   brw_create_constant_surface(brw, const_bo, const_offset, size,
+                               &stage_state->surf_offset[surf_index]);
+   drm_intel_bo_unreference(const_bo);
+
+   brw->ctx.NewDriverState |= brw_new_constbuf;
+}
 
 
-   const int surf = SURF_INDEX_VERT_CONST_BUFFER;
-   intel->vtbl.create_constant_surface(brw, brw->vs.const_bo,
-                                      params->NumParameters,
-                                      &brw->vs.surf_offset[surf]);
 
 
-   brw->state.dirty.brw |= BRW_NEW_VS_CONSTBUF;
+/* Creates a new VS constant buffer reflecting the current VS program's
+ * constants, if needed by the VS program.
+ *
+ * Otherwise, constants go through the CURBEs using the brw_constant_buffer
+ * state atom.
+ */
+static void
+brw_upload_vs_pull_constants(struct brw_context *brw)
+{
+   struct brw_stage_state *stage_state = &brw->vs.base;
+
+   /* BRW_NEW_VERTEX_PROGRAM */
+   struct brw_vertex_program *vp =
+      (struct brw_vertex_program *) brw->vertex_program;
+
+   /* BRW_NEW_VS_PROG_DATA */
+   const struct brw_stage_prog_data *prog_data = &brw->vs.prog_data->base.base;
+
+   _mesa_shader_write_subroutine_indices(&brw->ctx, MESA_SHADER_VERTEX);
+   /* _NEW_PROGRAM_CONSTANTS */
+   brw_upload_pull_constants(brw, BRW_NEW_VS_CONSTBUF, &vp->program.Base,
+                             stage_state, prog_data);
 }
 
 const struct brw_tracked_state brw_vs_pull_constants = {
    .dirty = {
 }
 
 const struct brw_tracked_state brw_vs_pull_constants = {
    .dirty = {
-      .mesa = (_NEW_PROGRAM_CONSTANTS),
-      .brw = (BRW_NEW_BATCH | BRW_NEW_VERTEX_PROGRAM),
-      .cache = CACHE_NEW_VS_PROG,
+      .mesa = _NEW_PROGRAM_CONSTANTS,
+      .brw = BRW_NEW_BATCH |
+             BRW_NEW_BLORP |
+             BRW_NEW_VERTEX_PROGRAM |
+             BRW_NEW_VS_PROG_DATA,
    },
    .emit = brw_upload_vs_pull_constants,
 };
 
    },
    .emit = brw_upload_vs_pull_constants,
 };
 
-/**
- * Constructs the binding table for the WM surface state, which maps unit
- * numbers to surface state objects.
- */
 static void
 static void
-brw_vs_upload_binding_table(struct brw_context *brw)
+brw_upload_vs_ubo_surfaces(struct brw_context *brw)
 {
 {
-   uint32_t *bind;
-   int i;
+   struct gl_context *ctx = &brw->ctx;
+   /* _NEW_PROGRAM */
+   struct gl_shader_program *prog =
+      ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
 
 
-   /* CACHE_NEW_VS_PROG: Skip making a binding table if we don't use textures or
-    * pull constants.
-    */
-   if (brw->vs.prog_data->num_surfaces == 0) {
-      if (brw->vs.bind_bo_offset != 0) {
-        brw->state.dirty.brw |= BRW_NEW_VS_BINDING_TABLE;
-        brw->vs.bind_bo_offset = 0;
-      }
+   if (!prog)
       return;
       return;
-   }
 
 
-   /* Might want to calculate nr_surfaces first, to avoid taking up so much
-    * space for the binding table.
-    */
-   bind = brw_state_batch(brw, AUB_TRACE_BINDING_TABLE,
-                         sizeof(uint32_t) * BRW_MAX_SURFACES,
-                         32, &brw->vs.bind_bo_offset);
+   /* BRW_NEW_VS_PROG_DATA */
+   brw_upload_ubo_surfaces(brw, prog->_LinkedShaders[MESA_SHADER_VERTEX],
+                           &brw->vs.base, &brw->vs.prog_data->base.base);
+}
+
+const struct brw_tracked_state brw_vs_ubo_surfaces = {
+   .dirty = {
+      .mesa = _NEW_PROGRAM,
+      .brw = BRW_NEW_BATCH |
+             BRW_NEW_BLORP |
+             BRW_NEW_UNIFORM_BUFFER |
+             BRW_NEW_VS_PROG_DATA,
+   },
+   .emit = brw_upload_vs_ubo_surfaces,
+};
 
 
-   /* BRW_NEW_SURFACES and BRW_NEW_VS_CONSTBUF */
-   for (i = 0; i < BRW_MAX_VS_SURFACES; i++) {
-      bind[i] = brw->vs.surf_offset[i];
+static void
+brw_upload_vs_abo_surfaces(struct brw_context *brw)
+{
+   struct gl_context *ctx = &brw->ctx;
+   /* _NEW_PROGRAM */
+   struct gl_shader_program *prog =
+      ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
+
+   if (prog) {
+      /* BRW_NEW_VS_PROG_DATA */
+      brw_upload_abo_surfaces(brw, prog->_LinkedShaders[MESA_SHADER_VERTEX],
+                              &brw->vs.base, &brw->vs.prog_data->base.base);
    }
    }
+}
 
 
-   brw->state.dirty.brw |= BRW_NEW_VS_BINDING_TABLE;
+const struct brw_tracked_state brw_vs_abo_surfaces = {
+   .dirty = {
+      .mesa = _NEW_PROGRAM,
+      .brw = BRW_NEW_ATOMIC_BUFFER |
+             BRW_NEW_BATCH |
+             BRW_NEW_BLORP |
+             BRW_NEW_VS_PROG_DATA,
+   },
+   .emit = brw_upload_vs_abo_surfaces,
+};
+
+static void
+brw_upload_vs_image_surfaces(struct brw_context *brw)
+{
+   struct gl_context *ctx = &brw->ctx;
+   /* BRW_NEW_VERTEX_PROGRAM */
+   struct gl_shader_program *prog =
+      ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX];
+
+   if (prog) {
+      /* BRW_NEW_VS_PROG_DATA, BRW_NEW_IMAGE_UNITS, _NEW_TEXTURE */
+      brw_upload_image_surfaces(brw, prog->_LinkedShaders[MESA_SHADER_VERTEX],
+                                &brw->vs.base, &brw->vs.prog_data->base.base);
+   }
 }
 
 }
 
-const struct brw_tracked_state brw_vs_binding_table = {
+const struct brw_tracked_state brw_vs_image_surfaces = {
    .dirty = {
    .dirty = {
-      .mesa = 0,
-      .brw = (BRW_NEW_BATCH |
-             BRW_NEW_VS_CONSTBUF |
-             BRW_NEW_SURFACES),
-      .cache = CACHE_NEW_VS_PROG
+      .mesa = _NEW_TEXTURE,
+      .brw = BRW_NEW_BATCH |
+             BRW_NEW_BLORP |
+             BRW_NEW_IMAGE_UNITS |
+             BRW_NEW_VERTEX_PROGRAM |
+             BRW_NEW_VS_PROG_DATA,
    },
    },
-   .emit = brw_vs_upload_binding_table,
+   .emit = brw_upload_vs_image_surfaces,
 };
 };