summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/i965/brw_fs.cpp
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2011-05-16 15:10:26 -0700
committerEric Anholt <[email protected]>2011-05-27 09:07:32 -0700
commit8752764076e5b3f052a57e0134424a37bf2e9164 (patch)
tree7855a121c8669c0330d0577ea4d0caa92a3a45f7 /src/mesa/drivers/dri/i965/brw_fs.cpp
parentd1f70a8a6c6ec7007bad22d3d6013415be2d243a (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.cpp110
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;
+}