blob: 9191c81755de25f646c3acd18a57af7b1d3d73f8 [file] [log] [blame]
Eric Anholt9f344b32006-08-09 19:14:05 +00001/*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial
16 portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **********************************************************************/
27 /*
28 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 */
31
Eric Anholt9f344b32006-08-09 19:14:05 +000032#include "brw_context.h"
Eric Anholt9f344b32006-08-09 19:14:05 +000033#include "brw_wm.h"
34#include "brw_state.h"
Eric Anholt9f344b32006-08-09 19:14:05 +000035
Eric Anholt9f344b32006-08-09 19:14:05 +000036
Brian Paul32e03c42008-12-31 17:16:44 -070037/** Return number of src args for given instruction */
Eric Anholt9f344b32006-08-09 19:14:05 +000038GLuint brw_wm_nr_args( GLuint opcode )
39{
40 switch (opcode) {
Eric Anholt699db6d2009-03-23 16:29:31 -070041 case WM_FRONTFACING:
Eric Anholt9f344b32006-08-09 19:14:05 +000042 case WM_PIXELXY:
Eric Anholt08687c82009-08-12 12:54:43 -070043 return 0;
Eric Anholt046e88f2009-01-08 19:00:10 -080044 case WM_CINTERP:
45 case WM_WPOSXY:
Eric Anholt08687c82009-08-12 12:54:43 -070046 case WM_DELTAXY:
Eric Anholt9f344b32006-08-09 19:14:05 +000047 return 1;
Eric Anholt046e88f2009-01-08 19:00:10 -080048 case WM_LINTERP:
Eric Anholt9f344b32006-08-09 19:14:05 +000049 case WM_PIXELW:
50 return 2;
Eric Anholt9f344b32006-08-09 19:14:05 +000051 case WM_FB_WRITE:
Eric Anholt046e88f2009-01-08 19:00:10 -080052 case WM_PINTERP:
Eric Anholt9f344b32006-08-09 19:14:05 +000053 return 3;
Eric Anholt9f344b32006-08-09 19:14:05 +000054 default:
Eric Anholt046e88f2009-01-08 19:00:10 -080055 assert(opcode < MAX_OPCODE);
56 return _mesa_num_inst_src_regs(opcode);
Eric Anholt9f344b32006-08-09 19:14:05 +000057 }
58}
59
60
61GLuint brw_wm_is_scalar_result( GLuint opcode )
62{
63 switch (opcode) {
64 case OPCODE_COS:
65 case OPCODE_EX2:
66 case OPCODE_LG2:
67 case OPCODE_POW:
68 case OPCODE_RCP:
69 case OPCODE_RSQ:
70 case OPCODE_SIN:
71 case OPCODE_DP3:
72 case OPCODE_DP4:
73 case OPCODE_DPH:
74 case OPCODE_DST:
75 return 1;
76
77 default:
78 return 0;
79 }
80}
81
82
Brian Paul2f78d4a2009-02-12 15:35:41 -070083/**
84 * Do GPU code generation for non-GLSL shader. non-GLSL shaders have
85 * no flow control instructions so we can more readily do SSA-style
86 * optimizations.
87 */
88static void
89brw_wm_non_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c)
90{
91 /* Augment fragment program. Add instructions for pre- and
92 * post-fragment-program tasks such as interpolation and fogging.
93 */
94 brw_wm_pass_fp(c);
95
96 /* Translate to intermediate representation. Build register usage
97 * chains.
98 */
99 brw_wm_pass0(c);
100
101 /* Dead code removal.
102 */
103 brw_wm_pass1(c);
104
105 /* Register allocation.
Brian Paul5f1ce6b2009-03-31 10:53:56 -0600106 * Divide by two because we operate on 16 pixels at a time and require
107 * two GRF entries for each logical shader register.
Brian Paul2f78d4a2009-02-12 15:35:41 -0700108 */
109 c->grf_limit = BRW_WM_MAX_GRF / 2;
110
111 brw_wm_pass2(c);
112
Brian Paul5f1ce6b2009-03-31 10:53:56 -0600113 /* how many general-purpose registers are used */
Brian Paul2f78d4a2009-02-12 15:35:41 -0700114 c->prog_data.total_grf = c->max_wm_grf;
Brian Paul5f1ce6b2009-03-31 10:53:56 -0600115
116 /* Scratch space is used for register spilling */
Brian Paul2f78d4a2009-02-12 15:35:41 -0700117 if (c->last_scratch) {
118 c->prog_data.total_scratch = c->last_scratch + 0x40;
119 }
120 else {
121 c->prog_data.total_scratch = 0;
122 }
123
124 /* Emit GEN4 code.
125 */
126 brw_wm_emit(c);
127}
128
129
130/**
131 * All Mesa program -> GPU code generation goes through this function.
132 * Depending on the instructions used (i.e. flow control instructions)
133 * we'll use one of two code generators.
134 */
Eric Anholt9f344b32006-08-09 19:14:05 +0000135static void do_wm_prog( struct brw_context *brw,
136 struct brw_fragment_program *fp,
137 struct brw_wm_prog_key *key)
138{
Eric Anholtd7b24fe2006-12-09 22:35:07 -0800139 struct brw_wm_compile *c;
Eric Anholt9f344b32006-08-09 19:14:05 +0000140 const GLuint *program;
141 GLuint program_size;
142
Eric Anholtd7b24fe2006-12-09 22:35:07 -0800143 c = brw->wm.compile_data;
144 if (c == NULL) {
Brian Paul14dc4932009-02-12 14:47:56 -0700145 brw->wm.compile_data = calloc(1, sizeof(*brw->wm.compile_data));
146 c = brw->wm.compile_data;
Robert Ellison44a4abf2009-05-08 14:40:38 -0600147 if (c == NULL) {
148 /* Ouch - big out of memory problem. Can't continue
149 * without triggering a segfault, no way to signal,
150 * so just return.
151 */
152 return;
153 }
Eric Anholtc5413832009-11-10 15:51:29 -0800154 c->instruction = _mesa_calloc(BRW_WM_MAX_INSN * sizeof(*c->instruction));
155 c->prog_instructions = _mesa_calloc(BRW_WM_MAX_INSN *
156 sizeof(*c->prog_instructions));
157 c->vreg = _mesa_calloc(BRW_WM_MAX_VREG * sizeof(*c->vreg));
158 c->refs = _mesa_calloc(BRW_WM_MAX_REF * sizeof(*c->refs));
Eric Anholtd7b24fe2006-12-09 22:35:07 -0800159 } else {
Eric Anholtc5413832009-11-10 15:51:29 -0800160 void *instruction = c->instruction;
161 void *prog_instructions = c->prog_instructions;
162 void *vreg = c->vreg;
163 void *refs = c->refs;
Brian Paul14dc4932009-02-12 14:47:56 -0700164 memset(c, 0, sizeof(*brw->wm.compile_data));
Eric Anholtc5413832009-11-10 15:51:29 -0800165 c->instruction = instruction;
166 c->prog_instructions = prog_instructions;
167 c->vreg = vreg;
168 c->refs = refs;
Eric Anholtd7b24fe2006-12-09 22:35:07 -0800169 }
170 memcpy(&c->key, key, sizeof(*key));
Eric Anholt9f344b32006-08-09 19:14:05 +0000171
Eric Anholtd7b24fe2006-12-09 22:35:07 -0800172 c->fp = fp;
173 c->env_param = brw->intel.ctx.FragmentProgram.Parameters;
Eric Anholt9f344b32006-08-09 19:14:05 +0000174
Brian Paul14dc4932009-02-12 14:47:56 -0700175 brw_init_compile(brw, &c->func);
176
Brian Paul5cbd1172009-03-06 16:04:53 -0700177 /* temporary sanity check assertion */
178 ASSERT(fp->isGLSL == brw_wm_is_glsl(&c->fp->program));
179
Brian Paul2f78d4a2009-02-12 15:35:41 -0700180 /*
181 * Shader which use GLSL features such as flow control are handled
182 * differently from "simple" shaders.
183 */
Brian Paul5cbd1172009-03-06 16:04:53 -0700184 if (fp->isGLSL) {
Eric Anholt0eb819a2009-08-11 16:02:54 -0700185 c->dispatch_width = 8;
Brian Paul14dc4932009-02-12 14:47:56 -0700186 brw_wm_glsl_emit(brw, c);
187 }
188 else {
Eric Anholt0eb819a2009-08-11 16:02:54 -0700189 c->dispatch_width = 16;
Brian Paul2f78d4a2009-02-12 15:35:41 -0700190 brw_wm_non_glsl_emit(brw, c);
Eric Anholtd7b24fe2006-12-09 22:35:07 -0800191 }
Brian Paul2f78d4a2009-02-12 15:35:41 -0700192
Eric Anholtfc3971d2009-01-08 19:15:04 -0800193 if (INTEL_DEBUG & DEBUG_WM)
194 fprintf(stderr, "\n");
195
Eric Anholt9f344b32006-08-09 19:14:05 +0000196 /* get the program
197 */
Eric Anholtd7b24fe2006-12-09 22:35:07 -0800198 program = brw_get_program(&c->func, &program_size);
Eric Anholt9f344b32006-08-09 19:14:05 +0000199
Eric Anholt38bad762007-12-14 11:02:48 -0800200 dri_bo_unreference(brw->wm.prog_bo);
Eric Anholt62a96f72010-01-18 13:27:47 -0800201 brw->wm.prog_bo = brw_upload_cache_with_auxdata(&brw->cache, BRW_WM_PROG,
202 &c->key, sizeof(c->key),
203 NULL, 0,
204 program, program_size,
205 &c->prog_data,
206 sizeof(c->prog_data),
207 &brw->wm.prog_data);
Eric Anholt9f344b32006-08-09 19:14:05 +0000208}
209
210
211
212static void brw_wm_populate_key( struct brw_context *brw,
213 struct brw_wm_prog_key *key )
214{
Eric Anholt052c1d62009-01-30 14:32:23 -0800215 GLcontext *ctx = &brw->intel.ctx;
Eric Anholt9f344b32006-08-09 19:14:05 +0000216 /* BRW_NEW_FRAGMENT_PROGRAM */
Brian Paul55d33e12009-02-20 10:49:30 -0700217 const struct brw_fragment_program *fp =
Eric Anholt9f344b32006-08-09 19:14:05 +0000218 (struct brw_fragment_program *)brw->fragment_program;
Eric Anholtf4491642009-08-05 20:12:15 -0700219 GLboolean uses_depth = (fp->program.Base.InputsRead & (1 << FRAG_ATTRIB_WPOS)) != 0;
Eric Anholt9f344b32006-08-09 19:14:05 +0000220 GLuint lookup = 0;
221 GLuint line_aa;
222 GLuint i;
223
224 memset(key, 0, sizeof(*key));
225
226 /* Build the index for table lookup
227 */
228 /* _NEW_COLOR */
229 if (fp->program.UsesKill ||
Eric Anholt052c1d62009-01-30 14:32:23 -0800230 ctx->Color.AlphaEnabled)
Eric Anholt9f344b32006-08-09 19:14:05 +0000231 lookup |= IZ_PS_KILL_ALPHATEST_BIT;
232
Ian Romanick5606dfb2009-11-17 16:10:24 -0800233 if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH))
Eric Anholt9f344b32006-08-09 19:14:05 +0000234 lookup |= IZ_PS_COMPUTES_DEPTH_BIT;
235
236 /* _NEW_DEPTH */
Eric Anholt052c1d62009-01-30 14:32:23 -0800237 if (ctx->Depth.Test)
Eric Anholt9f344b32006-08-09 19:14:05 +0000238 lookup |= IZ_DEPTH_TEST_ENABLE_BIT;
239
Eric Anholt052c1d62009-01-30 14:32:23 -0800240 if (ctx->Depth.Test &&
241 ctx->Depth.Mask) /* ?? */
Eric Anholt9f344b32006-08-09 19:14:05 +0000242 lookup |= IZ_DEPTH_WRITE_ENABLE_BIT;
243
244 /* _NEW_STENCIL */
Brian Paul91e61f42009-03-02 11:47:52 -0700245 if (ctx->Stencil._Enabled) {
Eric Anholt9f344b32006-08-09 19:14:05 +0000246 lookup |= IZ_STENCIL_TEST_ENABLE_BIT;
247
Eric Anholt052c1d62009-01-30 14:32:23 -0800248 if (ctx->Stencil.WriteMask[0] ||
249 ctx->Stencil.WriteMask[ctx->Stencil._BackFace])
Eric Anholt9f344b32006-08-09 19:14:05 +0000250 lookup |= IZ_STENCIL_WRITE_ENABLE_BIT;
251 }
252
Eric Anholt9f344b32006-08-09 19:14:05 +0000253 line_aa = AA_NEVER;
254
255 /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */
Eric Anholt052c1d62009-01-30 14:32:23 -0800256 if (ctx->Line.SmoothFlag) {
Eric Anholt9f344b32006-08-09 19:14:05 +0000257 if (brw->intel.reduced_primitive == GL_LINES) {
258 line_aa = AA_ALWAYS;
259 }
260 else if (brw->intel.reduced_primitive == GL_TRIANGLES) {
Eric Anholt052c1d62009-01-30 14:32:23 -0800261 if (ctx->Polygon.FrontMode == GL_LINE) {
Eric Anholt9f344b32006-08-09 19:14:05 +0000262 line_aa = AA_SOMETIMES;
263
Eric Anholt052c1d62009-01-30 14:32:23 -0800264 if (ctx->Polygon.BackMode == GL_LINE ||
265 (ctx->Polygon.CullFlag &&
266 ctx->Polygon.CullFaceMode == GL_BACK))
Eric Anholt9f344b32006-08-09 19:14:05 +0000267 line_aa = AA_ALWAYS;
268 }
Eric Anholt052c1d62009-01-30 14:32:23 -0800269 else if (ctx->Polygon.BackMode == GL_LINE) {
Eric Anholt9f344b32006-08-09 19:14:05 +0000270 line_aa = AA_SOMETIMES;
271
Eric Anholt052c1d62009-01-30 14:32:23 -0800272 if ((ctx->Polygon.CullFlag &&
273 ctx->Polygon.CullFaceMode == GL_FRONT))
Eric Anholt9f344b32006-08-09 19:14:05 +0000274 line_aa = AA_ALWAYS;
275 }
276 }
277 }
278
279 brw_wm_lookup_iz(line_aa,
280 lookup,
Eric Anholtf4491642009-08-05 20:12:15 -0700281 uses_depth,
Eric Anholt9f344b32006-08-09 19:14:05 +0000282 key);
283
284
285 /* BRW_NEW_WM_INPUT_DIMENSIONS */
Brian Paul6b917d02009-06-16 18:19:45 -0600286 key->proj_attrib_mask = brw->wm.input_size_masks[4-1];
Eric Anholt9f344b32006-08-09 19:14:05 +0000287
288 /* _NEW_LIGHT */
Eric Anholt052c1d62009-01-30 14:32:23 -0800289 key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT);
Eric Anholt9f344b32006-08-09 19:14:05 +0000290
Brian Paul18af7c32009-06-12 16:21:20 -0600291 /* _NEW_HINT */
292 key->linear_color = (ctx->Hint.PerspectiveCorrection == GL_FASTEST);
293
Eric Anholt9f344b32006-08-09 19:14:05 +0000294 /* _NEW_TEXTURE */
295 for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
Eric Anholt052c1d62009-01-30 14:32:23 -0800296 const struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
Eric Anholt9f344b32006-08-09 19:14:05 +0000297
298 if (unit->_ReallyEnabled) {
Brian Paul89fddf92009-01-28 11:42:42 -0700299 const struct gl_texture_object *t = unit->_Current;
300 const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
301 if (img->InternalFormat == GL_YCBCR_MESA) {
302 key->yuvtex_mask |= 1 << i;
Brian Paul1f7c9142009-09-30 20:28:45 -0600303 if (img->TexFormat == MESA_FORMAT_YCBCR)
Brian Paul89fddf92009-01-28 11:42:42 -0700304 key->yuvtex_swap_mask |= 1 << i;
Zou Nan hai76769802008-03-07 15:11:28 +0800305 }
Brian Paulc0d3b762009-01-28 14:50:03 -0700306
307 key->tex_swizzles[i] = t->_Swizzle;
308 }
309 else {
310 key->tex_swizzles[i] = SWIZZLE_NOOP;
Eric Anholt9f344b32006-08-09 19:14:05 +0000311 }
312 }
Eric Anholt9c8f27b2008-02-28 13:18:12 -0800313
Xiang, Haihaob17b1102008-08-20 15:54:41 +0800314 /* Shadow */
315 key->shadowtex_mask = fp->program.Base.ShadowSamplers;
316
Eric Anholt9c8f27b2008-02-28 13:18:12 -0800317 /* _NEW_BUFFERS */
318 /*
319 * Include the draw buffer origin and height so that we can calculate
320 * fragment position values relative to the bottom left of the drawable,
321 * from the incoming screen origin relative position we get as part of our
322 * payload.
323 *
Brian Paul861fec12009-10-29 15:29:41 -0600324 * This is only needed for the WM_WPOSXY opcode when the fragment program
325 * uses the gl_FragCoord input.
326 *
Eric Anholt9c8f27b2008-02-28 13:18:12 -0800327 * We could avoid recompiling by including this as a constant referenced by
328 * our program, but if we were to do that it would also be nice to handle
329 * getting that constant updated at batchbuffer submit time (when we
330 * hold the lock and know where the buffer really is) rather than at emit
331 * time when we don't hold the lock and are just guessing. We could also
332 * just avoid using this as key data if the program doesn't use
333 * fragment.position.
334 *
Brian Paul861fec12009-10-29 15:29:41 -0600335 * For DRI2 the origin_x/y will always be (0,0) but we still need the
336 * drawable height in order to invert the Y axis.
Eric Anholt9c8f27b2008-02-28 13:18:12 -0800337 */
Brian Paul861fec12009-10-29 15:29:41 -0600338 if (fp->program.Base.InputsRead & FRAG_BIT_WPOS) {
Eric Anholtf62c2a02010-01-26 13:08:42 -0800339 key->drawable_height = ctx->DrawBuffer->Height;
Eric Anholt9c8f27b2008-02-28 13:18:12 -0800340 }
Eric Anholt9f344b32006-08-09 19:14:05 +0000341
Brian Paul9ef33b82009-10-29 14:53:53 -0600342 key->nr_color_regions = brw->state.nr_color_regions;
343
Eric Anholt0f5113d2009-05-14 09:49:45 -0700344 /* CACHE_NEW_VS_PROG */
Ian Romanick5606dfb2009-11-17 16:10:24 -0800345 key->vp_outputs_written = brw->vs.prog_data->outputs_written;
Eric Anholt0f5113d2009-05-14 09:49:45 -0700346
Brian Paul55d33e12009-02-20 10:49:30 -0700347 /* The unique fragment program ID */
Eric Anholt9f344b32006-08-09 19:14:05 +0000348 key->program_string_id = fp->id;
Eric Anholt9f344b32006-08-09 19:14:05 +0000349}
350
351
Dave Airlief75843a2008-08-24 17:59:10 +1000352static void brw_prepare_wm_prog(struct brw_context *brw)
Eric Anholt9f344b32006-08-09 19:14:05 +0000353{
354 struct brw_wm_prog_key key;
355 struct brw_fragment_program *fp = (struct brw_fragment_program *)
356 brw->fragment_program;
Eric Anholt125bd4c2007-12-05 16:57:27 -0800357
Eric Anholt9f344b32006-08-09 19:14:05 +0000358 brw_wm_populate_key(brw, &key);
359
360 /* Make an early check for the key.
361 */
Eric Anholt38bad762007-12-14 11:02:48 -0800362 dri_bo_unreference(brw->wm.prog_bo);
363 brw->wm.prog_bo = brw_search_cache(&brw->cache, BRW_WM_PROG,
364 &key, sizeof(key),
365 NULL, 0,
366 &brw->wm.prog_data);
367 if (brw->wm.prog_bo == NULL)
368 do_wm_prog(brw, fp, &key);
Eric Anholt9f344b32006-08-09 19:14:05 +0000369}
370
371
Eric Anholt9f344b32006-08-09 19:14:05 +0000372const struct brw_tracked_state brw_wm_prog = {
373 .dirty = {
374 .mesa = (_NEW_COLOR |
375 _NEW_DEPTH |
Brian Paul18af7c32009-06-12 16:21:20 -0600376 _NEW_HINT |
Eric Anholt9f344b32006-08-09 19:14:05 +0000377 _NEW_STENCIL |
378 _NEW_POLYGON |
379 _NEW_LINE |
380 _NEW_LIGHT |
Eric Anholt9c8f27b2008-02-28 13:18:12 -0800381 _NEW_BUFFERS |
Eric Anholt9f344b32006-08-09 19:14:05 +0000382 _NEW_TEXTURE),
383 .brw = (BRW_NEW_FRAGMENT_PROGRAM |
384 BRW_NEW_WM_INPUT_DIMENSIONS |
385 BRW_NEW_REDUCED_PRIMITIVE),
Eric Anholt0f5113d2009-05-14 09:49:45 -0700386 .cache = CACHE_NEW_VS_PROG,
Eric Anholt9f344b32006-08-09 19:14:05 +0000387 },
Dave Airlie008653a2008-04-17 17:17:23 +1000388 .prepare = brw_prepare_wm_prog
Eric Anholt9f344b32006-08-09 19:14:05 +0000389};
390