Merge ../mesa into vulkan
[mesa.git] / src / vulkan / anv_compiler.cpp
index c7593e61b4dcfe3d63f60dbb4153dd60fd916d15..759ec7ae4d9d2bc618a29382dbe997701b95d82a 100644 (file)
@@ -35,6 +35,7 @@
 #include <brw_vs.h>
 #include <brw_gs.h>
 #include <brw_cs.h>
+#include "brw_vec4_gs_visitor.h"
 
 #include <mesa/main/shaderobj.h>
 #include <mesa/main/fbobject.h>
@@ -153,6 +154,71 @@ create_params_array(struct anv_pipeline *pipeline,
          (const gl_constant_value *)&null_data->client_data[i * sizeof(float)];
 }
 
+/**
+ * Return a bitfield where bit n is set if barycentric interpolation mode n
+ * (see enum brw_wm_barycentric_interp_mode) is needed by the fragment shader.
+ */
+unsigned
+brw_compute_barycentric_interp_modes(const struct brw_device_info *devinfo,
+                                     bool shade_model_flat,
+                                     bool persample_shading,
+                                     nir_shader *shader)
+{
+   unsigned barycentric_interp_modes = 0;
+
+   nir_foreach_variable(var, &shader->inputs) {
+      enum glsl_interp_qualifier interp_qualifier =
+         (enum glsl_interp_qualifier) var->data.interpolation;
+      bool is_centroid = var->data.centroid && !persample_shading;
+      bool is_sample = var->data.sample || persample_shading;
+      bool is_gl_Color = (var->data.location == VARYING_SLOT_COL0) ||
+                         (var->data.location == VARYING_SLOT_COL1);
+
+      /* Ignore WPOS and FACE, because they don't require interpolation. */
+      if (var->data.location == VARYING_SLOT_POS ||
+          var->data.location == VARYING_SLOT_FACE)
+         continue;
+
+      /* Determine the set (or sets) of barycentric coordinates needed to
+       * interpolate this variable.  Note that when
+       * brw->needs_unlit_centroid_workaround is set, centroid interpolation
+       * uses PIXEL interpolation for unlit pixels and CENTROID interpolation
+       * for lit pixels, so we need both sets of barycentric coordinates.
+       */
+      if (interp_qualifier == INTERP_QUALIFIER_NOPERSPECTIVE) {
+         if (is_centroid) {
+            barycentric_interp_modes |=
+               1 << BRW_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC;
+         } else if (is_sample) {
+            barycentric_interp_modes |=
+               1 << BRW_WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC;
+         }
+         if ((!is_centroid && !is_sample) ||
+             devinfo->needs_unlit_centroid_workaround) {
+            barycentric_interp_modes |=
+               1 << BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC;
+         }
+      } else if (interp_qualifier == INTERP_QUALIFIER_SMOOTH ||
+                 (!(shade_model_flat && is_gl_Color) &&
+                  interp_qualifier == INTERP_QUALIFIER_NONE)) {
+         if (is_centroid) {
+            barycentric_interp_modes |=
+               1 << BRW_WM_PERSPECTIVE_CENTROID_BARYCENTRIC;
+         } else if (is_sample) {
+            barycentric_interp_modes |=
+               1 << BRW_WM_PERSPECTIVE_SAMPLE_BARYCENTRIC;
+         }
+         if ((!is_centroid && !is_sample) ||
+             devinfo->needs_unlit_centroid_workaround) {
+            barycentric_interp_modes |=
+               1 << BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC;
+         }
+      }
+   }
+
+   return barycentric_interp_modes;
+}
+
 static void
 brw_vs_populate_key(struct brw_context *brw,
                     struct brw_vertex_program *vp,
@@ -188,10 +254,6 @@ brw_vs_populate_key(struct brw_context *brw,
             key->point_coord_replace |= (1 << i);
       }
    }
-
-   /* _NEW_TEXTURE */
-   brw_populate_sampler_prog_key_data(ctx, prog, brw->vs.base.sampler_count,
-                                      &key->tex);
 }
 
 static bool
@@ -263,7 +325,7 @@ really_do_vs_prog(struct brw_context *brw,
    /* Emit GEN4 code.
     */
    program = brw_vs_emit(brw, mem_ctx, key, prog_data, &vp->program,
-                         prog, &program_size);
+                         prog, -1, &program_size);
    if (program == NULL) {
       ralloc_free(mem_ctx);
       return false;
@@ -288,7 +350,6 @@ void brw_wm_populate_key(struct brw_context *brw,
                          struct brw_wm_prog_key *key)
 {
    struct gl_context *ctx = &brw->ctx;
-   struct gl_program *prog = (struct gl_program *) brw->fragment_program;
    GLuint lookup = 0;
    GLuint line_aa;
    bool program_uses_dfdy = fp->program.UsesDFdy;
@@ -383,10 +444,6 @@ void brw_wm_populate_key(struct brw_context *brw,
    /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */
    key->clamp_fragment_color = ctx->Color._ClampFragmentColor;
 
-   /* _NEW_TEXTURE */
-   brw_populate_sampler_prog_key_data(ctx, prog, brw->wm.base.sampler_count,
-                                      &key->tex);
-
    /* _NEW_BUFFERS */
    /*
     * Include the draw buffer origin and height so that we can calculate
@@ -522,7 +579,7 @@ really_do_wm_prog(struct brw_context *brw,
    prog_data->binding_table.render_target_start = 0;
 
    program = brw_wm_fs_emit(brw, mem_ctx, key, prog_data,
-                            &fp->program, prog, &program_size);
+                            &fp->program, prog, -1, -1, &program_size);
    if (program == NULL) {
       ralloc_free(mem_ctx);
       return false;
@@ -546,44 +603,260 @@ really_do_wm_prog(struct brw_context *brw,
    return true;
 }
 
-static void
-brw_gs_populate_key(struct brw_context *brw,
-                    struct anv_pipeline *pipeline,
+bool
+anv_codegen_gs_prog(struct brw_context *brw,
+                    struct gl_shader_program *prog,
                     struct brw_geometry_program *gp,
-                    struct brw_gs_prog_key *key)
+                    struct brw_gs_prog_key *key,
+                    struct anv_pipeline *pipeline)
 {
-   struct gl_context *ctx = &brw->ctx;
-   struct brw_stage_state *stage_state = &brw->gs.base;
-   struct gl_program *prog = &gp->program.Base;
+   struct brw_gs_compile c;
 
-   memset(key, 0, sizeof(*key));
+   memset(&c, 0, sizeof(c));
+   c.key = *key;
+   c.gp = gp;
 
-   key->program_string_id = gp->id;
+   c.prog_data.include_primitive_id =
+      (gp->program.Base.InputsRead & VARYING_BIT_PRIMITIVE_ID) != 0;
 
-   /* _NEW_TEXTURE */
-   brw_populate_sampler_prog_key_data(ctx, prog, stage_state->sampler_count,
-                                      &key->tex);
-}
+   c.prog_data.invocations = gp->program.Invocations;
 
-static bool
-really_do_gs_prog(struct brw_context *brw,
-                  struct gl_shader_program *prog,
-                  struct brw_geometry_program *gp,
-                  struct brw_gs_prog_key *key, struct anv_pipeline *pipeline)
-{
-   struct brw_gs_compile_output output;
-
-   /* FIXME: We pass the bind map to the compile in the output struct. Need
-    * something better. */
-   set_binding_table_layout(&output.prog_data.base.base,
+   set_binding_table_layout(&c.prog_data.base.base,
                             pipeline, VK_SHADER_STAGE_GEOMETRY);
 
-   brw_compile_gs_prog(brw, prog, gp, key, &output);
+   /* Allocate the references to the uniforms that will end up in the
+    * prog_data associated with the compiled program, and which will be freed
+    * by the state cache.
+    *
+    * Note: param_count needs to be num_uniform_components * 4, since we add
+    * padding around uniform values below vec4 size, so the worst case is that
+    * every uniform is a float which gets padded to the size of a vec4.
+    */
+   struct gl_shader *gs = prog->_LinkedShaders[MESA_SHADER_GEOMETRY];
+   int param_count = gp->program.Base.nir->num_uniforms * 4;
+
+   c.prog_data.base.base.param =
+      rzalloc_array(NULL, const gl_constant_value *, param_count);
+   c.prog_data.base.base.pull_param =
+      rzalloc_array(NULL, const gl_constant_value *, param_count);
+   c.prog_data.base.base.image_param =
+      rzalloc_array(NULL, struct brw_image_param, gs->NumImages);
+   c.prog_data.base.base.nr_params = param_count;
+   c.prog_data.base.base.nr_image_params = gs->NumImages;
+
+   brw_nir_setup_glsl_uniforms(gp->program.Base.nir, prog, &gp->program.Base,
+                               &c.prog_data.base.base, false);
+
+   if (brw->gen >= 8) {
+      c.prog_data.static_vertex_count = !gp->program.Base.nir ? -1 :
+         nir_gs_count_vertices(gp->program.Base.nir);
+   }
+
+   if (brw->gen >= 7) {
+      if (gp->program.OutputType == GL_POINTS) {
+         /* When the output type is points, the geometry shader may output data
+          * to multiple streams, and EndPrimitive() has no effect.  So we
+          * configure the hardware to interpret the control data as stream ID.
+          */
+         c.prog_data.control_data_format = GEN7_GS_CONTROL_DATA_FORMAT_GSCTL_SID;
+
+         /* We only have to emit control bits if we are using streams */
+         if (prog->Geom.UsesStreams)
+            c.control_data_bits_per_vertex = 2;
+         else
+            c.control_data_bits_per_vertex = 0;
+      } else {
+         /* When the output type is triangle_strip or line_strip, EndPrimitive()
+          * may be used to terminate the current strip and start a new one
+          * (similar to primitive restart), and outputting data to multiple
+          * streams is not supported.  So we configure the hardware to interpret
+          * the control data as EndPrimitive information (a.k.a. "cut bits").
+          */
+         c.prog_data.control_data_format = GEN7_GS_CONTROL_DATA_FORMAT_GSCTL_CUT;
+
+         /* We only need to output control data if the shader actually calls
+          * EndPrimitive().
+          */
+         c.control_data_bits_per_vertex = gp->program.UsesEndPrimitive ? 1 : 0;
+      }
+   } else {
+      /* There are no control data bits in gen6. */
+      c.control_data_bits_per_vertex = 0;
+
+      /* If it is using transform feedback, enable it */
+      if (prog->TransformFeedback.NumVarying)
+         c.prog_data.gen6_xfb_enabled = true;
+      else
+         c.prog_data.gen6_xfb_enabled = false;
+   }
+   c.control_data_header_size_bits =
+      gp->program.VerticesOut * c.control_data_bits_per_vertex;
+
+   /* 1 HWORD = 32 bytes = 256 bits */
+   c.prog_data.control_data_header_size_hwords =
+      ALIGN(c.control_data_header_size_bits, 256) / 256;
+
+   GLbitfield64 outputs_written = gp->program.Base.OutputsWritten;
+
+   brw_compute_vue_map(brw->intelScreen->devinfo,
+                       &c.prog_data.base.vue_map, outputs_written,
+                       prog ? prog->SeparateShader : false);
+
+   /* Compute the output vertex size.
+    *
+    * From the Ivy Bridge PRM, Vol2 Part1 7.2.1.1 STATE_GS - Output Vertex
+    * Size (p168):
+    *
+    *     [0,62] indicating [1,63] 16B units
+    *
+    *     Specifies the size of each vertex stored in the GS output entry
+    *     (following any Control Header data) as a number of 128-bit units
+    *     (minus one).
+    *
+    *     Programming Restrictions: The vertex size must be programmed as a
+    *     multiple of 32B units with the following exception: Rendering is
+    *     disabled (as per SOL stage state) and the vertex size output by the
+    *     GS thread is 16B.
+    *
+    *     If rendering is enabled (as per SOL state) the vertex size must be
+    *     programmed as a multiple of 32B units. In other words, the only time
+    *     software can program a vertex size with an odd number of 16B units
+    *     is when rendering is disabled.
+    *
+    * Note: B=bytes in the above text.
+    *
+    * It doesn't seem worth the extra trouble to optimize the case where the
+    * vertex size is 16B (especially since this would require special-casing
+    * the GEN assembly that writes to the URB).  So we just set the vertex
+    * size to a multiple of 32B (2 vec4's) in all cases.
+    *
+    * The maximum output vertex size is 62*16 = 992 bytes (31 hwords).  We
+    * budget that as follows:
+    *
+    *   512 bytes for varyings (a varying component is 4 bytes and
+    *             gl_MaxGeometryOutputComponents = 128)
+    *    16 bytes overhead for VARYING_SLOT_PSIZ (each varying slot is 16
+    *             bytes)
+    *    16 bytes overhead for gl_Position (we allocate it a slot in the VUE
+    *             even if it's not used)
+    *    32 bytes overhead for gl_ClipDistance (we allocate it 2 VUE slots
+    *             whenever clip planes are enabled, even if the shader doesn't
+    *             write to gl_ClipDistance)
+    *    16 bytes overhead since the VUE size must be a multiple of 32 bytes
+    *             (see below)--this causes up to 1 VUE slot to be wasted
+    *   400 bytes available for varying packing overhead
+    *
+    * Worst-case varying packing overhead is 3/4 of a varying slot (12 bytes)
+    * per interpolation type, so this is plenty.
+    *
+    */
+   unsigned output_vertex_size_bytes = c.prog_data.base.vue_map.num_slots * 16;
+   assert(brw->gen == 6 ||
+          output_vertex_size_bytes <= GEN7_MAX_GS_OUTPUT_VERTEX_SIZE_BYTES);
+   c.prog_data.output_vertex_size_hwords =
+      ALIGN(output_vertex_size_bytes, 32) / 32;
+
+   /* Compute URB entry size.  The maximum allowed URB entry size is 32k.
+    * That divides up as follows:
+    *
+    *     64 bytes for the control data header (cut indices or StreamID bits)
+    *   4096 bytes for varyings (a varying component is 4 bytes and
+    *              gl_MaxGeometryTotalOutputComponents = 1024)
+    *   4096 bytes overhead for VARYING_SLOT_PSIZ (each varying slot is 16
+    *              bytes/vertex and gl_MaxGeometryOutputVertices is 256)
+    *   4096 bytes overhead for gl_Position (we allocate it a slot in the VUE
+    *              even if it's not used)
+    *   8192 bytes overhead for gl_ClipDistance (we allocate it 2 VUE slots
+    *              whenever clip planes are enabled, even if the shader doesn't
+    *              write to gl_ClipDistance)
+    *   4096 bytes overhead since the VUE size must be a multiple of 32
+    *              bytes (see above)--this causes up to 1 VUE slot to be wasted
+    *   8128 bytes available for varying packing overhead
+    *
+    * Worst-case varying packing overhead is 3/4 of a varying slot per
+    * interpolation type, which works out to 3072 bytes, so this would allow
+    * us to accommodate 2 interpolation types without any danger of running
+    * out of URB space.
+    *
+    * In practice, the risk of running out of URB space is very small, since
+    * the above figures are all worst-case, and most of them scale with the
+    * number of output vertices.  So we'll just calculate the amount of space
+    * we need, and if it's too large, fail to compile.
+    *
+    * The above is for gen7+ where we have a single URB entry that will hold
+    * all the output. In gen6, we will have to allocate URB entries for every
+    * vertex we emit, so our URB entries only need to be large enough to hold
+    * a single vertex. Also, gen6 does not have a control data header.
+    */
+   unsigned output_size_bytes;
+   if (brw->gen >= 7) {
+      output_size_bytes =
+         c.prog_data.output_vertex_size_hwords * 32 * gp->program.VerticesOut;
+      output_size_bytes += 32 * c.prog_data.control_data_header_size_hwords;
+   } else {
+      output_size_bytes = c.prog_data.output_vertex_size_hwords * 32;
+   }
+
+   /* Broadwell stores "Vertex Count" as a full 8 DWord (32 byte) URB output,
+    * which comes before the control header.
+    */
+   if (brw->gen >= 8)
+      output_size_bytes += 32;
+
+   assert(output_size_bytes >= 1);
+   int max_output_size_bytes = GEN7_MAX_GS_URB_ENTRY_SIZE_BYTES;
+   if (brw->gen == 6)
+      max_output_size_bytes = GEN6_MAX_GS_URB_ENTRY_SIZE_BYTES;
+   if (output_size_bytes > max_output_size_bytes)
+      return false;
 
-   pipeline->gs_vec4 = upload_kernel(pipeline, output.program, output.program_size);
+
+   /* URB entry sizes are stored as a multiple of 64 bytes in gen7+ and
+    * a multiple of 128 bytes in gen6.
+    */
+   if (brw->gen >= 7)
+      c.prog_data.base.urb_entry_size = ALIGN(output_size_bytes, 64) / 64;
+   else
+      c.prog_data.base.urb_entry_size = ALIGN(output_size_bytes, 128) / 128;
+
+   /* FIXME: Need to pull this from nir shader. */
+   c.prog_data.output_topology = _3DPRIM_TRISTRIP;
+
+   /* The GLSL linker will have already matched up GS inputs and the outputs
+    * of prior stages.  The driver does extend VS outputs in some cases, but
+    * only for legacy OpenGL or Gen4-5 hardware, neither of which offer
+    * geometry shader support.  So we can safely ignore that.
+    *
+    * For SSO pipelines, we use a fixed VUE map layout based on variable
+    * locations, so we can rely on rendezvous-by-location making this work.
+    *
+    * However, we need to ignore VARYING_SLOT_PRIMITIVE_ID, as it's not
+    * written by previous stages and shows up via payload magic.
+    */
+   GLbitfield64 inputs_read =
+      gp->program.Base.InputsRead & ~VARYING_BIT_PRIMITIVE_ID;
+   brw_compute_vue_map(brw->intelScreen->devinfo,
+                       &c.input_vue_map, inputs_read,
+                       prog->SeparateShader);
+
+   /* GS inputs are read from the VUE 256 bits (2 vec4's) at a time, so we
+    * need to program a URB read length of ceiling(num_slots / 2).
+    */
+   c.prog_data.base.urb_read_length = (c.input_vue_map.num_slots + 1) / 2;
+
+   void *mem_ctx = ralloc_context(NULL);
+   unsigned program_size;
+   const unsigned *program =
+      brw_gs_emit(brw, prog, &c, mem_ctx, -1, &program_size);
+   if (program == NULL) {
+      ralloc_free(mem_ctx);
+      return false;
+   }
+
+   pipeline->gs_vec4 = upload_kernel(pipeline, program, program_size);
    pipeline->gs_vertex_count = gp->program.VerticesIn;
 
-   ralloc_free(output.mem_ctx);
+   ralloc_free(mem_ctx);
 
    return true;
 }
@@ -610,7 +883,7 @@ brw_codegen_cs_prog(struct brw_context *brw,
    anv_nir_apply_dynamic_offsets(pipeline, cs->Program->nir, &prog_data->base);
 
    program = brw_cs_emit(brw, mem_ctx, key, prog_data,
-                         &cp->program, prog, &program_size);
+                         &cp->program, prog, -1, &program_size);
    if (program == NULL) {
       ralloc_free(mem_ctx);
       return false;
@@ -690,7 +963,7 @@ anv_compiler_create(struct anv_device *device)
    compiler->brw->intelScreen = compiler->screen;
    compiler->screen->devinfo = &device->info;
 
-   brw_process_intel_debug_variable(compiler->screen);
+   brw_process_intel_debug_variable();
 
    compiler->screen->compiler = brw_compiler_create(compiler, &device->info);
 
@@ -1011,7 +1284,7 @@ anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline)
    brw->use_rep_send = pipeline->use_repclear;
    brw->no_simd8 = pipeline->use_repclear;
 
-   program = brw->ctx.Driver.NewShaderProgram(name);
+   program = _mesa_new_shader_program(name);
    program->Shaders = (struct gl_shader **)
       calloc(VK_SHADER_STAGE_NUM, sizeof(struct gl_shader *));
    fail_if(program == NULL || program->Shaders == NULL,
@@ -1059,9 +1332,7 @@ anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline)
          program->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program;
       struct brw_geometry_program *bgp = brw_geometry_program(gp);
 
-      brw_gs_populate_key(brw, pipeline, bgp, &gs_key);
-
-      success = really_do_gs_prog(brw, program, bgp, &gs_key, pipeline);
+      success = anv_codegen_gs_prog(brw, program, bgp, &gs_key, pipeline);
       fail_if(!success, "do_gs_prog failed\n");
       add_compiled_stage(pipeline, VK_SHADER_STAGE_GEOMETRY,
                          &pipeline->gs_prog_data.base.base);
@@ -1100,7 +1371,7 @@ anv_compiler_run(struct anv_compiler *compiler, struct anv_pipeline *pipeline)
                          &pipeline->cs_prog_data.base);
    }
 
-   brw->ctx.Driver.DeleteShaderProgram(&brw->ctx, program);
+   _mesa_delete_shader_program(&brw->ctx, program);
 
    struct anv_device *device = compiler->device;
    while (device->scratch_block_pool.bo.size < pipeline->total_scratch)