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. --- src/mesa/drivers/dri/i965/brw_fs.cpp | 130 +++++++++++++++++++++++++++++----- src/mesa/drivers/dri/i965/brw_fs.h | 8 ++- src/mesa/drivers/dri/i965/brw_wm.c | 26 +++++-- src/mesa/drivers/dri/i965/brw_wm.h | 7 ++- 4 files changed, 143 insertions(+), 28 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 22d034a..76df4dc 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -77,6 +77,92 @@ brw_new_shader_program(struct gl_context *ctx, GLuint name) return &prog->base; } +bool +brw_wm_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; + } + + key.shadowtex_mask = fp->Base.ShadowSamplers; + + 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; +} + +/** + * Performs a compile of the shader stages even when we don't know + * what non-orthogonal state will be set, in the hope that it reflects + * the eventual NOS used, and thus allows us to produce link failures. + */ +bool +brw_shader_precompile(struct gl_context *ctx, struct gl_shader_program *prog) +{ + if (!brw_wm_precompile(ctx, prog)) + return false; + + return true; +} + GLboolean brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) { @@ -144,6 +230,9 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) if (!_mesa_ir_link_shader(ctx, prog)) return GL_FALSE; + if (!brw_shader_precompile(ctx, prog)) + return GL_FALSE; + return GL_TRUE; } @@ -181,15 +270,20 @@ void fs_visitor::fail(const char *format, ...) { if (!failed) { + va_list va; + char *msg; + failed = true; - if (INTEL_DEBUG & DEBUG_WM) { - fprintf(stderr, "FS compile failed: "); + 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; - va_list va; - va_start(va, format); - vfprintf(stderr, format, va); - va_end(va); + if (INTEL_DEBUG & DEBUG_WM) { + fprintf(stderr, msg); } } } @@ -1419,9 +1513,9 @@ fs_visitor::visit(ir_texture *ir) assert(!ir->projector); sampler = _mesa_get_sampler_uniform_value(ir->sampler, - ctx->Shader.CurrentFragmentProgram, - &brw->fragment_program->Base); - sampler = c->fp->program.Base.SamplerUnits[sampler]; + prog, + &fp->Base); + sampler = fp->Base.SamplerUnits[sampler]; /* The 965 requires the EU to do the normalization of GL rectangle * texture coordinates. We use the program parameter state @@ -2807,7 +2901,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++; } } @@ -3729,7 +3823,7 @@ fs_visitor::generate_code() if (unlikely(INTEL_DEBUG & DEBUG_WM)) { printf("Native code for fragment shader %d (%d-wide dispatch):\n", - ctx->Shader.CurrentFragmentProgram->Name, c->dispatch_width); + prog->Name, c->dispatch_width); } foreach_iter(exec_list_iterator, iter, this->instructions) { @@ -4113,11 +4207,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; @@ -4137,16 +4230,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(); } diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index dd63777..8bd6a14 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -359,12 +359,14 @@ class fs_visitor : public ir_visitor { public: - fs_visitor(struct brw_wm_compile *c, struct brw_shader *shader) + fs_visitor(struct brw_wm_compile *c, struct gl_shader_program *prog, + struct brw_shader *shader) { this->c = c; this->p = &c->func; this->brw = p->brw; - this->fp = brw->fragment_program; + this->fp = prog->FragmentProgram; + this->prog = prog; this->intel = &brw->intel; this->ctx = &intel->ctx; this->mem_ctx = ralloc_context(NULL); @@ -540,6 +542,7 @@ public: struct brw_wm_compile *c; struct brw_compile *p; struct brw_shader *shader; + struct gl_shader_program *prog; void *mem_ctx; exec_list instructions; @@ -568,6 +571,7 @@ public: /** @} */ bool failed; + char *fail_msg; /* Result of last visit() method. */ fs_reg result; diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c index 6054918..d16d39f 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -34,6 +34,7 @@ #include "brw_state.h" #include "main/formats.h" #include "main/samplerobj.h" +#include "program/prog_parameter.h" /** Return number of src args for given instruction */ GLuint brw_wm_nr_args( GLuint opcode ) @@ -182,9 +183,10 @@ brw_wm_payload_setup(struct brw_context *brw, * Depending on the instructions used (i.e. flow control instructions) * we'll use one of two code generators. */ -static void do_wm_prog( struct brw_context *brw, - struct brw_fragment_program *fp, - struct brw_wm_prog_key *key) +bool do_wm_prog(struct brw_context *brw, + struct gl_shader_program *prog, + struct brw_fragment_program *fp, + struct brw_wm_prog_key *key) { struct intel_context *intel = &brw->intel; struct brw_wm_compile *c; @@ -200,7 +202,7 @@ static void do_wm_prog( struct brw_context *brw, * without triggering a segfault, no way to signal, * so just return. */ - return; + return false; } c->instruction = calloc(1, BRW_WM_MAX_INSN * sizeof(*c->instruction)); c->prog_instructions = calloc(1, BRW_WM_MAX_INSN * @@ -225,7 +227,10 @@ static void do_wm_prog( struct brw_context *brw, brw_init_compile(brw, &c->func); - if (!brw_wm_fs_emit(brw, c)) { + if (prog && prog->FragmentProgram) { + if (!brw_wm_fs_emit(brw, c, prog)) + return false; + } else { /* Fallback for fixed function and ARB_fp shaders. */ c->dispatch_width = 16; brw_wm_payload_setup(brw, c); @@ -273,6 +278,8 @@ static void do_wm_prog( struct brw_context *brw, program, program_size, &c->prog_data, sizeof(c->prog_data), &brw->wm.prog_data); + + return true; } @@ -467,6 +474,8 @@ static void brw_wm_populate_key( struct brw_context *brw, static void brw_prepare_wm_prog(struct brw_context *brw) { + struct intel_context *intel = &brw->intel; + struct gl_context *ctx = &intel->ctx; struct brw_wm_prog_key key; struct brw_fragment_program *fp = (struct brw_fragment_program *) brw->fragment_program; @@ -479,8 +488,11 @@ static void brw_prepare_wm_prog(struct brw_context *brw) brw->wm.prog_bo = brw_search_cache(&brw->cache, BRW_WM_PROG, &key, sizeof(key), &brw->wm.prog_data); - if (brw->wm.prog_bo == NULL) - do_wm_prog(brw, fp, &key); + if (brw->wm.prog_bo == NULL) { + bool success = do_wm_prog(brw, ctx->Shader.CurrentFragmentProgram, fp, + &key); + assert(success); + } } diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h index 8ab531b..b5004c4 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.h +++ b/src/mesa/drivers/dri/i965/brw_wm.h @@ -314,7 +314,8 @@ void brw_wm_print_program( struct brw_wm_compile *c, void brw_wm_lookup_iz(struct intel_context *intel, struct brw_wm_compile *c); -bool brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c); +bool brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c, + struct gl_shader_program *prog); /* brw_wm_emit.c */ void emit_alu1(struct brw_compile *p, @@ -476,5 +477,9 @@ bool brw_color_buffer_write_enabled(struct brw_context *brw); bool brw_render_target_supported(gl_format format); void brw_wm_payload_setup(struct brw_context *brw, struct brw_wm_compile *c); +bool do_wm_prog(struct brw_context *brw, + struct gl_shader_program *prog, + struct brw_fragment_program *fp, + struct brw_wm_prog_key *key); #endif -- 1.7.5.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev