diff options
author | Eric Anholt <[email protected]> | 2011-05-16 15:10:26 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2011-05-27 09:07:32 -0700 |
commit | 8752764076e5b3f052a57e0134424a37bf2e9164 (patch) | |
tree | 7855a121c8669c0330d0577ea4d0caa92a3a45f7 /src/mesa/drivers/dri/i965/brw_fs.cpp | |
parent | d1f70a8a6c6ec7007bad22d3d6013415be2d243a (diff) |
i965/fs: Do a FS compile up front at link time to produce link errors.
At glLinkShaders time, a fail() call in FS compile in 8-wide (the one
that's required to succeed, though we may relax that at some point for
pre-Ironlake performance) will now report out as a link error.
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_fs.cpp')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_fs.cpp | 110 |
1 files changed, 93 insertions, 17 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index bec43b43947..36040c3e071 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -84,17 +84,23 @@ fs_visitor::type_size(const struct glsl_type *type) void fs_visitor::fail(const char *format, ...) { - if (!failed) { - failed = true; + va_list va; + char *msg; - if (INTEL_DEBUG & DEBUG_WM) { - fprintf(stderr, "FS compile failed: "); + if (failed) + return; - va_list va; - va_start(va, format); - vfprintf(stderr, format, va); - va_end(va); - } + failed = true; + + va_start(va, format); + msg = ralloc_vasprintf(mem_ctx, format, va); + va_end(va); + msg = ralloc_asprintf(mem_ctx, "FS compile failed: %s\n", msg); + + this->fail_msg = msg; + + if (INTEL_DEBUG & DEBUG_WM) { + fprintf(stderr, msg); } } @@ -643,7 +649,7 @@ fs_visitor::calculate_urb_setup() /* Figure out where each of the incoming setup attributes lands. */ if (intel->gen >= 6) { for (unsigned int i = 0; i < FRAG_ATTRIB_MAX; i++) { - if (brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(i)) { + if (fp->Base.InputsRead & BITFIELD64_BIT(i)) { urb_setup[i] = urb_next++; } } @@ -1587,11 +1593,10 @@ fs_visitor::run() } bool -brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c) +brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c, + struct gl_shader_program *prog) { struct intel_context *intel = &brw->intel; - struct gl_context *ctx = &intel->ctx; - struct gl_shader_program *prog = ctx->Shader.CurrentFragmentProgram; if (!prog) return false; @@ -1611,16 +1616,17 @@ brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c) */ c->dispatch_width = 8; - fs_visitor v(c, shader); + fs_visitor v(c, prog, shader); if (!v.run()) { - /* FINISHME: Cleanly fail, test at link time, etc. */ - assert(!"not reached"); + prog->LinkStatus = GL_FALSE; + prog->InfoLog = ralloc_strdup(prog, v.fail_msg); + return false; } if (intel->gen >= 5 && c->prog_data.nr_pull_params == 0) { c->dispatch_width = 16; - fs_visitor v2(c, shader); + fs_visitor v2(c, prog, shader); v2.import_uniforms(v.variable_ht); v2.run(); } @@ -1629,3 +1635,73 @@ brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c) return true; } + +bool +brw_fs_precompile(struct gl_context *ctx, struct gl_shader_program *prog) +{ + struct brw_context *brw = brw_context(ctx); + struct brw_wm_prog_key key; + struct gl_fragment_program *fp = prog->FragmentProgram; + struct brw_fragment_program *bfp = brw_fragment_program(fp); + + if (!fp) + return true; + + memset(&key, 0, sizeof(key)); + + if (fp->UsesKill) + key.iz_lookup |= IZ_PS_KILL_ALPHATEST_BIT; + + if (fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) + key.iz_lookup |= IZ_PS_COMPUTES_DEPTH_BIT; + + /* Just assume depth testing. */ + key.iz_lookup |= IZ_DEPTH_TEST_ENABLE_BIT; + key.iz_lookup |= IZ_DEPTH_WRITE_ENABLE_BIT; + + key.vp_outputs_written |= BITFIELD64_BIT(FRAG_ATTRIB_WPOS); + for (int i = 0; i < FRAG_ATTRIB_MAX; i++) { + int vp_index = -1; + + if (!(fp->Base.InputsRead & BITFIELD64_BIT(i))) + continue; + + key.proj_attrib_mask |= 1 << i; + + if (i <= FRAG_ATTRIB_TEX7) + vp_index = i; + else if (i >= FRAG_ATTRIB_VAR0) + vp_index = i - FRAG_ATTRIB_VAR0 + VERT_RESULT_VAR0; + + if (vp_index >= 0) + key.vp_outputs_written |= BITFIELD64_BIT(vp_index); + } + + key.clamp_fragment_color = true; + + for (int i = 0; i < BRW_MAX_TEX_UNIT; i++) { + /* FINISHME: depth compares might use (0,0,0,W) for example */ + key.tex_swizzles[i] = SWIZZLE_XYZW; + } + + if (fp->Base.InputsRead & FRAG_BIT_WPOS) { + key.drawable_height = ctx->DrawBuffer->Height; + key.render_to_fbo = ctx->DrawBuffer->Name != 0; + } + + key.nr_color_regions = 1; + + key.program_string_id = bfp->id; + + drm_intel_bo *old_prog_bo = brw->wm.prog_bo; + struct brw_wm_prog_data *old_prog_data = brw->wm.prog_data; + brw->wm.prog_bo = NULL; + + bool success = do_wm_prog(brw, prog, bfp, &key); + + drm_intel_bo_unreference(brw->wm.prog_bo); + brw->wm.prog_bo = old_prog_bo; + brw->wm.prog_data = old_prog_data; + + return success; +} |