Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 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 
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 gl_context *ctx = &brw->ctx;
40
   /* _BRW_NEW_VERTEX_PROGRAM */
41
   const struct brw_vertex_program *vp =
42
      brw_vertex_program_const(brw->vertex_program);
43
 
44
   /* Updates the ParamaterValues[i] pointers for all parameters of the
45
    * basic type of PROGRAM_STATE_VAR.
46
    */
47
   /* XXX: Should this happen somewhere before to get our state flag set? */
48
   _mesa_load_state_parameters(ctx, vp->program.Base.Parameters);
49
 
50
   /* CACHE_NEW_VS_PROG */
51
   if (brw->vs.prog_data->base.nr_params == 0) {
52
      brw->vs.push_const_size = 0;
53
   } else {
54
      int params_uploaded;
55
      float *param;
56
      int i;
57
 
58
      param = brw_state_batch(brw, AUB_TRACE_VS_CONSTANTS,
59
			      brw->vs.prog_data->base.nr_params * sizeof(float),
60
			      32, &brw->vs.push_const_offset);
61
 
62
      /* _NEW_PROGRAM_CONSTANTS
63
       *
64
       * Also _NEW_TRANSFORM -- we may reference clip planes other than as a
65
       * side effect of dereferencing uniforms, so _NEW_PROGRAM_CONSTANTS
66
       * wouldn't be set for them.
67
      */
68
      for (i = 0; i < brw->vs.prog_data->base.nr_params; i++) {
69
         param[i] = *brw->vs.prog_data->base.param[i];
70
      }
71
      params_uploaded = brw->vs.prog_data->base.nr_params / 4;
72
 
73
      if (0) {
74
	 printf("VS constant buffer:\n");
75
	 for (i = 0; i < params_uploaded; i++) {
76
	    float *buf = param + i * 4;
77
	    printf("%d: %f %f %f %f\n",
78
		   i, buf[0], buf[1], buf[2], buf[3]);
79
	 }
80
      }
81
 
82
      brw->vs.push_const_size = (params_uploaded + 1) / 2;
83
      /* We can only push 32 registers of constants at a time. */
84
      assert(brw->vs.push_const_size <= 32);
85
   }
86
}
87
 
88
const struct brw_tracked_state gen6_vs_push_constants = {
89
   .dirty = {
90
      .mesa  = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS,
91
      .brw   = (BRW_NEW_BATCH |
92
		BRW_NEW_VERTEX_PROGRAM),
93
      .cache = CACHE_NEW_VS_PROG,
94
   },
95
   .emit = gen6_upload_vs_push_constants,
96
};
97
 
98
static void
99
upload_vs_state(struct brw_context *brw)
100
{
101
   struct gl_context *ctx = &brw->ctx;
102
   uint32_t floating_point_mode = 0;
103
 
104
   /* From the BSpec, 3D Pipeline > Geometry > Vertex Shader > State,
105
    * 3DSTATE_VS, Dword 5.0 "VS Function Enable":
106
    *
107
    *   [DevSNB] A pipeline flush must be programmed prior to a 3DSTATE_VS
108
    *   command that causes the VS Function Enable to toggle. Pipeline
109
    *   flush can be executed by sending a PIPE_CONTROL command with CS
110
    *   stall bit set and a post sync operation.
111
    *
112
    * Although we don't disable the VS during normal drawing, BLORP sometimes
113
    * disables it.  To be safe, do the flush here just in case.
114
    */
115
   intel_emit_post_sync_nonzero_flush(brw);
116
 
117
   if (brw->vs.push_const_size == 0) {
118
      /* Disable the push constant buffers. */
119
      BEGIN_BATCH(5);
120
      OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 | (5 - 2));
121
      OUT_BATCH(0);
122
      OUT_BATCH(0);
123
      OUT_BATCH(0);
124
      OUT_BATCH(0);
125
      ADVANCE_BATCH();
126
   } else {
127
      BEGIN_BATCH(5);
128
      OUT_BATCH(_3DSTATE_CONSTANT_VS << 16 |
129
		GEN6_CONSTANT_BUFFER_0_ENABLE |
130
		(5 - 2));
131
      /* Pointer to the VS constant buffer.  Covered by the set of
132
       * state flags from gen6_upload_vs_constants
133
       */
134
      OUT_BATCH(brw->vs.push_const_offset +
135
		brw->vs.push_const_size - 1);
136
      OUT_BATCH(0);
137
      OUT_BATCH(0);
138
      OUT_BATCH(0);
139
      ADVANCE_BATCH();
140
   }
141
 
142
   /* Use ALT floating point mode for ARB vertex programs, because they
143
    * require 0^0 == 1.
144
    */
145
   if (ctx->Shader.CurrentVertexProgram == NULL)
146
      floating_point_mode = GEN6_VS_FLOATING_POINT_MODE_ALT;
147
 
148
   BEGIN_BATCH(6);
149
   OUT_BATCH(_3DSTATE_VS << 16 | (6 - 2));
150
   OUT_BATCH(brw->vs.prog_offset);
151
   OUT_BATCH(floating_point_mode |
152
	     ((ALIGN(brw->sampler.count, 4)/4) << GEN6_VS_SAMPLER_COUNT_SHIFT));
153
 
154
   if (brw->vs.prog_data->base.total_scratch) {
155
      OUT_RELOC(brw->vs.scratch_bo,
156
		I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
157
		ffs(brw->vs.prog_data->base.total_scratch) - 11);
158
   } else {
159
      OUT_BATCH(0);
160
   }
161
 
162
   OUT_BATCH((1 << GEN6_VS_DISPATCH_START_GRF_SHIFT) |
163
	     (brw->vs.prog_data->base.urb_read_length << GEN6_VS_URB_READ_LENGTH_SHIFT) |
164
	     (0 << GEN6_VS_URB_ENTRY_READ_OFFSET_SHIFT));
165
 
166
   OUT_BATCH(((brw->max_vs_threads - 1) << GEN6_VS_MAX_THREADS_SHIFT) |
167
	     GEN6_VS_STATISTICS_ENABLE |
168
	     GEN6_VS_ENABLE);
169
   ADVANCE_BATCH();
170
 
171
   /* Based on my reading of the simulator, the VS constants don't get
172
    * pulled into the VS FF unit until an appropriate pipeline flush
173
    * happens, and instead the 3DSTATE_CONSTANT_VS packet just adds
174
    * references to them into a little FIFO.  The flushes are common,
175
    * but don't reliably happen between this and a 3DPRIMITIVE, causing
176
    * the primitive to use the wrong constants.  Then the FIFO
177
    * containing the constant setup gets added to again on the next
178
    * constants change, and eventually when a flush does happen the
179
    * unit is overwhelmed by constant changes and dies.
180
    *
181
    * To avoid this, send a PIPE_CONTROL down the line that will
182
    * update the unit immediately loading the constants.  The flush
183
    * type bits here were those set by the STATE_BASE_ADDRESS whose
184
    * move in a82a43e8d99e1715dd11c9c091b5ab734079b6a6 triggered the
185
    * bug reports that led to this workaround, and may be more than
186
    * what is strictly required to avoid the issue.
187
    */
188
   intel_emit_post_sync_nonzero_flush(brw);
189
 
190
   BEGIN_BATCH(4);
191
   OUT_BATCH(_3DSTATE_PIPE_CONTROL | (4 - 2));
192
   OUT_BATCH(PIPE_CONTROL_DEPTH_STALL |
193
	     PIPE_CONTROL_INSTRUCTION_FLUSH |
194
	     PIPE_CONTROL_STATE_CACHE_INVALIDATE);
195
   OUT_BATCH(0); /* address */
196
   OUT_BATCH(0); /* write data */
197
   ADVANCE_BATCH();
198
}
199
 
200
const struct brw_tracked_state gen6_vs_state = {
201
   .dirty = {
202
      .mesa  = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS,
203
      .brw   = (BRW_NEW_CONTEXT |
204
		BRW_NEW_VERTEX_PROGRAM |
205
		BRW_NEW_BATCH),
206
      .cache = CACHE_NEW_VS_PROG | CACHE_NEW_SAMPLER
207
   },
208
   .emit = upload_vs_state,
209
};