Home | History | Annotate | Download | only in i965
      1 /*
      2  * Copyright  2009 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  *
     23  * Authors:
     24  *    Eric Anholt <eric (at) anholt.net>
     25  *
     26  */
     27 
     28 #include "brw_context.h"
     29 #include "brw_state.h"
     30 #include "brw_defines.h"
     31 #include "brw_util.h"
     32 #include "program/prog_parameter.h"
     33 #include "program/prog_statevars.h"
     34 #include "intel_batchbuffer.h"
     35 
     36 static void
     37 gen6_upload_vs_push_constants(struct brw_context *brw)
     38 {
     39    struct intel_context *intel = &brw->intel;
     40    struct gl_context *ctx = &intel->ctx;
     41    /* _BRW_NEW_VERTEX_PROGRAM */
     42    const struct brw_vertex_program *vp =
     43       brw_vertex_program_const(brw->vertex_program);
     44    unsigned int nr_params = brw->vs.prog_data->nr_params / 4;
     45    bool uses_clip_distance = vp->program.UsesClipDistance;
     46 
     47    if (brw->vertex_program->IsNVProgram)
     48       _mesa_load_tracked_matrices(ctx);
     49 
     50    /* Updates the ParamaterValues[i] pointers for all parameters of the
     51     * basic type of PROGRAM_STATE_VAR.
     52     */
     53    /* XXX: Should this happen somewhere before to get our state flag set? */
     54    _mesa_load_state_parameters(ctx, vp->program.Base.Parameters);
     55 
     56    /* CACHE_NEW_VS_PROG | _NEW_TRANSFORM */
     57    if (brw->vs.prog_data->nr_params == 0 && !ctx->Transform.ClipPlanesEnabled) {
     58       brw->vs.push_const_size = 0;
     59    } else {
     60       int params_uploaded = 0;
     61       float *param;
     62       int i;
     63 
     64       param = brw_state_batch(brw, AUB_TRACE_VS_CONSTANTS,
     65 			      (MAX_CLIP_PLANES + nr_params) *
     66 			      4 * sizeof(float),
     67 			      32, &brw->vs.push_const_offset);
     68 
     69       if (brw->vs.prog_data->uses_new_param_layout) {
     70 	 for (i = 0; i < brw->vs.prog_data->nr_params; i++) {
     71 	    *param = *brw->vs.prog_data->param[i];
     72 	    param++;
     73 	 }
     74 	 params_uploaded += brw->vs.prog_data->nr_params / 4;
     75       } else {
     76          /* This should be loaded like any other param, but it's ad-hoc
     77           * until we redo the VS backend.
     78           */
     79          if (ctx->Transform.ClipPlanesEnabled != 0 && !uses_clip_distance) {
     80             gl_clip_plane *clip_planes = brw_select_clip_planes(ctx);
     81             int num_userclip_plane_consts
     82                = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1;
     83             int num_floats = 4 * num_userclip_plane_consts;
     84             memcpy(param, clip_planes, num_floats * sizeof(float));
     85             param += num_floats;
     86             params_uploaded += num_userclip_plane_consts;
     87          }
     88 
     89          /* Align to a reg for convenience for brw_vs_emit.c */
     90          if (params_uploaded & 1) {
     91             param += 4;
     92             params_uploaded++;
     93          }
     94 
     95 	 for (i = 0; i < vp->program.Base.Parameters->NumParameters; i++) {
     96 	    if (brw->vs.constant_map[i] != -1) {
     97 	       memcpy(param + brw->vs.constant_map[i] * 4,
     98 		      vp->program.Base.Parameters->ParameterValues[i],
     99 		      4 * sizeof(float));
    100 	       params_uploaded++;
    101 	    }
    102 	 }
    103       }
    104 
    105       if (0) {
    106 	 printf("VS constant buffer:\n");
    107 	 for (i = 0; i < params_uploaded; i++) {
    108 	    float *buf = param + i * 4;
    109 	    printf("%d: %f %f %f %f\n",
    110 		   i, buf[0], buf[1], buf[2], buf[3]);
    111 	 }
    112       }
    113 
    114       brw->vs.push_const_size = (params_uploaded + 1) / 2;
    115       /* We can only push 32 registers of constants at a time. */
    116       assert(brw->vs.push_const_size <= 32);
    117    }
    118 }
    119 
    120 const struct brw_tracked_state gen6_vs_push_constants = {
    121    .dirty = {
    122       .mesa  = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS,
    123       .brw   = (BRW_NEW_BATCH |
    124 		BRW_NEW_VERTEX_PROGRAM),
    125       .cache = CACHE_NEW_VS_PROG,
    126    },
    127    .emit = gen6_upload_vs_push_constants,
    128 };
    129 
    130 static void
    131 upload_vs_state(struct brw_context *brw)
    132 {
    133    struct intel_context *intel = &brw->intel;
    134    uint32_t floating_point_mode = 0;
    135 
    136    /* From the BSpec, Volume 2a, Part 3 "Vertex Shader", Section
    137     * 3DSTATE_VS, Dword 5.0 "VS Function Enable":
    138     *   [DevSNB] A pipeline flush must be programmed prior to a 3DSTATE_VS
    139     *   command that causes the VS Function Enable to toggle. Pipeline
    140     *   flush can be executed by sending a PIPE_CONTROL command with CS
    141     *   stall bit set and a post sync operation.
    142     */
    143    intel_emit_post_sync_nonzero_flush(intel);
    144 
    145    if (brw->vs.push_const_size == 0) {
    146       /* Disable the push constant buffers. */
    147       BEGIN_BATCH(5);
    148       OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 | (5 - 2));
    149       OUT_BATCH(0);
    150       OUT_BATCH(0);
    151       OUT_BATCH(0);
    152       OUT_BATCH(0);
    153       ADVANCE_BATCH();
    154    } else {
    155       BEGIN_BATCH(5);
    156       OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 |
    157 		GEN6_CONSTANT_BUFFER_0_ENABLE |
    158 		(5 - 2));
    159       /* Pointer to the VS constant buffer.  Covered by the set of
    160        * state flags from gen6_upload_vs_constants
    161        */
    162       OUT_BATCH(brw->vs.push_const_offset +
    163 		brw->vs.push_const_size - 1);
    164       OUT_BATCH(0);
    165       OUT_BATCH(0);
    166       OUT_BATCH(0);
    167       ADVANCE_BATCH();
    168    }
    169 
    170    /* Use ALT floating point mode for ARB vertex programs, because they
    171     * require 0^0 == 1.
    172     */
    173    if (intel->ctx.Shader.CurrentVertexProgram == NULL)
    174       floating_point_mode = GEN6_VS_FLOATING_POINT_MODE_ALT;
    175 
    176    BEGIN_BATCH(6);
    177    OUT_BATCH(_3DSTATE_VS << 16 | (6 - 2));
    178    OUT_BATCH(brw->vs.prog_offset);
    179    OUT_BATCH(floating_point_mode |
    180 	     ((ALIGN(brw->sampler.count, 4)/4) << GEN6_VS_SAMPLER_COUNT_SHIFT));
    181 
    182    if (brw->vs.prog_data->total_scratch) {
    183       OUT_RELOC(brw->vs.scratch_bo,
    184 		I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
    185 		ffs(brw->vs.prog_data->total_scratch) - 11);
    186    } else {
    187       OUT_BATCH(0);
    188    }
    189 
    190    OUT_BATCH((1 << GEN6_VS_DISPATCH_START_GRF_SHIFT) |
    191 	     (brw->vs.prog_data->urb_read_length << GEN6_VS_URB_READ_LENGTH_SHIFT) |
    192 	     (0 << GEN6_VS_URB_ENTRY_READ_OFFSET_SHIFT));
    193 
    194    OUT_BATCH(((brw->max_vs_threads - 1) << GEN6_VS_MAX_THREADS_SHIFT) |
    195 	     GEN6_VS_STATISTICS_ENABLE |
    196 	     GEN6_VS_ENABLE);
    197    ADVANCE_BATCH();
    198 
    199    /* Based on my reading of the simulator, the VS constants don't get
    200     * pulled into the VS FF unit until an appropriate pipeline flush
    201     * happens, and instead the 3DSTATE_CONSTANT_VS packet just adds
    202     * references to them into a little FIFO.  The flushes are common,
    203     * but don't reliably happen between this and a 3DPRIMITIVE, causing
    204     * the primitive to use the wrong constants.  Then the FIFO
    205     * containing the constant setup gets added to again on the next
    206     * constants change, and eventually when a flush does happen the
    207     * unit is overwhelmed by constant changes and dies.
    208     *
    209     * To avoid this, send a PIPE_CONTROL down the line that will
    210     * update the unit immediately loading the constants.  The flush
    211     * type bits here were those set by the STATE_BASE_ADDRESS whose
    212     * move in a82a43e8d99e1715dd11c9c091b5ab734079b6a6 triggered the
    213     * bug reports that led to this workaround, and may be more than
    214     * what is strictly required to avoid the issue.
    215     */
    216    intel_emit_post_sync_nonzero_flush(intel);
    217 
    218    BEGIN_BATCH(4);
    219    OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
    220    OUT_BATCH(PIPE_CONTROL_DEPTH_STALL |
    221 	     PIPE_CONTROL_INSTRUCTION_FLUSH |
    222 	     PIPE_CONTROL_STATE_CACHE_INVALIDATE);
    223    OUT_BATCH(0); /* address */
    224    OUT_BATCH(0); /* write data */
    225    ADVANCE_BATCH();
    226 }
    227 
    228 const struct brw_tracked_state gen6_vs_state = {
    229    .dirty = {
    230       .mesa  = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS,
    231       .brw   = (BRW_NEW_CONTEXT |
    232 		BRW_NEW_VERTEX_PROGRAM |
    233 		BRW_NEW_BATCH),
    234       .cache = CACHE_NEW_VS_PROG | CACHE_NEW_SAMPLER
    235    },
    236    .emit = upload_vs_state,
    237 };
    238