Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 1 | /* |
| 2 | * © Copyright 2018 Alyssa Rosenzweig |
| 3 | * |
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), |
| 6 | * to deal in the Software without restriction, including without limitation |
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 8 | * and/or sell copies of the Software, and to permit persons to whom the |
| 9 | * Software is furnished to do so, subject to the following conditions: |
| 10 | * |
| 11 | * The above copyright notice and this permission notice (including the next |
| 12 | * paragraph) shall be included in all copies or substantial portions of the |
| 13 | * Software. |
| 14 | * |
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 21 | * SOFTWARE. |
| 22 | * |
| 23 | */ |
| 24 | |
| 25 | #include <stdio.h> |
| 26 | #include <stdlib.h> |
| 27 | #include <string.h> |
Boris Brezillon | 154cb72 | 2019-09-14 09:58:55 +0200 | [diff] [blame] | 28 | #include "pan_bo.h" |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 29 | #include "pan_context.h" |
Alyssa Rosenzweig | 35418f6 | 2019-12-16 18:05:21 -0500 | [diff] [blame] | 30 | #include "pan_util.h" |
Alyssa Rosenzweig | 8016906 | 2020-04-06 16:44:17 -0400 | [diff] [blame] | 31 | #include "panfrost-quirks.h" |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 32 | |
| 33 | #include "compiler/nir/nir.h" |
| 34 | #include "nir/tgsi_to_nir.h" |
| 35 | #include "midgard/midgard_compile.h" |
Alyssa Rosenzweig | 8016906 | 2020-04-06 16:44:17 -0400 | [diff] [blame] | 36 | #include "bifrost/bifrost_compile.h" |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 37 | #include "util/u_dynarray.h" |
| 38 | |
| 39 | #include "tgsi/tgsi_dump.h" |
| 40 | |
Alyssa Rosenzweig | d104239 | 2020-04-08 13:54:17 -0400 | [diff] [blame] | 41 | static unsigned |
| 42 | pan_format_from_nir_base(nir_alu_type base) |
| 43 | { |
| 44 | switch (base) { |
| 45 | case nir_type_int: |
| 46 | return MALI_FORMAT_SINT; |
| 47 | case nir_type_uint: |
| 48 | case nir_type_bool: |
| 49 | return MALI_FORMAT_UINT; |
| 50 | case nir_type_float: |
| 51 | return MALI_CHANNEL_FLOAT; |
| 52 | default: |
| 53 | unreachable("Invalid base"); |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | static unsigned |
| 58 | pan_format_from_nir_size(nir_alu_type base, unsigned size) |
| 59 | { |
| 60 | if (base == nir_type_float) { |
| 61 | switch (size) { |
| 62 | case 16: return MALI_FORMAT_SINT; |
| 63 | case 32: return MALI_FORMAT_UNORM; |
| 64 | default: |
| 65 | unreachable("Invalid float size for format"); |
| 66 | } |
| 67 | } else { |
| 68 | switch (size) { |
| 69 | case 1: |
| 70 | case 8: return MALI_CHANNEL_8; |
| 71 | case 16: return MALI_CHANNEL_16; |
| 72 | case 32: return MALI_CHANNEL_32; |
| 73 | default: |
| 74 | unreachable("Invalid int size for format"); |
| 75 | } |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | static enum mali_format |
Alyssa Rosenzweig | 1c1782c | 2020-06-09 18:15:20 -0400 | [diff] [blame] | 80 | pan_format_from_glsl(const struct glsl_type *type, unsigned precision, unsigned frac) |
Alyssa Rosenzweig | d104239 | 2020-04-08 13:54:17 -0400 | [diff] [blame] | 81 | { |
Alyssa Rosenzweig | 8462ca0 | 2020-06-10 15:47:45 -0400 | [diff] [blame] | 82 | const struct glsl_type *column = glsl_without_array_or_matrix(type); |
| 83 | enum glsl_base_type glsl_base = glsl_get_base_type(column); |
Alyssa Rosenzweig | d104239 | 2020-04-08 13:54:17 -0400 | [diff] [blame] | 84 | nir_alu_type t = nir_get_nir_type_for_glsl_base_type(glsl_base); |
Alyssa Rosenzweig | 8462ca0 | 2020-06-10 15:47:45 -0400 | [diff] [blame] | 85 | unsigned chan = glsl_get_components(column); |
| 86 | |
| 87 | /* If we have a fractional location added, we need to increase the size |
| 88 | * so it will fit, i.e. a vec3 in YZW requires us to allocate a vec4. |
| 89 | * We could do better but this is an edge case as it is, normally |
| 90 | * packed varyings will be aligned. */ |
| 91 | chan += frac; |
| 92 | |
| 93 | assert(chan >= 1 && chan <= 4); |
Alyssa Rosenzweig | d104239 | 2020-04-08 13:54:17 -0400 | [diff] [blame] | 94 | |
| 95 | unsigned base = nir_alu_type_get_base_type(t); |
| 96 | unsigned size = nir_alu_type_get_type_size(t); |
| 97 | |
Alyssa Rosenzweig | 1c1782c | 2020-06-09 18:15:20 -0400 | [diff] [blame] | 98 | /* Demote to fp16 where possible. int16 varyings are TODO as the hw |
| 99 | * will saturate instead of wrap which is not conformant, so we need to |
| 100 | * insert i2i16/u2u16 instructions before the st_vary_32i/32u to get |
| 101 | * the intended behaviour */ |
| 102 | |
| 103 | bool is_16 = (precision == GLSL_PRECISION_MEDIUM) |
| 104 | || (precision == GLSL_PRECISION_LOW); |
| 105 | |
| 106 | if (is_16 && base == nir_type_float) |
| 107 | size = 16; |
| 108 | else |
| 109 | size = 32; |
| 110 | |
Alyssa Rosenzweig | d104239 | 2020-04-08 13:54:17 -0400 | [diff] [blame] | 111 | return pan_format_from_nir_base(base) | |
| 112 | pan_format_from_nir_size(base, size) | |
Alyssa Rosenzweig | 8462ca0 | 2020-06-10 15:47:45 -0400 | [diff] [blame] | 113 | MALI_NR_CHANNELS(chan); |
Alyssa Rosenzweig | d104239 | 2020-04-08 13:54:17 -0400 | [diff] [blame] | 114 | } |
| 115 | |
Tomeu Vizoso | 3c98c45 | 2020-04-24 08:40:51 +0200 | [diff] [blame] | 116 | static enum bifrost_shader_type |
| 117 | bifrost_blend_type_from_nir(nir_alu_type nir_type) |
| 118 | { |
| 119 | switch(nir_type) { |
| 120 | case 0: /* Render target not in use */ |
| 121 | return 0; |
| 122 | case nir_type_float16: |
| 123 | return BIFROST_BLEND_F16; |
| 124 | case nir_type_float32: |
| 125 | return BIFROST_BLEND_F32; |
| 126 | case nir_type_int32: |
| 127 | return BIFROST_BLEND_I32; |
| 128 | case nir_type_uint32: |
| 129 | return BIFROST_BLEND_U32; |
| 130 | case nir_type_int16: |
| 131 | return BIFROST_BLEND_I16; |
| 132 | case nir_type_uint16: |
| 133 | return BIFROST_BLEND_U16; |
| 134 | default: |
Alyssa Rosenzweig | ed1910d | 2020-07-07 16:15:45 -0400 | [diff] [blame] | 135 | unreachable("Unsupported blend shader type for NIR alu type"); |
Tomeu Vizoso | 3c98c45 | 2020-04-24 08:40:51 +0200 | [diff] [blame] | 136 | return 0; |
| 137 | } |
| 138 | } |
| 139 | |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 140 | void |
Boris Brezillon | b02f97c | 2020-03-05 16:20:18 +0100 | [diff] [blame] | 141 | panfrost_shader_compile(struct panfrost_context *ctx, |
| 142 | enum pipe_shader_ir ir_type, |
| 143 | const void *ir, |
| 144 | gl_shader_stage stage, |
| 145 | struct panfrost_shader_state *state, |
| 146 | uint64_t *outputs_written) |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 147 | { |
Alyssa Rosenzweig | ca8c625 | 2020-03-23 18:44:21 -0400 | [diff] [blame] | 148 | struct panfrost_device *dev = pan_device(ctx->base.screen); |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 149 | uint8_t *dst; |
| 150 | |
| 151 | nir_shader *s; |
| 152 | |
Alyssa Rosenzweig | c228046 | 2019-07-31 15:19:09 -0700 | [diff] [blame] | 153 | if (ir_type == PIPE_SHADER_IR_NIR) { |
| 154 | s = nir_shader_clone(NULL, ir); |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 155 | } else { |
Alyssa Rosenzweig | c228046 | 2019-07-31 15:19:09 -0700 | [diff] [blame] | 156 | assert (ir_type == PIPE_SHADER_IR_TGSI); |
Axel Davy | 522bd41 | 2020-05-12 21:52:40 +0200 | [diff] [blame] | 157 | s = tgsi_to_nir(ir, ctx->base.screen, false); |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 158 | } |
| 159 | |
Alyssa Rosenzweig | 4647999 | 2019-07-31 15:49:13 -0700 | [diff] [blame] | 160 | s->info.stage = stage; |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 161 | |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 162 | /* Call out to Midgard compiler given the above NIR */ |
| 163 | |
Alyssa Rosenzweig | 3a4524e | 2020-03-10 15:41:56 -0400 | [diff] [blame] | 164 | panfrost_program program = { |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 165 | .alpha_ref = state->alpha_state.ref_value |
| 166 | }; |
| 167 | |
Alyssa Rosenzweig | 8016906 | 2020-04-06 16:44:17 -0400 | [diff] [blame] | 168 | if (dev->quirks & IS_BIFROST) { |
| 169 | bifrost_compile_shader_nir(s, &program, dev->gpu_id); |
| 170 | } else { |
| 171 | midgard_compile_shader_nir(s, &program, false, 0, dev->gpu_id, |
Alyssa Rosenzweig | ed1910d | 2020-07-07 16:15:45 -0400 | [diff] [blame] | 172 | dev->debug & PAN_DBG_PRECOMPILE); |
Alyssa Rosenzweig | 8016906 | 2020-04-06 16:44:17 -0400 | [diff] [blame] | 173 | } |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 174 | |
| 175 | /* Prepare the compiled binary for upload */ |
| 176 | int size = program.compiled.size; |
| 177 | dst = program.compiled.data; |
| 178 | |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 179 | /* Upload the shader. The lookahead tag is ORed on as a tagged pointer. |
| 180 | * I bet someone just thought that would be a cute pun. At least, |
| 181 | * that's how I'd do it. */ |
| 182 | |
Alyssa Rosenzweig | bf5d8cf | 2019-12-16 16:45:28 -0500 | [diff] [blame] | 183 | if (size) { |
Alyssa Rosenzweig | 1d88f07 | 2020-07-07 16:19:39 -0400 | [diff] [blame^] | 184 | state->bo = panfrost_bo_create(dev, size, PAN_BO_EXECUTE); |
Alyssa Rosenzweig | bf5d8cf | 2019-12-16 16:45:28 -0500 | [diff] [blame] | 185 | memcpy(state->bo->cpu, dst, size); |
Alyssa Rosenzweig | 8016906 | 2020-04-06 16:44:17 -0400 | [diff] [blame] | 186 | } |
| 187 | |
| 188 | if (!(dev->quirks & IS_BIFROST)) { |
| 189 | /* If size = 0, no shader. Use dummy tag to avoid |
| 190 | * INSTR_INVALID_ENC */ |
| 191 | state->first_tag = size ? program.first_tag : 1; |
Alyssa Rosenzweig | bf5d8cf | 2019-12-16 16:45:28 -0500 | [diff] [blame] | 192 | } |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 193 | |
| 194 | util_dynarray_fini(&program.compiled); |
| 195 | |
Alyssa Rosenzweig | 7e8de5a | 2019-04-03 01:48:09 +0000 | [diff] [blame] | 196 | state->sysval_count = program.sysval_count; |
| 197 | memcpy(state->sysval, program.sysvals, sizeof(state->sysval[0]) * state->sysval_count); |
| 198 | |
Alyssa Rosenzweig | 8781378 | 2019-12-19 13:39:14 -0500 | [diff] [blame] | 199 | bool vertex_id = s->info.system_values_read & (1 << SYSTEM_VALUE_VERTEX_ID); |
| 200 | bool instance_id = s->info.system_values_read & (1 << SYSTEM_VALUE_INSTANCE_ID); |
| 201 | |
Alyssa Rosenzweig | 1d194f8 | 2020-05-29 16:06:10 -0400 | [diff] [blame] | 202 | /* On Bifrost it's a sysval, on Midgard it's a varying */ |
| 203 | state->reads_frag_coord = s->info.system_values_read & (1 << SYSTEM_VALUE_FRAG_COORD); |
| 204 | |
Alyssa Rosenzweig | dce7722 | 2020-06-02 14:12:29 -0400 | [diff] [blame] | 205 | state->writes_global = s->info.writes_memory; |
| 206 | |
Alyssa Rosenzweig | 4647999 | 2019-07-31 15:49:13 -0700 | [diff] [blame] | 207 | switch (stage) { |
Alyssa Rosenzweig | 5534fdb | 2019-07-23 17:02:38 -0700 | [diff] [blame] | 208 | case MESA_SHADER_VERTEX: |
Boris Brezillon | 55e0143 | 2020-03-05 15:17:31 +0100 | [diff] [blame] | 209 | state->attribute_count = util_bitcount64(s->info.inputs_read); |
| 210 | state->varying_count = util_bitcount64(s->info.outputs_written); |
Alyssa Rosenzweig | 8781378 | 2019-12-19 13:39:14 -0500 | [diff] [blame] | 211 | |
| 212 | if (vertex_id) |
Boris Brezillon | 55e0143 | 2020-03-05 15:17:31 +0100 | [diff] [blame] | 213 | state->attribute_count = MAX2(state->attribute_count, PAN_VERTEX_ID + 1); |
Alyssa Rosenzweig | 8781378 | 2019-12-19 13:39:14 -0500 | [diff] [blame] | 214 | |
| 215 | if (instance_id) |
Boris Brezillon | 55e0143 | 2020-03-05 15:17:31 +0100 | [diff] [blame] | 216 | state->attribute_count = MAX2(state->attribute_count, PAN_INSTANCE_ID + 1); |
Alyssa Rosenzweig | 8781378 | 2019-12-19 13:39:14 -0500 | [diff] [blame] | 217 | |
Alyssa Rosenzweig | 5534fdb | 2019-07-23 17:02:38 -0700 | [diff] [blame] | 218 | break; |
| 219 | case MESA_SHADER_FRAGMENT: |
Boris Brezillon | 55e0143 | 2020-03-05 15:17:31 +0100 | [diff] [blame] | 220 | state->attribute_count = 0; |
| 221 | state->varying_count = util_bitcount64(s->info.inputs_read); |
Boris Brezillon | 38c2069 | 2020-01-31 10:55:49 +0100 | [diff] [blame] | 222 | if (s->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) |
| 223 | state->writes_depth = true; |
| 224 | if (s->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) |
| 225 | state->writes_stencil = true; |
Alyssa Rosenzweig | 1085f74 | 2020-05-21 15:49:30 -0400 | [diff] [blame] | 226 | |
| 227 | /* List of reasons we need to execute frag shaders when things |
| 228 | * are masked off */ |
| 229 | |
| 230 | state->fs_sidefx = |
| 231 | s->info.writes_memory || |
| 232 | s->info.fs.uses_discard || |
| 233 | s->info.fs.uses_demote; |
Alyssa Rosenzweig | 5534fdb | 2019-07-23 17:02:38 -0700 | [diff] [blame] | 234 | break; |
Alyssa Rosenzweig | ff345d4 | 2019-07-31 15:52:04 -0700 | [diff] [blame] | 235 | case MESA_SHADER_COMPUTE: |
| 236 | /* TODO: images */ |
Boris Brezillon | 55e0143 | 2020-03-05 15:17:31 +0100 | [diff] [blame] | 237 | state->attribute_count = 0; |
| 238 | state->varying_count = 0; |
Alyssa Rosenzweig | 9603126 | 2020-02-06 14:29:42 -0500 | [diff] [blame] | 239 | state->shared_size = s->info.cs.shared_size; |
Alyssa Rosenzweig | ff345d4 | 2019-07-31 15:52:04 -0700 | [diff] [blame] | 240 | break; |
Alyssa Rosenzweig | 5534fdb | 2019-07-23 17:02:38 -0700 | [diff] [blame] | 241 | default: |
| 242 | unreachable("Unknown shader state"); |
| 243 | } |
| 244 | |
Alyssa Rosenzweig | bab4f6c | 2019-07-23 16:52:40 -0700 | [diff] [blame] | 245 | state->can_discard = s->info.fs.uses_discard; |
Alyssa Rosenzweig | 48991c7 | 2019-07-23 16:49:37 -0700 | [diff] [blame] | 246 | state->helper_invocations = s->info.fs.needs_helper_invocations; |
Alyssa Rosenzweig | 7597015 | 2019-12-09 11:18:21 -0500 | [diff] [blame] | 247 | state->stack_size = program.tls_size; |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 248 | |
Alyssa Rosenzweig | f1de952 | 2020-06-08 18:05:21 -0400 | [diff] [blame] | 249 | state->reads_frag_coord = s->info.inputs_read & (1 << VARYING_SLOT_POS); |
| 250 | state->reads_point_coord = s->info.inputs_read & (1 << VARYING_SLOT_PNTC); |
| 251 | state->reads_face = s->info.inputs_read & (1 << VARYING_SLOT_FACE); |
| 252 | state->writes_point_size = s->info.outputs_written & (1 << VARYING_SLOT_PSIZ); |
| 253 | |
Alyssa Rosenzweig | 5b0a1a4 | 2019-08-07 10:26:12 -0700 | [diff] [blame] | 254 | if (outputs_written) |
| 255 | *outputs_written = s->info.outputs_written; |
| 256 | |
Alyssa Rosenzweig | e30091b | 2020-04-08 14:44:31 -0400 | [diff] [blame] | 257 | /* Separate as primary uniform count is truncated. Sysvals are prefix |
| 258 | * uniforms */ |
| 259 | state->uniform_count = s->num_uniforms + program.sysval_count; |
Boris Brezillon | 55e0143 | 2020-03-05 15:17:31 +0100 | [diff] [blame] | 260 | state->uniform_cutoff = program.uniform_cutoff; |
| 261 | state->work_reg_count = program.work_register_count; |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 262 | |
Tomeu Vizoso | 3c98c45 | 2020-04-24 08:40:51 +0200 | [diff] [blame] | 263 | if (dev->quirks & IS_BIFROST) |
| 264 | for (unsigned i = 0; i < BIFROST_MAX_RENDER_TARGET_COUNT; i++) |
| 265 | state->blend_types[i] = bifrost_blend_type_from_nir(program.blend_types[i]); |
| 266 | |
Alyssa Rosenzweig | d104239 | 2020-04-08 13:54:17 -0400 | [diff] [blame] | 267 | /* Record the varying mapping for the command stream's bookkeeping */ |
| 268 | |
Alyssa Rosenzweig | d104239 | 2020-04-08 13:54:17 -0400 | [diff] [blame] | 269 | struct exec_list *l_varyings = |
| 270 | stage == MESA_SHADER_VERTEX ? &s->outputs : &s->inputs; |
| 271 | |
| 272 | nir_foreach_variable(var, l_varyings) { |
| 273 | unsigned loc = var->data.driver_location; |
| 274 | unsigned sz = glsl_count_attribute_slots(var->type, FALSE); |
| 275 | |
| 276 | for (int c = 0; c < sz; ++c) { |
Alyssa Rosenzweig | 3cc425e | 2020-06-10 15:48:33 -0400 | [diff] [blame] | 277 | state->varyings_loc[loc + c] = var->data.location + c; |
Alyssa Rosenzweig | 1c1782c | 2020-06-09 18:15:20 -0400 | [diff] [blame] | 278 | state->varyings[loc + c] = pan_format_from_glsl(var->type, |
| 279 | var->data.precision, var->data.location_frac); |
Alyssa Rosenzweig | d104239 | 2020-04-08 13:54:17 -0400 | [diff] [blame] | 280 | } |
| 281 | } |
Alyssa Rosenzweig | 7da251f | 2019-02-05 04:32:27 +0000 | [diff] [blame] | 282 | } |