X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fnir%2Fnir_lower_clip_cull_distance_arrays.c;h=390eded7b01a4a5610f734f2709203baddab5477;hb=2b676b2ce87520042ffb1fae8a9c0d97ba0e3cbc;hp=6a93f1c0a2dca83899d31fcb3dab204e80d4384a;hpb=d80c342d898275cbd6266c37e70dc422590d7d8c;p=mesa.git diff --git a/src/compiler/nir/nir_lower_clip_cull_distance_arrays.c b/src/compiler/nir/nir_lower_clip_cull_distance_arrays.c index 6a93f1c0a2d..390eded7b01 100644 --- a/src/compiler/nir/nir_lower_clip_cull_distance_arrays.c +++ b/src/compiler/nir/nir_lower_clip_cull_distance_arrays.c @@ -27,10 +27,10 @@ /** * @file * - * This pass combines separate clip and cull distance arrays into a - * single array that contains both. Clip distances come first, then - * cull distances. It also populates nir_shader_info with the size - * of the original arrays so the driver knows which are which. + * This pass combines clip and cull distance arrays in separate locations and + * colocates them both in VARYING_SLOT_CLIP_DIST0. It does so by maintaining + * two arrays but making them compact and using location_frac to stack them on + * top of each other. */ /** @@ -56,71 +56,6 @@ get_unwrapped_array_length(nir_shader *nir, nir_variable *var) return glsl_get_length(type); } -/** - * Update the type of the combined array (including interface block nesting). - */ -static void -update_type(nir_variable *var, gl_shader_stage stage, unsigned length) -{ - const struct glsl_type *type = glsl_array_type(glsl_float_type(), length); - - if (nir_is_per_vertex_io(var, stage)) - type = glsl_array_type(type, glsl_get_length(var->type)); - - var->type = type; -} - -/** - * Rewrite any clip/cull distances to refer to the new combined array. - */ -static void -rewrite_references(nir_instr *instr, - nir_variable *combined, - unsigned cull_offset) -{ - if (instr->type != nir_instr_type_intrinsic) - return; - - nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); - - /* copy_var needs to be lowered to load/store before calling this pass */ - assert(intrin->intrinsic != nir_intrinsic_copy_var); - - if (intrin->intrinsic != nir_intrinsic_load_var && - intrin->intrinsic != nir_intrinsic_store_var) - return; - - nir_deref_var *var_ref = intrin->variables[0]; - if (var_ref->var->data.mode != combined->data.mode) - return; - - if (var_ref->var->data.location != VARYING_SLOT_CLIP_DIST0 && - var_ref->var->data.location != VARYING_SLOT_CULL_DIST0) - return; - - /* Update types along the deref chain */ - const struct glsl_type *type = combined->type; - nir_deref *deref = &var_ref->deref; - while (deref) { - deref->type = type; - deref = deref->child; - type = glsl_get_array_element(type); - } - - /* For cull distances, add an offset to the array index */ - if (var_ref->var->data.location == VARYING_SLOT_CULL_DIST0) { - nir_deref *tail = nir_deref_tail(&intrin->variables[0]->deref); - nir_deref_array *array_ref = nir_deref_as_array(tail); - - array_ref->base_offset += cull_offset; - } - - /* Point the deref at the combined array */ - var_ref->var = combined; - - /* There's no need to update writemasks; it's a scalar array. */ -} - static bool combine_clip_cull(nir_shader *nir, struct exec_list *vars, @@ -128,7 +63,6 @@ combine_clip_cull(nir_shader *nir, { nir_variable *cull = NULL; nir_variable *clip = NULL; - bool progress = false; nir_foreach_variable(var, vars) { if (var->data.location == VARYING_SLOT_CLIP_DIST0) @@ -138,6 +72,30 @@ combine_clip_cull(nir_shader *nir, cull = var; } + if (!cull && !clip) { + /* If this is run after optimizations and the variables have been + * eliminated, we should update the shader info, because no other + * place does that. + */ + if (store_info) { + nir->info.clip_distance_array_size = 0; + nir->info.cull_distance_array_size = 0; + } + return false; + } + + if (!cull && clip) { + /* The GLSL IR lowering pass must have converted these to vectors */ + if (!clip->data.compact) + return false; + + /* If this pass has already run, don't repeat. We would think that + * the combined clip/cull distance array was clip-only and mess up. + */ + if (clip->data.how_declared == nir_var_hidden) + return false; + } + const unsigned clip_array_size = get_unwrapped_array_length(nir, clip); const unsigned cull_array_size = get_unwrapped_array_length(nir, cull); @@ -146,47 +104,19 @@ combine_clip_cull(nir_shader *nir, nir->info.cull_distance_array_size = cull_array_size; } - if (clip) - clip->data.compact = true; - - if (cull) - cull->data.compact = true; - - if (cull_array_size > 0) { - if (clip_array_size == 0) { - /* No clip distances, just change the cull distance location */ - cull->data.location = VARYING_SLOT_CLIP_DIST0; - } else { - /* Turn the ClipDistance array into a combined one */ - update_type(clip, nir->info.stage, clip_array_size + cull_array_size); - - /* Rewrite CullDistance to reference the combined array */ - nir_foreach_function(function, nir) { - if (function->impl) { - nir_foreach_block(block, function->impl) { - nir_foreach_instr(instr, block) { - rewrite_references(instr, clip, clip_array_size); - } - } - } - } - - /* Delete the old CullDistance variable */ - exec_node_remove(&cull->node); - ralloc_free(cull); - } + if (clip) { + assert(clip->data.compact); + clip->data.how_declared = nir_var_hidden; + } - nir_foreach_function(function, nir) { - if (function->impl) { - nir_metadata_preserve(function->impl, - nir_metadata_block_index | - nir_metadata_dominance); - } - } - progress = true; + if (cull) { + assert(cull->data.compact); + cull->data.how_declared = nir_var_hidden; + cull->data.location = VARYING_SLOT_CLIP_DIST0 + clip_array_size / 4; + cull->data.location_frac = clip_array_size % 4; } - return progress; + return true; } bool @@ -194,13 +124,26 @@ nir_lower_clip_cull_distance_arrays(nir_shader *nir) { bool progress = false; - nir_assert_lowered_derefs(nir, nir_lower_load_store_derefs); - if (nir->info.stage <= MESA_SHADER_GEOMETRY) progress |= combine_clip_cull(nir, &nir->outputs, true); if (nir->info.stage > MESA_SHADER_VERTEX) progress |= combine_clip_cull(nir, &nir->inputs, false); + nir_foreach_function(function, nir) { + if (!function->impl) + continue; + + if (progress) { + nir_metadata_preserve(function->impl, + nir_metadata_block_index | + nir_metadata_dominance | + nir_metadata_live_ssa_defs | + nir_metadata_loop_analysis); + } else { + nir_metadata_preserve(function->impl, nir_metadata_all); + } + } + return progress; }