X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_vs.c;h=b68a2fcaf28f668a34e94f2c3675a3abab63aa20;hb=eb3047c094abfa03e071453d7c373e9c2c574370;hp=59b748f20558303b5b13fe6e6bc5709b3a201776;hpb=d5c9955d3eaa7311e2b2350b6964bae516c7b7b2;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/brw_vs.c b/src/mesa/drivers/dri/i965/brw_vs.c index 59b748f2055..b68a2fcaf28 100644 --- a/src/mesa/drivers/dri/i965/brw_vs.c +++ b/src/mesa/drivers/dri/i965/brw_vs.c @@ -38,94 +38,56 @@ #include "brw_state.h" #include "program/prog_print.h" #include "program/prog_parameter.h" -#include "brw_nir.h" +#include "compiler/brw_nir.h" #include "brw_program.h" #include "util/ralloc.h" -bool -brw_codegen_vs_prog(struct brw_context *brw, - struct gl_shader_program *prog, - struct brw_vertex_program *vp, - struct brw_vs_prog_key *key) +/** + * Decide which set of clip planes should be used when clipping via + * gl_Position or gl_ClipVertex. + */ +gl_clip_plane * +brw_select_clip_planes(struct gl_context *ctx) { - const struct brw_compiler *compiler = brw->intelScreen->compiler; - GLuint program_size; - const GLuint *program; - struct brw_vs_prog_data prog_data; - struct brw_stage_prog_data *stage_prog_data = &prog_data.base.base; - void *mem_ctx; - int i; - struct brw_shader *vs = NULL; - bool start_busy = false; - double start_time = 0; - - if (prog) - vs = (struct brw_shader *) prog->_LinkedShaders[MESA_SHADER_VERTEX]; - - memset(&prog_data, 0, sizeof(prog_data)); - - /* Use ALT floating point mode for ARB programs so that 0^0 == 1. */ - if (!prog) - stage_prog_data->use_alt_mode = true; - - mem_ctx = ralloc_context(NULL); - - brw_assign_common_binding_table_offsets(MESA_SHADER_VERTEX, - brw->intelScreen->devinfo, - prog, &vp->program.Base, - &prog_data.base.base, 0); - - /* Allocate the references to the uniforms that will end up in the - * prog_data associated with the compiled program, and which will be freed - * by the state cache. - */ - int param_count = vp->program.Base.nir->num_uniforms; - if (!compiler->scalar_stage[MESA_SHADER_VERTEX]) - param_count *= 4; - - if (vs) - prog_data.base.base.nr_image_params = vs->base.NumImages; - - /* vec4_visitor::setup_uniform_clipplane_values() also uploads user clip - * planes as uniforms. - */ - param_count += key->nr_userclip_plane_consts * 4; - - stage_prog_data->param = - rzalloc_array(NULL, const gl_constant_value *, param_count); - stage_prog_data->pull_param = - rzalloc_array(NULL, const gl_constant_value *, param_count); - stage_prog_data->image_param = - rzalloc_array(NULL, struct brw_image_param, - stage_prog_data->nr_image_params); - stage_prog_data->nr_params = param_count; - - if (prog) { - brw_nir_setup_glsl_uniforms(vp->program.Base.nir, prog, &vp->program.Base, - &prog_data.base.base, - compiler->scalar_stage[MESA_SHADER_VERTEX]); + if (ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]) { + /* There is currently a GLSL vertex shader, so clip according to GLSL + * rules, which means compare gl_ClipVertex (or gl_Position, if + * gl_ClipVertex wasn't assigned) against the eye-coordinate clip planes + * that were stored in EyeUserPlane at the time the clip planes were + * specified. + */ + return ctx->Transform.EyeUserPlane; } else { - brw_nir_setup_arb_uniforms(vp->program.Base.nir, &vp->program.Base, - &prog_data.base.base); + /* Either we are using fixed function or an ARB vertex program. In + * either case the clip planes are going to be compared against + * gl_Position (which is in clip coordinates) so we have to clip using + * _ClipUserPlane, which was transformed into clip coordinates by Mesa + * core. + */ + return ctx->Transform._ClipUserPlane; } +} - GLbitfield64 outputs_written = vp->program.Base.OutputsWritten; - prog_data.inputs_read = vp->program.Base.InputsRead; +static GLbitfield64 +brw_vs_outputs_written(struct brw_context *brw, struct brw_vs_prog_key *key, + GLbitfield64 user_varyings) +{ + const struct gen_device_info *devinfo = &brw->screen->devinfo; + GLbitfield64 outputs_written = user_varyings; if (key->copy_edgeflag) { outputs_written |= BITFIELD64_BIT(VARYING_SLOT_EDGE); - prog_data.inputs_read |= VERT_BIT_EDGEFLAG; } - if (brw->gen < 6) { + if (devinfo->gen < 6) { /* Put dummy slots into the VUE for the SF to put the replaced * point sprite coords in. We shouldn't need these dummy slots, * which take up precious URB space, but it would mean that the SF * doesn't get nice aligned pairs of input coords into output * coords, which would be a pain to handle. */ - for (i = 0; i < 8; i++) { + for (unsigned i = 0; i < 8; i++) { if (key->point_coord_replace & (1 << i)) outputs_written |= BITFIELD64_BIT(VARYING_SLOT_TEX0 + i); } @@ -146,44 +108,89 @@ brw_codegen_vs_prog(struct brw_context *brw, outputs_written |= BITFIELD64_BIT(VARYING_SLOT_CLIP_DIST1); } - brw_compute_vue_map(brw->intelScreen->devinfo, + return outputs_written; +} + +static bool +brw_codegen_vs_prog(struct brw_context *brw, + struct brw_program *vp, + struct brw_vs_prog_key *key) +{ + const struct brw_compiler *compiler = brw->screen->compiler; + const struct gen_device_info *devinfo = &brw->screen->devinfo; + const GLuint *program; + struct brw_vs_prog_data prog_data; + struct brw_stage_prog_data *stage_prog_data = &prog_data.base.base; + void *mem_ctx; + bool start_busy = false; + double start_time = 0; + + memset(&prog_data, 0, sizeof(prog_data)); + + /* Use ALT floating point mode for ARB programs so that 0^0 == 1. */ + if (vp->program.is_arb_asm) + stage_prog_data->use_alt_mode = true; + + mem_ctx = ralloc_context(NULL); + + nir_shader *nir = nir_shader_clone(mem_ctx, vp->program.nir); + + brw_assign_common_binding_table_offsets(devinfo, &vp->program, + &prog_data.base.base, 0); + + if (!vp->program.is_arb_asm) { + brw_nir_setup_glsl_uniforms(mem_ctx, nir, &vp->program, + &prog_data.base.base, + compiler->scalar_stage[MESA_SHADER_VERTEX]); + brw_nir_analyze_ubo_ranges(compiler, nir, key, + prog_data.base.base.ubo_ranges); + } else { + brw_nir_setup_arb_uniforms(mem_ctx, nir, &vp->program, + &prog_data.base.base); + } + + if (key->nr_userclip_plane_consts > 0) { + brw_nir_lower_legacy_clipping(nir, key->nr_userclip_plane_consts, + &prog_data.base.base); + } + + uint64_t outputs_written = + brw_vs_outputs_written(brw, key, nir->info.outputs_written); + + brw_compute_vue_map(devinfo, &prog_data.base.vue_map, outputs_written, - prog ? prog->SeparateShader : false); + nir->info.separate_shader); if (0) { - _mesa_fprint_program_opt(stderr, &vp->program.Base, PROG_PRINT_DEBUG, - true); + _mesa_fprint_program_opt(stderr, &vp->program, PROG_PRINT_DEBUG, true); } if (unlikely(brw->perf_debug)) { start_busy = (brw->batch.last_bo && - drm_intel_bo_busy(brw->batch.last_bo)); + brw_bo_busy(brw->batch.last_bo)); start_time = get_time(); } if (unlikely(INTEL_DEBUG & DEBUG_VS)) { - brw_dump_ir("vertex", prog, vs ? &vs->base : NULL, &vp->program.Base); - - fprintf(stderr, "VS Output "); - brw_print_vue_map(stderr, &prog_data.base.vue_map); + if (vp->program.is_arb_asm) + brw_dump_arb_asm("vertex", &vp->program); } int st_index = -1; - if (INTEL_DEBUG & DEBUG_SHADER_TIME) - st_index = brw_get_shader_time_index(brw, prog, &vp->program.Base, ST_VS); + if (INTEL_DEBUG & DEBUG_SHADER_TIME) { + st_index = brw_get_shader_time_index(brw, &vp->program, ST_VS, + !vp->program.is_arb_asm); + } /* Emit GEN4 code. */ char *error_str; - program = brw_compile_vs(compiler, brw, mem_ctx, key, - &prog_data, vp->program.Base.nir, - brw_select_clip_planes(&brw->ctx), - !_mesa_is_gles3(&brw->ctx), - st_index, &program_size, &error_str); + program = brw_compile_vs(compiler, brw, mem_ctx, key, &prog_data, + nir, st_index, NULL, &error_str); if (program == NULL) { - if (prog) { - prog->LinkStatus = false; - ralloc_strcat(&prog->InfoLog, error_str); + if (!vp->program.is_arb_asm) { + vp->program.sh.data->LinkStatus = LINKING_FAILURE; + ralloc_strcat(&vp->program.sh.data->InfoLog, error_str); } _mesa_problem(NULL, "Failed to compile vertex shader: %s\n", error_str); @@ -192,90 +199,37 @@ brw_codegen_vs_prog(struct brw_context *brw, return false; } - if (unlikely(brw->perf_debug) && vs) { - if (vs->compiled_once) { - brw_vs_debug_recompile(brw, prog, key); + if (unlikely(brw->perf_debug)) { + if (vp->compiled_once) { + brw_debug_recompile(brw, MESA_SHADER_VERTEX, vp->program.Id, + &key->base); } - if (start_busy && !drm_intel_bo_busy(brw->batch.last_bo)) { + if (start_busy && !brw_bo_busy(brw->batch.last_bo)) { perf_debug("VS compile took %.03f ms and stalled the GPU\n", (get_time() - start_time) * 1000); } - vs->compiled_once = true; + vp->compiled_once = true; } /* Scratch space is used for register spilling */ - if (prog_data.base.base.total_scratch) { - brw_get_scratch_bo(brw, &brw->vs.base.scratch_bo, - prog_data.base.base.total_scratch * - brw->max_vs_threads); - } + brw_alloc_stage_scratch(brw, &brw->vs.base, + prog_data.base.base.total_scratch); + /* The param and pull_param arrays will be freed by the shader cache. */ + ralloc_steal(NULL, prog_data.base.base.param); + ralloc_steal(NULL, prog_data.base.base.pull_param); brw_upload_cache(&brw->cache, BRW_CACHE_VS_PROG, - key, sizeof(struct brw_vs_prog_key), - program, program_size, - &prog_data, sizeof(prog_data), - &brw->vs.base.prog_offset, &brw->vs.prog_data); + key, sizeof(struct brw_vs_prog_key), + program, prog_data.base.base.program_size, + &prog_data, sizeof(prog_data), + &brw->vs.base.prog_offset, &brw->vs.base.prog_data); ralloc_free(mem_ctx); return true; } -void -brw_vs_debug_recompile(struct brw_context *brw, - struct gl_shader_program *prog, - const struct brw_vs_prog_key *key) -{ - struct brw_cache_item *c = NULL; - const struct brw_vs_prog_key *old_key = NULL; - bool found = false; - - perf_debug("Recompiling vertex shader for program %d\n", prog->Name); - - for (unsigned int i = 0; i < brw->cache.size; i++) { - for (c = brw->cache.items[i]; c; c = c->next) { - if (c->cache_id == BRW_CACHE_VS_PROG) { - old_key = c->key; - - if (old_key->program_string_id == key->program_string_id) - break; - } - } - if (c) - break; - } - - if (!c) { - perf_debug(" Didn't find previous compile in the shader cache for " - "debug\n"); - return; - } - - for (unsigned int i = 0; i < VERT_ATTRIB_MAX; i++) { - found |= key_debug(brw, "Vertex attrib w/a flags", - old_key->gl_attrib_wa_flags[i], - key->gl_attrib_wa_flags[i]); - } - - found |= key_debug(brw, "legacy user clipping", - old_key->nr_userclip_plane_consts, - key->nr_userclip_plane_consts); - - found |= key_debug(brw, "copy edgeflag", - old_key->copy_edgeflag, key->copy_edgeflag); - found |= key_debug(brw, "PointCoord replace", - old_key->point_coord_replace, key->point_coord_replace); - found |= key_debug(brw, "vertex color clamping", - old_key->clamp_vertex_color, key->clamp_vertex_color); - - found |= brw_debug_recompile_sampler_key(brw, &old_key->tex, &key->tex); - - if (!found) { - perf_debug(" Something else\n"); - } -} - static bool -brw_vs_state_dirty(struct brw_context *brw) +brw_vs_state_dirty(const struct brw_context *brw) { return brw_state_dirty(brw, _NEW_BUFFERS | @@ -288,113 +242,120 @@ brw_vs_state_dirty(struct brw_context *brw) BRW_NEW_VS_ATTRIB_WORKAROUNDS); } -static void +void brw_vs_populate_key(struct brw_context *brw, struct brw_vs_prog_key *key) { struct gl_context *ctx = &brw->ctx; /* BRW_NEW_VERTEX_PROGRAM */ - struct brw_vertex_program *vp = - (struct brw_vertex_program *)brw->vertex_program; - struct gl_program *prog = (struct gl_program *) brw->vertex_program; - int i; + struct gl_program *prog = brw->programs[MESA_SHADER_VERTEX]; + struct brw_program *vp = (struct brw_program *) prog; + const struct gen_device_info *devinfo = &brw->screen->devinfo; memset(key, 0, sizeof(*key)); /* Just upload the program verbatim for now. Always send it all * the inputs it asks for, whether they are varying or not. */ - key->program_string_id = vp->id; + + /* _NEW_TEXTURE */ + brw_populate_base_prog_key(ctx, vp, &key->base); if (ctx->Transform.ClipPlanesEnabled != 0 && - (ctx->API == API_OPENGL_COMPAT || - ctx->API == API_OPENGLES) && - vp->program.Base.ClipDistanceArraySize == 0) { + (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) && + vp->program.info.clip_distance_array_size == 0) { key->nr_userclip_plane_consts = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; } - /* _NEW_POLYGON */ - if (brw->gen < 6) { + if (devinfo->gen < 6) { + /* _NEW_POLYGON */ key->copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); + + /* _NEW_POINT */ + if (ctx->Point.PointSprite) { + key->point_coord_replace = ctx->Point.CoordReplace & 0xff; + } } - if (prog->OutputsWritten & (VARYING_BIT_COL0 | VARYING_BIT_COL1 | - VARYING_BIT_BFC0 | VARYING_BIT_BFC1)) { + if (prog->info.outputs_written & + (VARYING_BIT_COL0 | VARYING_BIT_COL1 | VARYING_BIT_BFC0 | + VARYING_BIT_BFC1)) { /* _NEW_LIGHT | _NEW_BUFFERS */ key->clamp_vertex_color = ctx->Light._ClampVertexColor; } - /* _NEW_POINT */ - if (brw->gen < 6 && ctx->Point.PointSprite) { - for (i = 0; i < 8; i++) { - if (ctx->Point.CoordReplace[i]) - key->point_coord_replace |= (1 << i); - } - } - - /* _NEW_TEXTURE */ - brw_populate_sampler_prog_key_data(ctx, prog, brw->vs.base.sampler_count, - &key->tex); - /* BRW_NEW_VS_ATTRIB_WORKAROUNDS */ - memcpy(key->gl_attrib_wa_flags, brw->vb.attrib_wa_flags, - sizeof(brw->vb.attrib_wa_flags)); + if (devinfo->gen < 8 && !devinfo->is_haswell) { + memcpy(key->gl_attrib_wa_flags, brw->vb.attrib_wa_flags, + sizeof(brw->vb.attrib_wa_flags)); + } } void brw_upload_vs_prog(struct brw_context *brw) { - struct gl_context *ctx = &brw->ctx; - struct gl_shader_program **current = ctx->_Shader->CurrentProgram; struct brw_vs_prog_key key; /* BRW_NEW_VERTEX_PROGRAM */ - struct brw_vertex_program *vp = - (struct brw_vertex_program *)brw->vertex_program; + struct brw_program *vp = + (struct brw_program *) brw->programs[MESA_SHADER_VERTEX]; if (!brw_vs_state_dirty(brw)) return; brw_vs_populate_key(brw, &key); - if (!brw_search_cache(&brw->cache, BRW_CACHE_VS_PROG, - &key, sizeof(key), - &brw->vs.base.prog_offset, &brw->vs.prog_data)) { - bool success = brw_codegen_vs_prog(brw, current[MESA_SHADER_VERTEX], - vp, &key); - (void) success; - assert(success); - } - brw->vs.base.prog_data = &brw->vs.prog_data->base.base; + if (brw_search_cache(&brw->cache, BRW_CACHE_VS_PROG, &key, sizeof(key), + &brw->vs.base.prog_offset, &brw->vs.base.prog_data, + true)) + return; + + if (brw_disk_cache_upload_program(brw, MESA_SHADER_VERTEX)) + return; + + vp = (struct brw_program *) brw->programs[MESA_SHADER_VERTEX]; + vp->id = key.base.program_string_id; + + ASSERTED bool success = brw_codegen_vs_prog(brw, vp, &key); + assert(success); +} + +void +brw_vs_populate_default_key(const struct brw_compiler *compiler, + struct brw_vs_prog_key *key, + struct gl_program *prog) +{ + const struct gen_device_info *devinfo = compiler->devinfo; + struct brw_program *bvp = brw_program(prog); + + memset(key, 0, sizeof(*key)); + + brw_populate_default_base_prog_key(devinfo, bvp, &key->base); + + key->clamp_vertex_color = + (prog->info.outputs_written & + (VARYING_BIT_COL0 | VARYING_BIT_COL1 | VARYING_BIT_BFC0 | + VARYING_BIT_BFC1)); } bool -brw_vs_precompile(struct gl_context *ctx, - struct gl_shader_program *shader_prog, - struct gl_program *prog) +brw_vs_precompile(struct gl_context *ctx, struct gl_program *prog) { struct brw_context *brw = brw_context(ctx); struct brw_vs_prog_key key; uint32_t old_prog_offset = brw->vs.base.prog_offset; - struct brw_vs_prog_data *old_prog_data = brw->vs.prog_data; + struct brw_stage_prog_data *old_prog_data = brw->vs.base.prog_data; bool success; - struct gl_vertex_program *vp = (struct gl_vertex_program *) prog; - struct brw_vertex_program *bvp = brw_vertex_program(vp); - - memset(&key, 0, sizeof(key)); + struct brw_program *bvp = brw_program(prog); - brw_setup_tex_for_precompile(brw, &key.tex, prog); - key.program_string_id = bvp->id; - key.clamp_vertex_color = - (prog->OutputsWritten & (VARYING_BIT_COL0 | VARYING_BIT_COL1 | - VARYING_BIT_BFC0 | VARYING_BIT_BFC1)); + brw_vs_populate_default_key(brw->screen->compiler, &key, prog); - success = brw_codegen_vs_prog(brw, shader_prog, bvp, &key); + success = brw_codegen_vs_prog(brw, bvp, &key); brw->vs.base.prog_offset = old_prog_offset; - brw->vs.prog_data = old_prog_data; + brw->vs.base.prog_data = old_prog_data; return success; }