diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index c6413d8582c..28eada2ac64 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -2433,6 +2433,16 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr) dst[0]->cat6.type = TYPE_U32; __ssa_dst(dst[0]); break; + case nir_intrinsic_load_tess_level_outer_default: + for (int i = 0; i < dest_components; i++) { + dst[i] = create_driver_param(ctx, IR3_DP_HS_DEFAULT_OUTER_LEVEL_X + i); + } + break; + case nir_intrinsic_load_tess_level_inner_default: + for (int i = 0; i < dest_components; i++) { + dst[i] = create_driver_param(ctx, IR3_DP_HS_DEFAULT_INNER_LEVEL_X + i); + } + break; case nir_intrinsic_discard_if: case nir_intrinsic_discard: case nir_intrinsic_demote: diff --git a/src/freedreno/ir3/ir3_nir.c b/src/freedreno/ir3/ir3_nir.c index ca39ecea4d5..266955298b9 100644 --- a/src/freedreno/ir3/ir3_nir.c +++ b/src/freedreno/ir3/ir3_nir.c @@ -679,6 +679,8 @@ ir3_nir_lower_variant(struct ir3_shader_variant *so, nir_shader *s) progress = true; break; case MESA_SHADER_TESS_CTRL: + NIR_PASS_V(s, nir_lower_io_to_scalar, + nir_var_shader_in | nir_var_shader_out); NIR_PASS_V(s, ir3_nir_lower_tess_ctrl, so, so->key.tessellation); NIR_PASS_V(s, ir3_nir_lower_to_explicit_input, so); progress = true; @@ -940,6 +942,14 @@ ir3_nir_scan_driver_consts(struct ir3_compiler *compiler, nir_shader *shader, st layout->num_driver_params = MAX2(layout->num_driver_params, IR3_DP_DRAWID + 1); break; + case nir_intrinsic_load_tess_level_outer_default: + layout->num_driver_params = MAX2(layout->num_driver_params, + IR3_DP_HS_DEFAULT_OUTER_LEVEL_W + 1); + break; + case nir_intrinsic_load_tess_level_inner_default: + layout->num_driver_params = MAX2(layout->num_driver_params, + IR3_DP_HS_DEFAULT_INNER_LEVEL_Y + 1); + break; default: break; } diff --git a/src/freedreno/ir3/ir3_shader.c b/src/freedreno/ir3/ir3_shader.c index 7ce121baf91..049b5d7f184 100644 --- a/src/freedreno/ir3/ir3_shader.c +++ b/src/freedreno/ir3/ir3_shader.c @@ -415,9 +415,58 @@ ir3_shader_get_variant(struct ir3_shader *shader, return v; } +struct ir3_shader * +ir3_shader_passthrough_tcs(struct ir3_shader *vs, unsigned patch_vertices) +{ + assert(vs->type == MESA_SHADER_VERTEX); + assert(patch_vertices > 0); + assert(patch_vertices <= 32); + + unsigned n = patch_vertices - 1; + if (!vs->vs.passthrough_tcs[n]) { + const nir_shader_compiler_options *options = + ir3_get_compiler_options(vs->compiler); + nir_shader *tcs = + nir_create_passthrough_tcs(options, vs->nir, patch_vertices); + + /* Technically it is an internal shader but it is confusing to + * not have it show up in debug output + */ + tcs->info.internal = false; + + nir_assign_io_var_locations(tcs, nir_var_shader_in, + &tcs->num_inputs, + tcs->info.stage); + + nir_assign_io_var_locations(tcs, nir_var_shader_out, + &tcs->num_outputs, + tcs->info.stage); + + NIR_PASS_V(tcs, nir_lower_system_values); + + nir_shader_gather_info(tcs, nir_shader_get_entrypoint(tcs)); + + ir3_finalize_nir(vs->compiler, tcs); + + struct ir3_shader_options ir3_options = {}; + + vs->vs.passthrough_tcs[n] = + ir3_shader_from_nir(vs->compiler, tcs, &ir3_options, NULL); + + vs->vs.passthrough_tcs_compiled |= BITFIELD_BIT(n); + } + + return vs->vs.passthrough_tcs[n]; +} + void ir3_shader_destroy(struct ir3_shader *shader) { + if (shader->type == MESA_SHADER_VERTEX) { + u_foreach_bit (b, shader->vs.passthrough_tcs_compiled) { + ir3_shader_destroy(shader->vs.passthrough_tcs[b]); + } + } ralloc_free(shader->nir); mtx_destroy(&shader->variants_lock); ralloc_free(shader); diff --git a/src/freedreno/ir3/ir3_shader.h b/src/freedreno/ir3/ir3_shader.h index ddc635e1425..a97a65a797a 100644 --- a/src/freedreno/ir3/ir3_shader.h +++ b/src/freedreno/ir3/ir3_shader.h @@ -73,6 +73,15 @@ enum ir3_driver_param { IR3_DP_UCP7_W = 35, IR3_DP_VS_COUNT = 36, /* must be aligned to vec4 */ + /* TCS driver params: */ + IR3_DP_HS_DEFAULT_OUTER_LEVEL_X = 0, + IR3_DP_HS_DEFAULT_OUTER_LEVEL_Y = 1, + IR3_DP_HS_DEFAULT_OUTER_LEVEL_Z = 2, + IR3_DP_HS_DEFAULT_OUTER_LEVEL_W = 3, + IR3_DP_HS_DEFAULT_INNER_LEVEL_X = 4, + IR3_DP_HS_DEFAULT_INNER_LEVEL_Y = 5, + IR3_DP_HS_COUNT = 8, /* must be aligned to vec4 */ + /* fragment shader driver params: */ IR3_DP_FS_SUBGROUP_SIZE = 0, }; @@ -854,6 +863,15 @@ struct ir3_shader { unsigned req_input_mem; /* in dwords */ unsigned req_local_mem; } cs; + /* For vertex shaders: */ + struct { + /* If we need to generate a passthrough TCS, it will be a function of + * (a) the VS and (b) the # of patch_vertices (max 32), so cache them + * in the VS keyed by # of patch_vertices-1. + */ + unsigned passthrough_tcs_compiled; + struct ir3_shader *passthrough_tcs[32]; + } vs; }; struct ir3_shader_variant *variants; @@ -939,6 +957,8 @@ ir3_shader_from_nir(struct ir3_compiler *compiler, nir_shader *nir, struct ir3_stream_output_info *stream_output); uint32_t ir3_trim_constlen(struct ir3_shader_variant **variants, const struct ir3_compiler *compiler); +struct ir3_shader * +ir3_shader_passthrough_tcs(struct ir3_shader *vs, unsigned patch_vertices); void ir3_shader_destroy(struct ir3_shader *shader); void ir3_shader_disasm(struct ir3_shader_variant *so, uint32_t *bin, FILE *out); uint64_t ir3_shader_outputs(const struct ir3_shader *so);