1 /*
2 * Copyright © 2011 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
24 #include "compiler/nir/nir.h"
25 #include "brw_context.h"
26 #include "brw_state.h"
27 #include "brw_defines.h"
28 #include "brw_util.h"
29 #include "main/macros.h"
30 #include "main/fbobject.h"
31 #include "intel_batchbuffer.h"
32
33 static void
upload_sbe(struct brw_context * brw)34 upload_sbe(struct brw_context *brw)
35 {
36 struct gl_context *ctx = &brw->ctx;
37 /* BRW_NEW_FS_PROG_DATA */
38 const struct brw_wm_prog_data *wm_prog_data =
39 brw_wm_prog_data(brw->wm.base.prog_data);
40 uint32_t num_outputs = wm_prog_data->num_varying_inputs;
41 uint16_t attr_overrides[VARYING_SLOT_MAX];
42 uint32_t urb_entry_read_length;
43 uint32_t urb_entry_read_offset;
44 uint32_t point_sprite_enables;
45 int sbe_cmd_length;
46
47 uint32_t dw1 =
48 GEN7_SBE_SWIZZLE_ENABLE |
49 num_outputs << GEN7_SBE_NUM_OUTPUTS_SHIFT;
50 uint32_t dw4 = 0;
51 uint32_t dw5 = 0;
52
53 /* _NEW_BUFFERS */
54 bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer);
55
56 /* _NEW_POINT
57 *
58 * Window coordinates in an FBO are inverted, which means point
59 * sprite origin must be inverted.
60 */
61 if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo)
62 dw1 |= GEN6_SF_POINT_SPRITE_LOWERLEFT;
63 else
64 dw1 |= GEN6_SF_POINT_SPRITE_UPPERLEFT;
65
66 /* _NEW_POINT | _NEW_LIGHT | _NEW_PROGRAM,
67 * BRW_NEW_FS_PROG_DATA | BRW_NEW_FRAGMENT_PROGRAM |
68 * BRW_NEW_GS_PROG_DATA | BRW_NEW_PRIMITIVE | BRW_NEW_TES_PROG_DATA |
69 * BRW_NEW_VUE_MAP_GEOM_OUT
70 */
71 calculate_attr_overrides(brw, attr_overrides,
72 &point_sprite_enables,
73 &urb_entry_read_length,
74 &urb_entry_read_offset);
75
76 /* Typically, the URB entry read length and offset should be programmed in
77 * 3DSTATE_VS and 3DSTATE_GS; SBE inherits it from the last active stage
78 * which produces geometry. However, we don't know the proper value until
79 * we call calculate_attr_overrides().
80 *
81 * To fit with our existing code, we override the inherited values and
82 * specify it here directly, as we did on previous generations.
83 */
84 dw1 |=
85 urb_entry_read_length << GEN7_SBE_URB_ENTRY_READ_LENGTH_SHIFT |
86 urb_entry_read_offset << GEN8_SBE_URB_ENTRY_READ_OFFSET_SHIFT |
87 GEN8_SBE_FORCE_URB_ENTRY_READ_LENGTH |
88 GEN8_SBE_FORCE_URB_ENTRY_READ_OFFSET;
89
90 if (brw->gen == 8) {
91 sbe_cmd_length = 4;
92 } else {
93 sbe_cmd_length = 6;
94
95 /* prepare the active component dwords */
96 int input_index = 0;
97 for (int attr = 0; attr < VARYING_SLOT_MAX; attr++) {
98 if (!(brw->fragment_program->info.inputs_read &
99 BITFIELD64_BIT(attr))) {
100 continue;
101 }
102
103 assert(input_index < 32);
104
105 if (input_index < 16)
106 dw4 |= (GEN9_SBE_ACTIVE_COMPONENT_XYZW << (input_index << 1));
107 else
108 dw5 |= (GEN9_SBE_ACTIVE_COMPONENT_XYZW << ((input_index - 16) << 1));
109
110 ++input_index;
111 }
112 }
113 BEGIN_BATCH(sbe_cmd_length);
114 OUT_BATCH(_3DSTATE_SBE << 16 | (sbe_cmd_length - 2));
115 OUT_BATCH(dw1);
116 OUT_BATCH(point_sprite_enables);
117 OUT_BATCH(wm_prog_data->flat_inputs);
118 if (sbe_cmd_length >= 6) {
119 OUT_BATCH(dw4);
120 OUT_BATCH(dw5);
121 }
122 ADVANCE_BATCH();
123
124 BEGIN_BATCH(11);
125 OUT_BATCH(_3DSTATE_SBE_SWIZ << 16 | (11 - 2));
126
127 /* Output DWords 1 through 8: */
128 for (int i = 0; i < 8; i++) {
129 OUT_BATCH(attr_overrides[i * 2] | attr_overrides[i * 2 + 1] << 16);
130 }
131
132 OUT_BATCH(0); /* wrapshortest enables 0-7 */
133 OUT_BATCH(0); /* wrapshortest enables 8-15 */
134 ADVANCE_BATCH();
135 }
136
137 const struct brw_tracked_state gen8_sbe_state = {
138 .dirty = {
139 .mesa = _NEW_BUFFERS |
140 _NEW_LIGHT |
141 _NEW_POINT |
142 _NEW_POLYGON |
143 _NEW_PROGRAM,
144 .brw = BRW_NEW_BLORP |
145 BRW_NEW_CONTEXT |
146 BRW_NEW_FRAGMENT_PROGRAM |
147 BRW_NEW_FS_PROG_DATA |
148 BRW_NEW_GS_PROG_DATA |
149 BRW_NEW_TES_PROG_DATA |
150 BRW_NEW_VUE_MAP_GEOM_OUT,
151 },
152 .emit = upload_sbe,
153 };
154
155 static void
upload_sf(struct brw_context * brw)156 upload_sf(struct brw_context *brw)
157 {
158 struct gl_context *ctx = &brw->ctx;
159 uint32_t dw1 = 0, dw2 = 0, dw3 = 0;
160 float point_size;
161
162 dw1 = GEN6_SF_STATISTICS_ENABLE;
163
164 if (brw->sf.viewport_transform_enable)
165 dw1 |= GEN6_SF_VIEWPORT_TRANSFORM_ENABLE;
166
167 /* _NEW_LINE */
168 uint32_t line_width_u3_7 = brw_get_line_width(brw);
169 if (brw->gen >= 9 || brw->is_cherryview) {
170 dw1 |= line_width_u3_7 << GEN9_SF_LINE_WIDTH_SHIFT;
171 } else {
172 dw2 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT;
173 }
174
175 if (ctx->Line.SmoothFlag) {
176 dw2 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0;
177 }
178
179 /* _NEW_POINT - Clamp to ARB_point_parameters user limits */
180 point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize);
181
182 /* Clamp to the hardware limits and convert to fixed point */
183 dw3 |= U_FIXED(CLAMP(point_size, 0.125f, 255.875f), 3);
184
185 /* _NEW_PROGRAM | _NEW_POINT, BRW_NEW_VUE_MAP_GEOM_OUT */
186 if (use_state_point_size(brw))
187 dw3 |= GEN6_SF_USE_STATE_POINT_WIDTH;
188
189 /* _NEW_POINT | _NEW_MULTISAMPLE */
190 if ((ctx->Point.SmoothFlag || _mesa_is_multisample_enabled(ctx)) &&
191 !ctx->Point.PointSprite) {
192 dw3 |= GEN8_SF_SMOOTH_POINT_ENABLE;
193 }
194
195 dw3 |= GEN6_SF_LINE_AA_MODE_TRUE;
196
197 /* _NEW_LIGHT */
198 if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) {
199 dw3 |= (2 << GEN6_SF_TRI_PROVOKE_SHIFT) |
200 (2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) |
201 (1 << GEN6_SF_LINE_PROVOKE_SHIFT);
202 } else {
203 dw3 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT);
204 }
205
206 BEGIN_BATCH(4);
207 OUT_BATCH(_3DSTATE_SF << 16 | (4 - 2));
208 OUT_BATCH(dw1);
209 OUT_BATCH(dw2);
210 OUT_BATCH(dw3);
211 ADVANCE_BATCH();
212 }
213
214 const struct brw_tracked_state gen8_sf_state = {
215 .dirty = {
216 .mesa = _NEW_LIGHT |
217 _NEW_PROGRAM |
218 _NEW_LINE |
219 _NEW_MULTISAMPLE |
220 _NEW_POINT,
221 .brw = BRW_NEW_BLORP |
222 BRW_NEW_CONTEXT |
223 BRW_NEW_VUE_MAP_GEOM_OUT,
224 },
225 .emit = upload_sf,
226 };
227
228 static void
upload_raster(struct brw_context * brw)229 upload_raster(struct brw_context *brw)
230 {
231 struct gl_context *ctx = &brw->ctx;
232 uint32_t dw1 = 0;
233
234 /* _NEW_BUFFERS */
235 bool render_to_fbo = _mesa_is_user_fbo(brw->ctx.DrawBuffer);
236
237 /* _NEW_POLYGON */
238 if (ctx->Polygon._FrontBit == render_to_fbo)
239 dw1 |= GEN8_RASTER_FRONT_WINDING_CCW;
240
241 if (ctx->Polygon.CullFlag) {
242 switch (ctx->Polygon.CullFaceMode) {
243 case GL_FRONT:
244 dw1 |= GEN8_RASTER_CULL_FRONT;
245 break;
246 case GL_BACK:
247 dw1 |= GEN8_RASTER_CULL_BACK;
248 break;
249 case GL_FRONT_AND_BACK:
250 dw1 |= GEN8_RASTER_CULL_BOTH;
251 break;
252 default:
253 unreachable("not reached");
254 }
255 } else {
256 dw1 |= GEN8_RASTER_CULL_NONE;
257 }
258
259 /* _NEW_POINT */
260 if (ctx->Point.SmoothFlag)
261 dw1 |= GEN8_RASTER_SMOOTH_POINT_ENABLE;
262
263 if (_mesa_is_multisample_enabled(ctx))
264 dw1 |= GEN8_RASTER_API_MULTISAMPLE_ENABLE;
265
266 if (ctx->Polygon.OffsetFill)
267 dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID;
268
269 if (ctx->Polygon.OffsetLine)
270 dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME;
271
272 if (ctx->Polygon.OffsetPoint)
273 dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT;
274
275 switch (ctx->Polygon.FrontMode) {
276 case GL_FILL:
277 dw1 |= GEN6_SF_FRONT_SOLID;
278 break;
279 case GL_LINE:
280 dw1 |= GEN6_SF_FRONT_WIREFRAME;
281 break;
282 case GL_POINT:
283 dw1 |= GEN6_SF_FRONT_POINT;
284 break;
285
286 default:
287 unreachable("not reached");
288 }
289
290 switch (ctx->Polygon.BackMode) {
291 case GL_FILL:
292 dw1 |= GEN6_SF_BACK_SOLID;
293 break;
294 case GL_LINE:
295 dw1 |= GEN6_SF_BACK_WIREFRAME;
296 break;
297 case GL_POINT:
298 dw1 |= GEN6_SF_BACK_POINT;
299 break;
300 default:
301 unreachable("not reached");
302 }
303
304 /* _NEW_LINE */
305 if (ctx->Line.SmoothFlag)
306 dw1 |= GEN8_RASTER_LINE_AA_ENABLE;
307
308 /* _NEW_SCISSOR */
309 if (ctx->Scissor.EnableFlags)
310 dw1 |= GEN8_RASTER_SCISSOR_ENABLE;
311
312 /* _NEW_TRANSFORM */
313 if (!ctx->Transform.DepthClamp) {
314 if (brw->gen >= 9) {
315 dw1 |= GEN9_RASTER_VIEWPORT_Z_NEAR_CLIP_TEST_ENABLE |
316 GEN9_RASTER_VIEWPORT_Z_FAR_CLIP_TEST_ENABLE;
317 } else {
318 dw1 |= GEN8_RASTER_VIEWPORT_Z_CLIP_TEST_ENABLE;
319 }
320 }
321
322 /* BRW_NEW_CONSERVATIVE_RASTERIZATION */
323 if (ctx->IntelConservativeRasterization) {
324 if (brw->gen >= 9)
325 dw1 |= GEN9_RASTER_CONSERVATIVE_RASTERIZATION_ENABLE;
326 }
327
328 BEGIN_BATCH(5);
329 OUT_BATCH(_3DSTATE_RASTER << 16 | (5 - 2));
330 OUT_BATCH(dw1);
331 OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */
332 OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */
333 OUT_BATCH_F(ctx->Polygon.OffsetClamp); /* global depth offset clamp */
334 ADVANCE_BATCH();
335 }
336
337 const struct brw_tracked_state gen8_raster_state = {
338 .dirty = {
339 .mesa = _NEW_BUFFERS |
340 _NEW_LINE |
341 _NEW_MULTISAMPLE |
342 _NEW_POINT |
343 _NEW_POLYGON |
344 _NEW_SCISSOR |
345 _NEW_TRANSFORM,
346 .brw = BRW_NEW_BLORP |
347 BRW_NEW_CONTEXT |
348 BRW_NEW_CONSERVATIVE_RASTERIZATION,
349 },
350 .emit = upload_raster,
351 };
352