-static void
-tu6_emit_program(struct tu_cs *cs,
- const struct tu_pipeline_builder *builder,
- const struct tu_bo *binary_bo,
- bool binning_pass,
- struct tu_streamout_state *tf)
-{
- static const struct ir3_shader_variant dummy_variant = {
- .type = MESA_SHADER_NONE
- };
- assert(builder->shaders[MESA_SHADER_VERTEX]);
- const struct ir3_shader_variant *vs =
- &builder->shaders[MESA_SHADER_VERTEX]->variants[0];
- const struct ir3_shader_variant *hs =
- builder->shaders[MESA_SHADER_TESS_CTRL]
- ? &builder->shaders[MESA_SHADER_TESS_CTRL]->variants[0]
- : &dummy_variant;
- const struct ir3_shader_variant *ds =
- builder->shaders[MESA_SHADER_TESS_EVAL]
- ? &builder->shaders[MESA_SHADER_TESS_EVAL]->variants[0]
- : &dummy_variant;
- const struct ir3_shader_variant *gs =
- builder->shaders[MESA_SHADER_GEOMETRY]
- ? &builder->shaders[MESA_SHADER_GEOMETRY]->variants[0]
- : &dummy_variant;
- const struct ir3_shader_variant *fs =
- builder->shaders[MESA_SHADER_FRAGMENT]
- ? &builder->shaders[MESA_SHADER_FRAGMENT]->variants[0]
- : &dummy_variant;
- bool has_gs = gs->type != MESA_SHADER_NONE;
-
- if (binning_pass) {
- /* if we have streamout, use full VS in binning pass, as the
- * binning pass VS will have outputs on other than position/psize
- * stripped out:
- */
- if (vs->shader->stream_output.num_outputs == 0)
- vs = &builder->shaders[MESA_SHADER_VERTEX]->variants[1];
- fs = &dummy_variant;
- }
-
- tu6_emit_vs_config(cs, builder->shaders[MESA_SHADER_VERTEX], vs);
- tu6_emit_hs_config(cs, builder->shaders[MESA_SHADER_TESS_CTRL], hs);
- tu6_emit_ds_config(cs, builder->shaders[MESA_SHADER_TESS_EVAL], ds);
- tu6_emit_gs_config(cs, builder->shaders[MESA_SHADER_GEOMETRY], gs);
- tu6_emit_fs_config(cs, builder->shaders[MESA_SHADER_FRAGMENT], fs);
-
- tu6_emit_vs_system_values(cs, vs, gs);
- tu6_emit_vpc(cs, vs, gs, fs, binning_pass, tf);
- tu6_emit_vpc_varying_modes(cs, fs, binning_pass);
- tu6_emit_fs_inputs(cs, fs);
- tu6_emit_fs_outputs(cs, fs, builder->color_attachment_count);
-
- tu6_emit_shader_object(cs, MESA_SHADER_VERTEX, vs, binary_bo,
- binning_pass ? builder->binning_vs_offset : builder->shader_offsets[MESA_SHADER_VERTEX]);
- if (has_gs)
- tu6_emit_shader_object(cs, MESA_SHADER_GEOMETRY, gs, binary_bo,
- builder->shader_offsets[MESA_SHADER_GEOMETRY]);
- tu6_emit_shader_object(cs, MESA_SHADER_FRAGMENT, fs, binary_bo,
- builder->shader_offsets[MESA_SHADER_FRAGMENT]);
-
- tu6_emit_immediates(cs, vs, CP_LOAD_STATE6_GEOM, SB6_VS_SHADER);
- if (has_gs) {
- tu6_emit_immediates(cs, gs, CP_LOAD_STATE6_GEOM, SB6_GS_SHADER);
- tu6_emit_geometry_consts(cs, vs, gs);
- }
- if (!binning_pass)
- tu6_emit_immediates(cs, fs, CP_LOAD_STATE6_FRAG, SB6_FS_SHADER);
+ if (fs) {
+ tu6_emit_fs_inputs(cs, fs);
+ tu6_emit_fs_outputs(cs, fs, builder->color_attachment_count,
+ builder->use_dual_src_blend,
+ builder->render_components,
+ builder->depth_attachment_format == VK_FORMAT_S8_UINT);
+ } else {
+ /* TODO: check if these can be skipped if fs is disabled */
+ struct ir3_shader_variant dummy_variant = {};
+ tu6_emit_fs_inputs(cs, &dummy_variant);
+ tu6_emit_fs_outputs(cs, &dummy_variant, builder->color_attachment_count,
+ builder->use_dual_src_blend,
+ builder->render_components,
+ builder->depth_attachment_format == VK_FORMAT_S8_UINT);
+ }
+
+ if (gs || hs) {
+ uint32_t cps_per_patch = builder->create_info->pTessellationState ?
+ builder->create_info->pTessellationState->patchControlPoints : 0;
+ tu6_emit_geom_tess_consts(cs, vs, hs, ds, gs, cps_per_patch);
+ }