• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 Intel Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "blorp_priv.h"
7 #include "blorp_nir_builder.h"
8 #include "compiler/brw_compiler.h"
9 #include "compiler/brw_nir.h"
10 #include "dev/intel_debug.h"
11 
12 static const nir_shader_compiler_options *
blorp_nir_options_brw(struct blorp_context * blorp,gl_shader_stage stage)13 blorp_nir_options_brw(struct blorp_context *blorp,
14                       gl_shader_stage stage)
15 {
16    const struct brw_compiler *compiler = blorp->compiler->brw;
17    return compiler->nir_options[stage];
18 }
19 
20 static struct blorp_program
blorp_compile_fs_brw(struct blorp_context * blorp,void * mem_ctx,struct nir_shader * nir,bool multisample_fbo,bool is_fast_clear,bool use_repclear)21 blorp_compile_fs_brw(struct blorp_context *blorp, void *mem_ctx,
22                      struct nir_shader *nir,
23                      bool multisample_fbo,
24                      bool is_fast_clear,
25                      bool use_repclear)
26 {
27    const struct brw_compiler *compiler = blorp->compiler->brw;
28 
29    struct brw_wm_prog_data *wm_prog_data = rzalloc(mem_ctx, struct brw_wm_prog_data);
30    wm_prog_data->base.nr_params = 0;
31    wm_prog_data->base.param = NULL;
32 
33    struct brw_nir_compiler_opts opts = {};
34    brw_preprocess_nir(compiler, nir, &opts);
35    nir_remove_dead_variables(nir, nir_var_shader_in, NULL);
36    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
37    if (is_fast_clear || use_repclear)
38       nir->info.subgroup_size = SUBGROUP_SIZE_REQUIRE_16;
39 
40    struct brw_wm_prog_key wm_key;
41    memset(&wm_key, 0, sizeof(wm_key));
42    wm_key.multisample_fbo = multisample_fbo ? INTEL_ALWAYS : INTEL_NEVER;
43    wm_key.nr_color_regions = 1;
44 
45    struct brw_compile_fs_params params = {
46       .base = {
47          .mem_ctx = mem_ctx,
48          .nir = nir,
49          .log_data = blorp->driver_ctx,
50          .debug_flag = DEBUG_BLORP,
51       },
52       .key = &wm_key,
53       .prog_data = wm_prog_data,
54 
55       .use_rep_send = use_repclear,
56       .max_polygons = 1,
57    };
58 
59    const unsigned *kernel = brw_compile_fs(compiler, &params);
60    return (struct blorp_program){
61       .kernel         = kernel,
62       .kernel_size    = wm_prog_data->base.program_size,
63       .prog_data      = wm_prog_data,
64       .prog_data_size = sizeof(*wm_prog_data),
65    };
66 }
67 
68 static struct blorp_program
blorp_compile_vs_brw(struct blorp_context * blorp,void * mem_ctx,struct nir_shader * nir)69 blorp_compile_vs_brw(struct blorp_context *blorp, void *mem_ctx,
70                      struct nir_shader *nir)
71 {
72    const struct brw_compiler *compiler = blorp->compiler->brw;
73 
74    struct brw_nir_compiler_opts opts = {};
75    brw_preprocess_nir(compiler, nir, &opts);
76    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
77 
78    struct brw_vs_prog_data *vs_prog_data = rzalloc(mem_ctx, struct brw_vs_prog_data);
79    vs_prog_data->inputs_read = nir->info.inputs_read;
80 
81    brw_compute_vue_map(compiler->devinfo,
82                        &vs_prog_data->base.vue_map,
83                        nir->info.outputs_written,
84                        nir->info.separate_shader,
85                        1);
86 
87    struct brw_vs_prog_key vs_key = { 0, };
88 
89    struct brw_compile_vs_params params = {
90       .base = {
91          .mem_ctx = mem_ctx,
92          .nir = nir,
93          .log_data = blorp->driver_ctx,
94          .debug_flag = DEBUG_BLORP,
95       },
96       .key = &vs_key,
97       .prog_data = vs_prog_data,
98    };
99 
100    const unsigned *kernel = brw_compile_vs(compiler, &params);
101    return (struct blorp_program) {
102       .kernel         = kernel,
103       .kernel_size    = vs_prog_data->base.base.program_size,
104       .prog_data      = vs_prog_data,
105       .prog_data_size = sizeof(*vs_prog_data),
106    };
107 }
108 
109 static bool
lower_base_workgroup_id(nir_builder * b,nir_intrinsic_instr * intrin,UNUSED void * data)110 lower_base_workgroup_id(nir_builder *b, nir_intrinsic_instr *intrin,
111                         UNUSED void *data)
112 {
113    if (intrin->intrinsic != nir_intrinsic_load_base_workgroup_id)
114       return false;
115 
116    b->cursor = nir_instr_remove(&intrin->instr);
117    nir_def_rewrite_uses(&intrin->def, nir_imm_zero(b, 3, 32));
118    return true;
119 }
120 
121 static struct blorp_program
blorp_compile_cs_brw(struct blorp_context * blorp,void * mem_ctx,struct nir_shader * nir)122 blorp_compile_cs_brw(struct blorp_context *blorp, void *mem_ctx,
123                      struct nir_shader *nir)
124 {
125    const struct brw_compiler *compiler = blorp->compiler->brw;
126 
127    struct brw_nir_compiler_opts opts = {};
128    brw_preprocess_nir(compiler, nir, &opts);
129    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
130 
131    NIR_PASS_V(nir, nir_lower_io, nir_var_uniform, type_size_scalar_bytes,
132               (nir_lower_io_options)0);
133 
134    STATIC_ASSERT(offsetof(struct blorp_wm_inputs, subgroup_id) + 4 ==
135                  sizeof(struct blorp_wm_inputs));
136    nir->num_uniforms = offsetof(struct blorp_wm_inputs, subgroup_id);
137    unsigned nr_params = nir->num_uniforms / 4;
138 
139    struct brw_cs_prog_data *cs_prog_data = rzalloc(mem_ctx, struct brw_cs_prog_data);
140    cs_prog_data->base.nr_params = nr_params;
141    cs_prog_data->base.param = rzalloc_array(NULL, uint32_t, nr_params);
142 
143    NIR_PASS_V(nir, brw_nir_lower_cs_intrinsics, compiler->devinfo,
144               cs_prog_data);
145    NIR_PASS_V(nir, nir_shader_intrinsics_pass, lower_base_workgroup_id,
146               nir_metadata_control_flow, NULL);
147 
148    struct brw_cs_prog_key cs_key;
149    memset(&cs_key, 0, sizeof(cs_key));
150 
151    struct brw_compile_cs_params params = {
152       .base = {
153          .mem_ctx = mem_ctx,
154          .nir = nir,
155          .log_data = blorp->driver_ctx,
156          .debug_flag = DEBUG_BLORP,
157       },
158       .key = &cs_key,
159       .prog_data = cs_prog_data,
160    };
161 
162    const unsigned *kernel = brw_compile_cs(compiler, &params);
163 
164    ralloc_free(cs_prog_data->base.param);
165    cs_prog_data->base.param = NULL;
166 
167    return (struct blorp_program) {
168       .kernel         = kernel,
169       .kernel_size    = cs_prog_data->base.program_size,
170       .prog_data      = cs_prog_data,
171       .prog_data_size = sizeof(*cs_prog_data),
172    };
173 }
174 
175 #pragma pack(push, 1)
176 struct layer_offset_vs_key {
177    struct blorp_base_key base;
178    unsigned num_inputs;
179 };
180 #pragma pack(pop)
181 
182 /* In the case of doing attachment clears, we are using a surface state that
183  * is handed to us so we can't set (and don't even know) the base array layer.
184  * In order to do a layered clear in this scenario, we need some way of adding
185  * the base array layer to the instance id.  Unfortunately, our hardware has
186  * no real concept of "base instance", so we have to do it manually in a
187  * vertex shader.
188  */
189 static bool
blorp_params_get_layer_offset_vs_brw(struct blorp_batch * batch,struct blorp_params * params)190 blorp_params_get_layer_offset_vs_brw(struct blorp_batch *batch,
191                                      struct blorp_params *params)
192 {
193    struct blorp_context *blorp = batch->blorp;
194    struct layer_offset_vs_key blorp_key = {
195       .base = BLORP_BASE_KEY_INIT(BLORP_SHADER_TYPE_LAYER_OFFSET_VS),
196    };
197 
198    struct brw_wm_prog_data *wm_prog_data = params->wm_prog_data;
199    if (wm_prog_data)
200       blorp_key.num_inputs = wm_prog_data->num_varying_inputs;
201 
202    if (blorp->lookup_shader(batch, &blorp_key, sizeof(blorp_key),
203                             &params->vs_prog_kernel, &params->vs_prog_data))
204       return true;
205 
206    void *mem_ctx = ralloc_context(NULL);
207 
208    nir_builder b;
209    blorp_nir_init_shader(&b, blorp, mem_ctx, MESA_SHADER_VERTEX,
210                          blorp_shader_type_to_name(blorp_key.base.shader_type));
211 
212    const struct glsl_type *uvec4_type = glsl_vector_type(GLSL_TYPE_UINT, 4);
213 
214    /* First we deal with the header which has instance and base instance */
215    nir_variable *a_header = nir_variable_create(b.shader, nir_var_shader_in,
216                                                 uvec4_type, "header");
217    a_header->data.location = VERT_ATTRIB_GENERIC0;
218 
219    nir_variable *v_layer = nir_variable_create(b.shader, nir_var_shader_out,
220                                                glsl_int_type(), "layer_id");
221    v_layer->data.location = VARYING_SLOT_LAYER;
222 
223    /* Compute the layer id */
224    nir_def *header = nir_load_var(&b, a_header);
225    nir_def *base_layer = nir_channel(&b, header, 0);
226    nir_def *instance = nir_channel(&b, header, 1);
227    nir_store_var(&b, v_layer, nir_iadd(&b, instance, base_layer), 0x1);
228 
229    /* Then we copy the vertex from the next slot to VARYING_SLOT_POS */
230    nir_variable *a_vertex = nir_variable_create(b.shader, nir_var_shader_in,
231                                                 glsl_vec4_type(), "a_vertex");
232    a_vertex->data.location = VERT_ATTRIB_GENERIC1;
233 
234    nir_variable *v_pos = nir_variable_create(b.shader, nir_var_shader_out,
235                                              glsl_vec4_type(), "v_pos");
236    v_pos->data.location = VARYING_SLOT_POS;
237 
238    nir_copy_var(&b, v_pos, a_vertex);
239 
240    /* Then we copy everything else */
241    for (unsigned i = 0; i < blorp_key.num_inputs; i++) {
242       nir_variable *a_in = nir_variable_create(b.shader, nir_var_shader_in,
243                                                uvec4_type, "input");
244       a_in->data.location = VERT_ATTRIB_GENERIC2 + i;
245 
246       nir_variable *v_out = nir_variable_create(b.shader, nir_var_shader_out,
247                                                 uvec4_type, "output");
248       v_out->data.location = VARYING_SLOT_VAR0 + i;
249 
250       nir_copy_var(&b, v_out, a_in);
251    }
252 
253    const struct blorp_program p =
254       blorp_compile_vs(blorp, mem_ctx, b.shader);
255 
256    bool result =
257       blorp->upload_shader(batch, MESA_SHADER_VERTEX,
258                            &blorp_key, sizeof(blorp_key),
259                            p.kernel, p.kernel_size,
260                            p.prog_data, p.prog_data_size,
261                            &params->vs_prog_kernel, &params->vs_prog_data);
262 
263    ralloc_free(mem_ctx);
264    return result;
265 }
266 
267 void
blorp_init_brw(struct blorp_context * blorp,void * driver_ctx,struct isl_device * isl_dev,const struct brw_compiler * brw,const struct blorp_config * config)268 blorp_init_brw(struct blorp_context *blorp, void *driver_ctx,
269                struct isl_device *isl_dev, const struct brw_compiler *brw,
270                const struct blorp_config *config)
271 {
272    blorp_init(blorp, driver_ctx, isl_dev, config);
273    assert(brw);
274 
275    blorp->compiler->brw = brw;
276    blorp->compiler->nir_options = blorp_nir_options_brw;
277    blorp->compiler->compile_fs = blorp_compile_fs_brw;
278    blorp->compiler->compile_vs = blorp_compile_vs_brw;
279    blorp->compiler->compile_cs = blorp_compile_cs_brw;
280    blorp->compiler->params_get_layer_offset_vs =
281       blorp_params_get_layer_offset_vs_brw;
282 }
283