X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_link.cpp;h=977feb37fc2f5768cbf3246ea5678b5cfb856b5a;hb=db6d23cfd22fbe41e7e7de558c987c065e5f3e15;hp=31d29ec9045d333b65de9740d526544bea74acfa;hpb=d5c9955d3eaa7311e2b2350b6964bae516c7b7b2;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/brw_link.cpp b/src/mesa/drivers/dri/i965/brw_link.cpp index 31d29ec9045..977feb37fc2 100644 --- a/src/mesa/drivers/dri/i965/brw_link.cpp +++ b/src/mesa/drivers/dri/i965/brw_link.cpp @@ -26,10 +26,12 @@ #include "brw_fs.h" #include "brw_nir.h" #include "brw_program.h" -#include "glsl/ir_optimization.h" -#include "glsl/glsl_parser_extras.h" +#include "compiler/glsl/ir.h" +#include "compiler/glsl/ir_optimization.h" +#include "compiler/glsl/program.h" #include "program/program.h" #include "main/shaderapi.h" +#include "main/shaderobj.h" #include "main/uniforms.h" /** @@ -41,21 +43,29 @@ static bool brw_shader_precompile(struct gl_context *ctx, struct gl_shader_program *sh_prog) { - struct gl_shader *vs = sh_prog->_LinkedShaders[MESA_SHADER_VERTEX]; - struct gl_shader *gs = sh_prog->_LinkedShaders[MESA_SHADER_GEOMETRY]; - struct gl_shader *fs = sh_prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; - struct gl_shader *cs = sh_prog->_LinkedShaders[MESA_SHADER_COMPUTE]; + struct gl_linked_shader *vs = sh_prog->_LinkedShaders[MESA_SHADER_VERTEX]; + struct gl_linked_shader *tcs = sh_prog->_LinkedShaders[MESA_SHADER_TESS_CTRL]; + struct gl_linked_shader *tes = sh_prog->_LinkedShaders[MESA_SHADER_TESS_EVAL]; + struct gl_linked_shader *gs = sh_prog->_LinkedShaders[MESA_SHADER_GEOMETRY]; + struct gl_linked_shader *fs = sh_prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; + struct gl_linked_shader *cs = sh_prog->_LinkedShaders[MESA_SHADER_COMPUTE]; + + if (fs && !brw_fs_precompile(ctx, fs->Program)) + return false; + + if (gs && !brw_gs_precompile(ctx, gs->Program)) + return false; - if (fs && !brw_fs_precompile(ctx, sh_prog, fs->Program)) + if (tes && !brw_tes_precompile(ctx, sh_prog, tes->Program)) return false; - if (gs && !brw_gs_precompile(ctx, sh_prog, gs->Program)) + if (tcs && !brw_tcs_precompile(ctx, sh_prog, tcs->Program)) return false; - if (vs && !brw_vs_precompile(ctx, sh_prog, vs->Program)) + if (vs && !brw_vs_precompile(ctx, vs->Program)) return false; - if (cs && !brw_cs_precompile(ctx, sh_prog, cs->Program)) + if (cs && !brw_cs_precompile(ctx, cs->Program)) return false; return true; @@ -63,49 +73,24 @@ brw_shader_precompile(struct gl_context *ctx, static void brw_lower_packing_builtins(struct brw_context *brw, - gl_shader_stage shader_type, exec_list *ir) { - const struct brw_compiler *compiler = brw->intelScreen->compiler; - - int ops = LOWER_PACK_SNORM_2x16 - | LOWER_UNPACK_SNORM_2x16 - | LOWER_PACK_UNORM_2x16 - | LOWER_UNPACK_UNORM_2x16; - - if (compiler->scalar_stage[shader_type]) { - ops |= LOWER_UNPACK_UNORM_4x8 - | LOWER_UNPACK_SNORM_4x8 - | LOWER_PACK_UNORM_4x8 - | LOWER_PACK_SNORM_4x8; - } - - if (brw->gen >= 7) { - /* Gen7 introduced the f32to16 and f16to32 instructions, which can be - * used to execute packHalf2x16 and unpackHalf2x16. For AOS code, no - * lowering is needed. For SOA code, the Half2x16 ops must be - * scalarized. - */ - if (compiler->scalar_stage[shader_type]) { - ops |= LOWER_PACK_HALF_2x16_TO_SPLIT - | LOWER_UNPACK_HALF_2x16_TO_SPLIT; - } - } else { - ops |= LOWER_PACK_HALF_2x16 - | LOWER_UNPACK_HALF_2x16; - } + /* Gens < 7 don't have instructions to convert to or from half-precision, + * and Gens < 6 don't expose that functionality. + */ + if (brw->gen != 6) + return; - lower_packing_builtins(ir, ops); + lower_packing_builtins(ir, LOWER_PACK_HALF_2x16 | LOWER_UNPACK_HALF_2x16); } static void -process_glsl_ir(gl_shader_stage stage, - struct brw_context *brw, +process_glsl_ir(struct brw_context *brw, struct gl_shader_program *shader_prog, - struct gl_shader *shader) + struct gl_linked_shader *shader) { struct gl_context *ctx = &brw->ctx; - const struct brw_compiler *compiler = brw->intelScreen->compiler; + const struct brw_compiler *compiler = brw->screen->compiler; const struct gl_shader_compiler_options *options = &ctx->Const.ShaderCompilerOptions[shader->Stage]; @@ -114,67 +99,57 @@ process_glsl_ir(gl_shader_stage stage, ralloc_adopt(mem_ctx, shader->ir); + lower_blend_equation_advanced(shader); + /* lower_packing_builtins() inserts arithmetic instructions, so it * must precede lower_instructions(). */ - brw_lower_packing_builtins(brw, shader->Stage, shader->ir); + brw_lower_packing_builtins(brw, shader->ir); do_mat_op_to_vec(shader->ir); - const int bitfield_insert = brw->gen >= 7 ? BITFIELD_INSERT_TO_BFM_BFI : 0; - lower_instructions(shader->ir, - MOD_TO_FLOOR | - DIV_TO_MUL_RCP | - SUB_TO_ADD_NEG | - EXP_TO_EXP2 | - LOG_TO_LOG2 | - bitfield_insert | - LDEXP_TO_ARITH | - CARRY_TO_ARITH | - BORROW_TO_ARITH); + + unsigned instructions_to_lower = (DIV_TO_MUL_RCP | + SUB_TO_ADD_NEG | + EXP_TO_EXP2 | + LOG_TO_LOG2 | + DFREXP_DLDEXP_TO_ARITH); + if (brw->gen < 7) { + instructions_to_lower |= BIT_COUNT_TO_MATH | + EXTRACT_TO_SHIFTS | + INSERT_TO_SHIFTS | + REVERSE_TO_SHIFTS; + } + + lower_instructions(shader->ir, instructions_to_lower); + lower_64bit_integer_instructions(shader->ir, + MUL64 | + DIV64 | + MOD64 | + SIGN64); /* Pre-gen6 HW can only nest if-statements 16 deep. Beyond this, * if-statements need to be flattened. */ if (brw->gen < 6) - lower_if_to_cond_assign(shader->ir, 16); + lower_if_to_cond_assign(shader->Stage, shader->ir, 16); do_lower_texture_projection(shader->ir); - brw_lower_texture_gradients(brw, shader->ir); do_vec_index_to_cond_assign(shader->ir); lower_vector_insert(shader->ir, true); lower_offset_arrays(shader->ir); - brw_do_lower_unnormalized_offset(shader->ir); lower_noise(shader->ir); lower_quadop_vector(shader->ir, false); - bool lowered_variable_indexing = - lower_variable_index_to_cond_assign((gl_shader_stage)stage, - shader->ir, - options->EmitNoIndirectInput, - options->EmitNoIndirectOutput, - options->EmitNoIndirectTemp, - options->EmitNoIndirectUniform); - - if (unlikely(brw->perf_debug && lowered_variable_indexing)) { - perf_debug("Unsupported form of variable indexing in %s; falling " - "back to very inefficient code generation\n", - _mesa_shader_stage_to_abbrev(shader->Stage)); - } - bool progress; do { progress = false; if (compiler->scalar_stage[shader->Stage]) { - brw_do_channel_expressions(shader->ir); + if (shader->Stage == MESA_SHADER_VERTEX || + shader->Stage == MESA_SHADER_FRAGMENT) + brw_do_channel_expressions(shader->ir); brw_do_vector_splitting(shader->ir); } - progress = do_lower_jumps(shader->ir, true, true, - true, /* main return */ - false, /* continue */ - false /* loops */ - ) || progress; - progress = do_common_optimization(shader->ir, true, true, options, ctx->Const.NativeIntegers) || progress; } while (progress); @@ -190,76 +165,109 @@ process_glsl_ir(gl_shader_stage stage, if (ctx->_Shader->Flags & GLSL_DUMP) { fprintf(stderr, "\n"); - fprintf(stderr, "GLSL IR for linked %s program %d:\n", - _mesa_shader_stage_to_string(shader->Stage), - shader_prog->Name); - _mesa_print_ir(stderr, shader->ir, NULL); + if (shader->ir) { + fprintf(stderr, "GLSL IR for linked %s program %d:\n", + _mesa_shader_stage_to_string(shader->Stage), + shader_prog->Name); + _mesa_print_ir(stderr, shader->ir, NULL); + } else { + fprintf(stderr, "No GLSL IR for linked %s program %d (shader may be " + "from cache)\n", _mesa_shader_stage_to_string(shader->Stage), + shader_prog->Name); + } fprintf(stderr, "\n"); } } +static void +unify_interfaces(struct shader_info **infos) +{ + struct shader_info *prev_info = NULL; + + for (unsigned i = MESA_SHADER_VERTEX; i < MESA_SHADER_FRAGMENT; i++) { + if (!infos[i]) + continue; + + if (prev_info) { + prev_info->outputs_written |= infos[i]->inputs_read & + ~(VARYING_BIT_TESS_LEVEL_INNER | VARYING_BIT_TESS_LEVEL_OUTER); + infos[i]->inputs_read |= prev_info->outputs_written & + ~(VARYING_BIT_TESS_LEVEL_INNER | VARYING_BIT_TESS_LEVEL_OUTER); + + prev_info->patch_outputs_written |= infos[i]->patch_inputs_read; + infos[i]->patch_inputs_read |= prev_info->patch_outputs_written; + } + prev_info = infos[i]; + } +} + extern "C" GLboolean brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg) { struct brw_context *brw = brw_context(ctx); - const struct brw_compiler *compiler = brw->intelScreen->compiler; + const struct brw_compiler *compiler = brw->screen->compiler; unsigned int stage; + struct shader_info *infos[MESA_SHADER_STAGES] = { 0, }; for (stage = 0; stage < ARRAY_SIZE(shProg->_LinkedShaders); stage++) { - struct gl_shader *shader = shProg->_LinkedShaders[stage]; + struct gl_linked_shader *shader = shProg->_LinkedShaders[stage]; if (!shader) - continue; + continue; - struct gl_program *prog = - ctx->Driver.NewProgram(ctx, _mesa_shader_stage_to_program(stage), - shader->Name); - if (!prog) - return false; + struct gl_program *prog = shader->Program; prog->Parameters = _mesa_new_parameter_list(); - _mesa_copy_linked_program_data((gl_shader_stage) stage, shProg, prog); + process_glsl_ir(brw, shProg, shader); - process_glsl_ir((gl_shader_stage) stage, brw, shProg, shader); + _mesa_copy_linked_program_data(shProg, shader); - /* Make a pass over the IR to add state references for any built-in - * uniforms that are used. This has to be done now (during linking). - * Code generation doesn't happen until the first time this shader is - * used for rendering. Waiting until then to generate the parameters is - * too late. At that point, the values for the built-in uniforms won't - * get sent to the shader. - */ - foreach_in_list(ir_instruction, node, shader->ir) { - ir_variable *var = node->as_variable(); - - if ((var == NULL) || (var->data.mode != ir_var_uniform) - || (strncmp(var->name, "gl_", 3) != 0)) - continue; - - const ir_state_slot *const slots = var->get_state_slots(); - assert(slots != NULL); - - for (unsigned int i = 0; i < var->get_num_state_slots(); i++) { - _mesa_add_state_reference(prog->Parameters, - (gl_state_index *) slots[i].tokens); - } - } - - do_set_program_inouts(shader->ir, prog, shader->Stage); - - prog->SamplersUsed = shader->active_samplers; prog->ShadowSamplers = shader->shadow_samplers; _mesa_update_shader_textures_used(shProg, prog); - _mesa_reference_program(ctx, &shader->Program, prog); - brw_add_texrect_params(prog); + bool debug_enabled = + (INTEL_DEBUG & intel_debug_flag_for_shader_stage(shader->Stage)); + + if (debug_enabled && shader->ir) { + fprintf(stderr, "GLSL IR for native %s shader %d:\n", + _mesa_shader_stage_to_string(shader->Stage), shProg->Name); + _mesa_print_ir(stderr, shader->ir, NULL); + fprintf(stderr, "\n\n"); + } + prog->nir = brw_create_nir(brw, shProg, prog, (gl_shader_stage) stage, compiler->scalar_stage[stage]); + infos[stage] = prog->nir->info; - _mesa_reference_program(ctx, &prog, NULL); + /* Make a pass over the IR to add state references for any built-in + * uniforms that are used. This has to be done now (during linking). + * Code generation doesn't happen until the first time this shader is + * used for rendering. Waiting until then to generate the parameters is + * too late. At that point, the values for the built-in uniforms won't + * get sent to the shader. + */ + nir_foreach_variable(var, &prog->nir->uniforms) { + if (strncmp(var->name, "gl_", 3) == 0) { + const nir_state_slot *const slots = var->state_slots; + assert(var->state_slots != NULL); + + for (unsigned int i = 0; i < var->num_state_slots; i++) { + _mesa_add_state_reference(prog->Parameters, + (gl_state_index *)slots[i].tokens); + } + } + } } + /* The linker tries to dead code eliminate unused varying components, + * and make sure interfaces match. But it isn't able to do so in all + * cases. So, explicitly make the interfaces match by OR'ing together + * the inputs_read/outputs_written bitfields of adjacent stages. + */ + if (!shProg->SeparateShader) + unify_interfaces(infos); + if ((ctx->_Shader->Flags & GLSL_DUMP) && shProg->Name != 0) { for (unsigned i = 0; i < shProg->NumShaders; i++) { const struct gl_shader *sh = shProg->Shaders[i]; @@ -277,5 +285,17 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg) if (brw->precompile && !brw_shader_precompile(ctx, shProg)) return false; + build_program_resource_list(ctx, shProg); + + for (stage = 0; stage < ARRAY_SIZE(shProg->_LinkedShaders); stage++) { + struct gl_linked_shader *shader = shProg->_LinkedShaders[stage]; + if (!shader) + continue; + + /* The GLSL IR won't be needed anymore. */ + ralloc_free(shader->ir); + shader->ir = NULL; + } + return true; }