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 | };><>><>><>><>><>><>><>><>=>>> |