xref: /aosp_15_r20/external/mesa3d/src/intel/compiler/brw_compile_tes.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2010 Intel Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "brw_cfg.h"
7 #include "brw_eu.h"
8 #include "brw_fs.h"
9 #include "brw_nir.h"
10 #include "brw_private.h"
11 #include "dev/intel_debug.h"
12 #include "util/macros.h"
13 
14 static void
brw_assign_tes_urb_setup(fs_visitor & s)15 brw_assign_tes_urb_setup(fs_visitor &s)
16 {
17    assert(s.stage == MESA_SHADER_TESS_EVAL);
18 
19    struct brw_vue_prog_data *vue_prog_data = brw_vue_prog_data(s.prog_data);
20 
21    s.first_non_payload_grf += 8 * vue_prog_data->urb_read_length;
22 
23    /* Rewrite all ATTR file references to HW_REGs. */
24    foreach_block_and_inst(block, fs_inst, inst, s.cfg) {
25       s.convert_attr_sources_to_hw_regs(inst);
26    }
27 }
28 
29 static bool
run_tes(fs_visitor & s)30 run_tes(fs_visitor &s)
31 {
32    assert(s.stage == MESA_SHADER_TESS_EVAL);
33 
34    s.payload_ = new tes_thread_payload(s);
35 
36    nir_to_brw(&s);
37 
38    if (s.failed)
39       return false;
40 
41    s.emit_urb_writes();
42 
43    brw_calculate_cfg(s);
44 
45    brw_fs_optimize(s);
46 
47    s.assign_curb_setup();
48    brw_assign_tes_urb_setup(s);
49 
50    brw_fs_lower_3src_null_dest(s);
51    brw_fs_workaround_memory_fence_before_eot(s);
52    brw_fs_workaround_emit_dummy_mov_instruction(s);
53 
54    brw_allocate_registers(s, true /* allow_spilling */);
55 
56    return !s.failed;
57 }
58 
59 const unsigned *
brw_compile_tes(const struct brw_compiler * compiler,brw_compile_tes_params * params)60 brw_compile_tes(const struct brw_compiler *compiler,
61                 brw_compile_tes_params *params)
62 {
63    const struct intel_device_info *devinfo = compiler->devinfo;
64    nir_shader *nir = params->base.nir;
65    const struct brw_tes_prog_key *key = params->key;
66    const struct intel_vue_map *input_vue_map = params->input_vue_map;
67    struct brw_tes_prog_data *prog_data = params->prog_data;
68 
69    const bool debug_enabled = brw_should_print_shader(nir, DEBUG_TES);
70 
71    prog_data->base.base.stage = MESA_SHADER_TESS_EVAL;
72    prog_data->base.base.ray_queries = nir->info.ray_queries;
73 
74    nir->info.inputs_read = key->inputs_read;
75    nir->info.patch_inputs_read = key->patch_inputs_read;
76 
77    brw_nir_apply_key(nir, compiler, &key->base,
78                      brw_geometry_stage_dispatch_width(compiler->devinfo));
79    brw_nir_lower_tes_inputs(nir, input_vue_map);
80    brw_nir_lower_vue_outputs(nir);
81    brw_postprocess_nir(nir, compiler, debug_enabled,
82                        key->base.robust_flags);
83 
84    brw_compute_vue_map(devinfo, &prog_data->base.vue_map,
85                        nir->info.outputs_written,
86                        nir->info.separate_shader, 1);
87 
88    unsigned output_size_bytes = prog_data->base.vue_map.num_slots * 4 * 4;
89 
90    assert(output_size_bytes >= 1);
91    if (output_size_bytes > GFX7_MAX_DS_URB_ENTRY_SIZE_BYTES) {
92       params->base.error_str = ralloc_strdup(params->base.mem_ctx,
93                                              "DS outputs exceed maximum size");
94       return NULL;
95    }
96 
97    prog_data->base.clip_distance_mask =
98       ((1 << nir->info.clip_distance_array_size) - 1);
99    prog_data->base.cull_distance_mask =
100       ((1 << nir->info.cull_distance_array_size) - 1) <<
101       nir->info.clip_distance_array_size;
102 
103    prog_data->include_primitive_id =
104       BITSET_TEST(nir->info.system_values_read, SYSTEM_VALUE_PRIMITIVE_ID);
105 
106    /* URB entry sizes are stored as a multiple of 64 bytes. */
107    prog_data->base.urb_entry_size = ALIGN(output_size_bytes, 64) / 64;
108 
109    prog_data->base.urb_read_length = 0;
110 
111    STATIC_ASSERT(INTEL_TESS_PARTITIONING_INTEGER == TESS_SPACING_EQUAL - 1);
112    STATIC_ASSERT(INTEL_TESS_PARTITIONING_ODD_FRACTIONAL ==
113                  TESS_SPACING_FRACTIONAL_ODD - 1);
114    STATIC_ASSERT(INTEL_TESS_PARTITIONING_EVEN_FRACTIONAL ==
115                  TESS_SPACING_FRACTIONAL_EVEN - 1);
116 
117    prog_data->partitioning =
118       (enum intel_tess_partitioning) (nir->info.tess.spacing - 1);
119 
120    switch (nir->info.tess._primitive_mode) {
121    case TESS_PRIMITIVE_QUADS:
122       prog_data->domain = INTEL_TESS_DOMAIN_QUAD;
123       break;
124    case TESS_PRIMITIVE_TRIANGLES:
125       prog_data->domain = INTEL_TESS_DOMAIN_TRI;
126       break;
127    case TESS_PRIMITIVE_ISOLINES:
128       prog_data->domain = INTEL_TESS_DOMAIN_ISOLINE;
129       break;
130    default:
131       unreachable("invalid domain shader primitive mode");
132    }
133 
134    if (nir->info.tess.point_mode) {
135       prog_data->output_topology = INTEL_TESS_OUTPUT_TOPOLOGY_POINT;
136    } else if (nir->info.tess._primitive_mode == TESS_PRIMITIVE_ISOLINES) {
137       prog_data->output_topology = INTEL_TESS_OUTPUT_TOPOLOGY_LINE;
138    } else {
139       /* Hardware winding order is backwards from OpenGL */
140       prog_data->output_topology =
141          nir->info.tess.ccw ? INTEL_TESS_OUTPUT_TOPOLOGY_TRI_CW
142                              : INTEL_TESS_OUTPUT_TOPOLOGY_TRI_CCW;
143    }
144 
145    if (unlikely(debug_enabled)) {
146       fprintf(stderr, "TES Input ");
147       brw_print_vue_map(stderr, input_vue_map, MESA_SHADER_TESS_EVAL);
148       fprintf(stderr, "TES Output ");
149       brw_print_vue_map(stderr, &prog_data->base.vue_map,
150                         MESA_SHADER_TESS_EVAL);
151    }
152 
153    const unsigned dispatch_width = devinfo->ver >= 20 ? 16 : 8;
154    fs_visitor v(compiler, &params->base, &key->base,
155                 &prog_data->base.base, nir, dispatch_width,
156                 params->base.stats != NULL, debug_enabled);
157    if (!run_tes(v)) {
158       params->base.error_str =
159          ralloc_strdup(params->base.mem_ctx, v.fail_msg);
160       return NULL;
161    }
162 
163    assert(v.payload().num_regs % reg_unit(devinfo) == 0);
164    prog_data->base.base.dispatch_grf_start_reg = v.payload().num_regs / reg_unit(devinfo);
165 
166    prog_data->base.dispatch_mode = INTEL_DISPATCH_MODE_SIMD8;
167 
168    fs_generator g(compiler, &params->base,
169                   &prog_data->base.base, MESA_SHADER_TESS_EVAL);
170    if (unlikely(debug_enabled)) {
171       g.enable_debug(ralloc_asprintf(params->base.mem_ctx,
172                                      "%s tessellation evaluation shader %s",
173                                      nir->info.label ? nir->info.label
174                                                      : "unnamed",
175                                      nir->info.name));
176    }
177 
178    g.generate_code(v.cfg, dispatch_width, v.shader_stats,
179                    v.performance_analysis.require(), params->base.stats);
180 
181    g.add_const_data(nir->constant_data, nir->constant_data_size);
182 
183    return g.get_assembly();
184 }
185 
186