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