freedreno/ir3: remove indirect input load
[mesa.git] / src / freedreno / ir3 / ir3_nir_lower_tess.c
index 4c06b458665f1484b5668b37722c3bb76e77c211..44b2921dcb7b97742ebc322442444f1968bed970 100644 (file)
@@ -41,7 +41,11 @@ struct state {
        nir_variable *vertex_flags_out;
 
        struct exec_list old_outputs;
+       struct exec_list new_outputs;
        struct exec_list emit_outputs;
+
+       /* tess ctrl shader on a650 gets the local primitive id at different bits: */
+       unsigned local_primitive_id_start;
 };
 
 static nir_ssa_def *
@@ -66,13 +70,13 @@ build_vertex_id(nir_builder *b, struct state *state)
 static nir_ssa_def *
 build_local_primitive_id(nir_builder *b, struct state *state)
 {
-       return bitfield_extract(b, state->header, 0, 63);
+       return bitfield_extract(b, state->header, state->local_primitive_id_start, 63);
 }
 
 static nir_variable *
-get_var(struct exec_list *list, int driver_location)
+get_var(nir_shader *shader, nir_variable_mode mode, int driver_location)
 {
-       nir_foreach_variable (v, list) {
+       nir_foreach_variable_with_modes (v, shader, mode) {
                if (v->data.driver_location == driver_location) {
                        return v;
                }
@@ -149,9 +153,9 @@ replace_intrinsic(nir_builder *b, nir_intrinsic_instr *intr,
 }
 
 static void
-build_primitive_map(nir_shader *shader, struct primitive_map *map, struct exec_list *list)
+build_primitive_map(nir_shader *shader, nir_variable_mode mode, struct primitive_map *map)
 {
-       nir_foreach_variable (var, list) {
+       nir_foreach_variable_with_modes (var, shader, mode) {
                switch (var->data.location) {
                case VARYING_SLOT_TESS_LEVEL_OUTER:
                case VARYING_SLOT_TESS_LEVEL_INNER:
@@ -169,7 +173,7 @@ build_primitive_map(nir_shader *shader, struct primitive_map *map, struct exec_l
        for (uint32_t i = 0; i < ARRAY_SIZE(map->size); i++) {
                if (map->size[i] == 0)
                                continue;
-               nir_variable *var = get_var(list, i);
+               nir_variable *var = get_var(shader, mode, i);
                map->loc[i] = loc;
                loc += map->size[i];
 
@@ -236,7 +240,7 @@ ir3_nir_lower_to_explicit_output(nir_shader *shader, struct ir3_shader_variant *
 {
        struct state state = { };
 
-       build_primitive_map(shader, &state.map, &shader->outputs);
+       build_primitive_map(shader, nir_var_shader_out, &state.map);
        memcpy(v->output_loc, state.map.loc, sizeof(v->output_loc));
 
        nir_function_impl *impl = nir_shader_get_entrypoint(shader);
@@ -301,10 +305,16 @@ lower_block_to_explicit_input(nir_block *block, nir_builder *b, struct state *st
 }
 
 void
-ir3_nir_lower_to_explicit_input(nir_shader *shader)
+ir3_nir_lower_to_explicit_input(nir_shader *shader, struct ir3_compiler *compiler)
 {
        struct state state = { };
 
+       /* when using stl/ldl (instead of stlw/ldlw) for linking VS and HS,
+        * HS uses a different primitive id, which starts at bit 16 in the header
+        */
+       if (shader->info.stage == MESA_SHADER_TESS_CTRL && compiler->tess_use_shared)
+               state.local_primitive_id_start = 16;
+
        nir_function_impl *impl = nir_shader_get_entrypoint(shader);
        assert(impl);
 
@@ -434,7 +444,7 @@ lower_tess_ctrl_block(nir_block *block, nir_builder *b, struct state *state)
                        b->cursor = nir_before_instr(&intr->instr);
 
                        nir_ssa_def *address = nir_load_tess_param_base_ir3(b);
-                       nir_variable *var = get_var(&b->shader->outputs, nir_intrinsic_base(intr));
+                       nir_variable *var = get_var(b->shader, nir_var_shader_out, nir_intrinsic_base(intr));
                        nir_ssa_def *offset = build_per_vertex_offset(b, state,
                                        intr->src[0].ssa, intr->src[1].ssa, var);
 
@@ -452,7 +462,7 @@ lower_tess_ctrl_block(nir_block *block, nir_builder *b, struct state *state)
 
                        nir_ssa_def *value = intr->src[0].ssa;
                        nir_ssa_def *address = nir_load_tess_param_base_ir3(b);
-                       nir_variable *var = get_var(&b->shader->outputs, nir_intrinsic_base(intr));
+                       nir_variable *var = get_var(b->shader, nir_var_shader_out, nir_intrinsic_base(intr));
                        nir_ssa_def *offset = build_per_vertex_offset(b, state,
                                        intr->src[1].ssa, intr->src[2].ssa, var);
 
@@ -465,7 +475,7 @@ lower_tess_ctrl_block(nir_block *block, nir_builder *b, struct state *state)
                case nir_intrinsic_load_output: {
                        // src[] = { offset }.
 
-                       nir_variable *var = get_var(&b->shader->outputs, nir_intrinsic_base(intr));
+                       nir_variable *var = get_var(b->shader, nir_var_shader_out, nir_intrinsic_base(intr));
 
                        b->cursor = nir_before_instr(&intr->instr);
 
@@ -494,7 +504,7 @@ lower_tess_ctrl_block(nir_block *block, nir_builder *b, struct state *state)
 
                        /* write patch output to bo */
 
-                       nir_variable *var = get_var(&b->shader->outputs, nir_intrinsic_base(intr));
+                       nir_variable *var = get_var(b->shader, nir_var_shader_out, nir_intrinsic_base(intr));
 
                        b->cursor = nir_before_instr(&intr->instr);
 
@@ -570,7 +580,7 @@ ir3_nir_lower_tess_ctrl(nir_shader *shader, struct ir3_shader_variant *v,
                nir_print_shader(shader, stderr);
        }
 
-       build_primitive_map(shader, &state.map, &shader->outputs);
+       build_primitive_map(shader, nir_var_shader_out, &state.map);
        memcpy(v->output_loc, state.map.loc, sizeof(v->output_loc));
        v->output_size = state.map.stride;
 
@@ -662,7 +672,7 @@ lower_tess_eval_block(nir_block *block, nir_builder *b, struct state *state)
                        b->cursor = nir_before_instr(&intr->instr);
 
                        nir_ssa_def *address = nir_load_tess_param_base_ir3(b);
-                       nir_variable *var = get_var(&b->shader->inputs, nir_intrinsic_base(intr));
+                       nir_variable *var = get_var(b->shader, nir_var_shader_in, nir_intrinsic_base(intr));
                        nir_ssa_def *offset = build_per_vertex_offset(b, state,
                                        intr->src[0].ssa, intr->src[1].ssa, var);
 
@@ -673,7 +683,7 @@ lower_tess_eval_block(nir_block *block, nir_builder *b, struct state *state)
                case nir_intrinsic_load_input: {
                        // src[] = { offset }.
 
-                       nir_variable *var = get_var(&b->shader->inputs, nir_intrinsic_base(intr));
+                       nir_variable *var = get_var(b->shader, nir_var_shader_in, nir_intrinsic_base(intr));
 
                        debug_assert(var->data.patch);
 
@@ -719,7 +729,7 @@ ir3_nir_lower_tess_eval(nir_shader *shader, unsigned topology)
        }
 
        /* Build map of inputs so we have the sizes. */
-       build_primitive_map(shader, &state.map, &shader->inputs);
+       build_primitive_map(shader, nir_var_shader_in, &state.map);
 
        nir_function_impl *impl = nir_shader_get_entrypoint(shader);
        assert(impl);
@@ -794,7 +804,7 @@ ir3_nir_lower_gs(nir_shader *shader)
                nir_print_shader(shader, stderr);
        }
 
-       build_primitive_map(shader, &state.map, &shader->inputs);
+       build_primitive_map(shader, nir_var_shader_in, &state.map);
 
        /* Create an output var for vertex_flags. This will be shadowed below,
         * same way regular outputs get shadowed, and this variable will become a
@@ -821,14 +831,19 @@ ir3_nir_lower_gs(nir_shader *shader)
         * we copy the emit_outputs to the real outputs, so that we get
         * store_output in uniform control flow.
         */
-       exec_list_move_nodes_to(&shader->outputs, &state.old_outputs);
+       exec_list_make_empty(&state.old_outputs);
+       nir_foreach_shader_out_variable_safe(var, shader) {
+               exec_node_remove(&var->node);
+               exec_list_push_tail(&state.old_outputs, &var->node);
+       }
+       exec_list_make_empty(&state.new_outputs);
        exec_list_make_empty(&state.emit_outputs);
-       nir_foreach_variable(var, &state.old_outputs) {
+       nir_foreach_variable_in_list(var, &state.old_outputs) {
                /* Create a new output var by cloning the original output var and
                 * stealing the name.
                 */
                nir_variable *output = nir_variable_clone(var, shader);
-               exec_list_push_tail(&shader->outputs, &output->node);
+               exec_list_push_tail(&state.new_outputs, &output->node);
 
                /* Rewrite the original output to be a shadow variable. */
                var->name = ralloc_asprintf(var, "%s@gs-temp", output->name);
@@ -874,15 +889,16 @@ ir3_nir_lower_gs(nir_shader *shader)
 
                nir_builder_instr_insert(&b, &discard_if->instr);
 
-               foreach_two_lists(dest_node, &shader->outputs, src_node, &state.emit_outputs) {
+               foreach_two_lists(dest_node, &state.new_outputs, src_node, &state.emit_outputs) {
                        nir_variable *dest = exec_node_data(nir_variable, dest_node, node);
                        nir_variable *src = exec_node_data(nir_variable, src_node, node);
                        nir_copy_var(&b, dest, src);
                }
        }
 
-       exec_list_append(&shader->globals, &state.old_outputs);
-       exec_list_append(&shader->globals, &state.emit_outputs);
+       exec_list_append(&shader->variables, &state.old_outputs);
+       exec_list_append(&shader->variables, &state.emit_outputs);
+       exec_list_append(&shader->variables, &state.new_outputs);
 
        nir_metadata_preserve(impl, 0);
 
@@ -919,8 +935,8 @@ ir3_link_geometry_stages(const struct ir3_shader_variant *producer,
                unreachable("bad shader stage");
        }
 
-       nir_foreach_variable(in_var, &consumer->shader->nir->inputs) {
-               nir_foreach_variable(out_var, &producer->shader->nir->outputs) {
+       nir_foreach_shader_in_variable(in_var, consumer->shader->nir) {
+               nir_foreach_shader_out_variable(out_var, producer->shader->nir) {
                        if (in_var->data.location == out_var->data.location) {
                                locs[in_var->data.driver_location] =
                                        producer->output_loc[out_var->data.driver_location] * factor;