+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);
+
+ 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, vp->program.nir, &vp->program,
+ &prog_data.base.base,
+ compiler->scalar_stage[MESA_SHADER_VERTEX]);
+ brw_nir_analyze_ubo_ranges(compiler, vp->program.nir,
+ prog_data.base.base.ubo_ranges);
+ } else {
+ brw_nir_setup_arb_uniforms(mem_ctx, vp->program.nir, &vp->program,
+ &prog_data.base.base);
+ }
+
+ uint64_t outputs_written =
+ brw_vs_outputs_written(brw, key, vp->program.nir->info.outputs_written);
+
+ brw_compute_vue_map(devinfo,
+ &prog_data.base.vue_map, outputs_written,
+ vp->program.nir->info.separate_shader);
+
+ if (0) {
+ _mesa_fprint_program_opt(stderr, &vp->program, PROG_PRINT_DEBUG, true);
+ }
+
+ if (unlikely(brw->perf_debug)) {
+ start_busy = (brw->batch.last_bo &&
+ brw_bo_busy(brw->batch.last_bo));
+ start_time = get_time();
+ }
+
+ if (unlikely(INTEL_DEBUG & DEBUG_VS)) {
+ 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, &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.nir,
+ st_index, &error_str);
+ if (program == NULL) {
+ 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);
+
+ ralloc_free(mem_ctx);
+ return false;
+ }
+
+ if (unlikely(brw->perf_debug)) {
+ if (vp->compiled_once) {
+ brw_vs_debug_recompile(brw, &vp->program, key);
+ }
+ 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);
+ }
+ vp->compiled_once = true;
+ }
+
+ /* Scratch space is used for register spilling */
+ 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, 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;
+}
+
+static bool
+brw_vs_state_dirty(const struct brw_context *brw)