+const unsigned *
+blorp_compile_vs(struct blorp_context *blorp, void *mem_ctx,
+ struct nir_shader *nir,
+ struct brw_vs_prog_data *vs_prog_data)
+{
+ const struct brw_compiler *compiler = blorp->compiler;
+
+ nir->options =
+ compiler->glsl_compiler_options[MESA_SHADER_VERTEX].NirOptions;
+
+ brw_preprocess_nir(compiler, nir, NULL);
+ nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
+
+ vs_prog_data->inputs_read = nir->info.inputs_read;
+
+ brw_compute_vue_map(compiler->devinfo,
+ &vs_prog_data->base.vue_map,
+ nir->info.outputs_written,
+ nir->info.separate_shader,
+ 1);
+
+ struct brw_vs_prog_key vs_key = { 0, };
+
+ const unsigned *program =
+ brw_compile_vs(compiler, blorp->driver_ctx, mem_ctx,
+ &vs_key, vs_prog_data, nir, -1, NULL, NULL);
+
+ return program;
+}
+
+struct blorp_sf_key {
+ enum blorp_shader_type shader_type; /* Must be BLORP_SHADER_TYPE_GEN4_SF */
+
+ struct brw_sf_prog_key key;
+};
+
+bool
+blorp_ensure_sf_program(struct blorp_batch *batch,
+ struct blorp_params *params)
+{
+ struct blorp_context *blorp = batch->blorp;
+ const struct brw_wm_prog_data *wm_prog_data = params->wm_prog_data;
+ assert(params->wm_prog_data);
+
+ /* Gen6+ doesn't need a strips and fans program */
+ if (blorp->compiler->devinfo->gen >= 6)
+ return true;
+
+ struct blorp_sf_key key = {
+ .shader_type = BLORP_SHADER_TYPE_GEN4_SF,
+ };
+
+ /* Everything gets compacted in vertex setup, so we just need a
+ * pass-through for the correct number of input varyings.
+ */
+ const uint64_t slots_valid = VARYING_BIT_POS |
+ ((1ull << wm_prog_data->num_varying_inputs) - 1) << VARYING_SLOT_VAR0;
+
+ key.key.attrs = slots_valid;
+ key.key.primitive = BRW_SF_PRIM_TRIANGLES;
+ key.key.contains_flat_varying = wm_prog_data->contains_flat_varying;
+
+ STATIC_ASSERT(sizeof(key.key.interp_mode) ==
+ sizeof(wm_prog_data->interp_mode));
+ memcpy(key.key.interp_mode, wm_prog_data->interp_mode,
+ sizeof(key.key.interp_mode));
+
+ if (blorp->lookup_shader(batch, &key, sizeof(key),
+ ¶ms->sf_prog_kernel, ¶ms->sf_prog_data))
+ return true;
+
+ void *mem_ctx = ralloc_context(NULL);
+
+ const unsigned *program;
+ unsigned program_size;
+
+ struct brw_vue_map vue_map;
+ brw_compute_vue_map(blorp->compiler->devinfo, &vue_map, slots_valid, false, 1);
+
+ struct brw_sf_prog_data prog_data_tmp;
+ program = brw_compile_sf(blorp->compiler, mem_ctx, &key.key,
+ &prog_data_tmp, &vue_map, &program_size);
+
+ bool result =
+ blorp->upload_shader(batch, MESA_SHADER_NONE,
+ &key, sizeof(key), program, program_size,
+ (void *)&prog_data_tmp, sizeof(prog_data_tmp),
+ ¶ms->sf_prog_kernel, ¶ms->sf_prog_data);
+
+ ralloc_free(mem_ctx);
+
+ return result;
+}
+