X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fnir%2Fnir_lower_clip.c;h=6e8010cf78b626ea75dcb21c9f7f3109ea19c66c;hb=025bdbac3e09ae9bac9eefb831e9446b9574d120;hp=ec0285f47baf65c9f83b19f0f57372d83c382f5e;hpb=4b08bb47704ee181c9406e26c086815bd4c241ec;p=mesa.git diff --git a/src/compiler/nir/nir_lower_clip.c b/src/compiler/nir/nir_lower_clip.c index ec0285f47ba..6e8010cf78b 100644 --- a/src/compiler/nir/nir_lower_clip.c +++ b/src/compiler/nir/nir_lower_clip.c @@ -41,41 +41,54 @@ static nir_variable * -create_clipdist_var(nir_shader *shader, unsigned drvloc, - bool output, gl_varying_slot slot) +create_clipdist_var(nir_shader *shader, + bool output, gl_varying_slot slot, unsigned array_size) { nir_variable *var = rzalloc(shader, nir_variable); - var->data.driver_location = drvloc; - var->type = glsl_vec4_type(); - var->data.mode = output ? nir_var_shader_out : nir_var_shader_in; - var->name = ralloc_asprintf(var, "clipdist_%d", drvloc); + /* TODO use type_size() for num_inputs/outputs */ + if (output) { + var->data.driver_location = shader->num_outputs++; + var->data.mode = nir_var_shader_out; + } else { + var->data.driver_location = shader->num_inputs++; + var->data.mode = nir_var_shader_in; + } + var->name = ralloc_asprintf(var, "clipdist_%d", var->data.driver_location); var->data.index = 0; var->data.location = slot; - if (output) { - exec_list_push_tail(&shader->outputs, &var->node); - shader->num_outputs++; /* TODO use type_size() */ - } - else { - exec_list_push_tail(&shader->inputs, &var->node); - shader->num_inputs++; /* TODO use type_size() */ - } + if (array_size > 0) { + var->type = glsl_array_type(glsl_float_type(), array_size, + sizeof(float)); + var->data.compact = 1; + } else + var->type = glsl_vec4_type(); + + nir_shader_add_variable(shader, var); return var; } static void create_clipdist_vars(nir_shader *shader, nir_variable **io_vars, - unsigned ucp_enables, int *drvloc, bool output) + unsigned ucp_enables, bool output, + bool use_clipdist_array) { - if (ucp_enables & 0x0f) + if (use_clipdist_array) { io_vars[0] = - create_clipdist_var(shader, ++(*drvloc), output, - VARYING_SLOT_CLIP_DIST0); - if (ucp_enables & 0xf0) - io_vars[1] = - create_clipdist_var(shader, ++(*drvloc), output, - VARYING_SLOT_CLIP_DIST1); + create_clipdist_var(shader, output, + VARYING_SLOT_CLIP_DIST0, + util_last_bit(ucp_enables)); + } else { + if (ucp_enables & 0x0f) + io_vars[0] = + create_clipdist_var(shader, output, + VARYING_SLOT_CLIP_DIST0, 0); + if (ucp_enables & 0xf0) + io_vars[1] = + create_clipdist_var(shader, output, + VARYING_SLOT_CLIP_DIST1, 0); + } } static void @@ -94,13 +107,14 @@ store_clipdist_output(nir_builder *b, nir_variable *out, nir_ssa_def **val) } static void -load_clipdist_input(nir_builder *b, nir_variable *in, nir_ssa_def **val) +load_clipdist_input(nir_builder *b, nir_variable *in, int location_offset, + nir_ssa_def **val) { nir_intrinsic_instr *load; load = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_input); load->num_components = 4; - nir_intrinsic_set_base(load, in->data.driver_location); + nir_intrinsic_set_base(load, in->data.driver_location + location_offset); load->src[0] = nir_src_for_ssa(nir_imm_int(b, 0)); nir_ssa_dest_init(&load->instr, &load->dest, 4, 32, NULL); nir_builder_instr_insert(b, &load->instr); @@ -165,7 +179,7 @@ find_clipvertex_and_position_outputs(nir_shader *shader, nir_variable **clipvertex, nir_variable **position) { - nir_foreach_variable(var, &shader->outputs) { + nir_foreach_shader_out_variable(var, shader) { switch (var->data.location) { case VARYING_SLOT_POS: *position = var; @@ -189,10 +203,35 @@ find_clipvertex_and_position_outputs(nir_shader *shader, return *clipvertex || *position; } +static nir_ssa_def * +get_ucp(nir_builder *b, int plane, + const gl_state_index16 clipplane_state_tokens[][STATE_LENGTH]) +{ + if (clipplane_state_tokens) { + char tmp[100]; + snprintf(tmp, ARRAY_SIZE(tmp), "gl_ClipPlane%dMESA", plane); + nir_variable *var = nir_variable_create(b->shader, + nir_var_uniform, + glsl_vec4_type(), + tmp); + + var->num_state_slots = 1; + var->state_slots = ralloc_array(var, nir_state_slot, 1); + memcpy(var->state_slots[0].tokens, + clipplane_state_tokens[plane], + sizeof(var->state_slots[0].tokens)); + return nir_load_var(b, var); + } else + return nir_load_user_clip_plane(b, plane); +} + + static void lower_clip_outputs(nir_builder *b, nir_variable *position, nir_variable *clipvertex, nir_variable **out, - unsigned ucp_enables, bool use_vars) + unsigned ucp_enables, bool use_vars, + bool use_clipdist_array, + const gl_state_index16 clipplane_state_tokens[][STATE_LENGTH]) { nir_ssa_def *clipdist[MAX_CLIP_PLANES]; nir_ssa_def *cv; @@ -201,9 +240,8 @@ lower_clip_outputs(nir_builder *b, nir_variable *position, cv = nir_load_var(b, clipvertex ? clipvertex : position); if (clipvertex) { - exec_node_remove(&clipvertex->node); clipvertex->data.mode = nir_var_shader_temp; - exec_list_push_tail(&b->shader->globals, &clipvertex->node); + nir_fixup_deref_modes(b->shader); } } else { if (clipvertex) @@ -216,7 +254,7 @@ lower_clip_outputs(nir_builder *b, nir_variable *position, for (int plane = 0; plane < MAX_CLIP_PLANES; plane++) { if (ucp_enables & (1 << plane)) { - nir_ssa_def *ucp = nir_load_user_clip_plane(b, plane); + nir_ssa_def *ucp = get_ucp(b, plane, clipplane_state_tokens); /* calculate clipdist[plane] - dot(ucp, cv): */ clipdist[plane] = nir_fdot4(b, ucp, cv); @@ -224,18 +262,28 @@ lower_clip_outputs(nir_builder *b, nir_variable *position, /* 0.0 == don't-clip == disabled: */ clipdist[plane] = nir_imm_float(b, 0.0); } + if (use_clipdist_array && plane < util_last_bit(ucp_enables)) { + assert(use_vars); + nir_deref_instr *deref; + deref = nir_build_deref_array_imm(b, + nir_build_deref_var(b, out[0]), + plane); + nir_store_deref(b, deref, clipdist[plane], 1); + } } - if (use_vars) { - if (ucp_enables & 0x0f) - nir_store_var(b, out[0], nir_vec(b, clipdist, 4), 0xf); - if (ucp_enables & 0xf0) - nir_store_var(b, out[1], nir_vec(b, &clipdist[4], 4), 0xf); - } else { - if (ucp_enables & 0x0f) - store_clipdist_output(b, out[0], &clipdist[0]); - if (ucp_enables & 0xf0) - store_clipdist_output(b, out[1], &clipdist[4]); + if (!use_clipdist_array) { + if (use_vars) { + if (ucp_enables & 0x0f) + nir_store_var(b, out[0], nir_vec(b, clipdist, 4), 0xf); + if (ucp_enables & 0xf0) + nir_store_var(b, out[1], nir_vec(b, &clipdist[4], 4), 0xf); + } else { + if (ucp_enables & 0x0f) + store_clipdist_output(b, out[0], &clipdist[0]); + if (ucp_enables & 0xf0) + store_clipdist_output(b, out[1], &clipdist[4]); + } } } @@ -248,13 +296,17 @@ lower_clip_outputs(nir_builder *b, nir_variable *position, * * If use_vars is true, the pass will use variable loads and stores instead * of working with store_output intrinsics. + * + * If use_clipdist_array is true, the pass will use compact arrays for the + * clipdist output instead of two vec4s. */ bool -nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables, bool use_vars) +nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables, bool use_vars, + bool use_clipdist_array, + const gl_state_index16 clipplane_state_tokens[][STATE_LENGTH]) { nir_function_impl *impl = nir_shader_get_entrypoint(shader); nir_builder b; - int maxloc = -1; nir_variable *position = NULL; nir_variable *clipvertex = NULL; nir_variable *out[2] = { NULL }; @@ -281,9 +333,74 @@ nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables, bool use_vars) return false; /* insert CLIPDIST outputs */ - create_clipdist_vars(shader, out, ucp_enables, &maxloc, true); + create_clipdist_vars(shader, out, ucp_enables, true, + use_clipdist_array); + + lower_clip_outputs(&b, position, clipvertex, out, ucp_enables, use_vars, + use_clipdist_array, clipplane_state_tokens); + + nir_metadata_preserve(impl, nir_metadata_dominance); + + return true; +} + +static void +lower_clip_in_gs_block(nir_builder *b, nir_block *block, nir_variable *position, + nir_variable *clipvertex, nir_variable **out, + unsigned ucp_enables, bool use_clipdist_array, + const gl_state_index16 clipplane_state_tokens[][STATE_LENGTH]) +{ + nir_foreach_instr_safe(instr, block) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); + switch (intrin->intrinsic) { + case nir_intrinsic_emit_vertex_with_counter: + case nir_intrinsic_emit_vertex: + b->cursor = nir_before_instr(instr); + lower_clip_outputs(b, position, clipvertex, out, ucp_enables, true, + use_clipdist_array, clipplane_state_tokens); + break; + default: + /* not interesting; skip this */ + break; + } + } +} + +/* + * GS lowering + */ + +bool +nir_lower_clip_gs(nir_shader *shader, unsigned ucp_enables, + bool use_clipdist_array, + const gl_state_index16 clipplane_state_tokens[][STATE_LENGTH]) +{ + nir_function_impl *impl = nir_shader_get_entrypoint(shader); + nir_builder b; + nir_variable *position = NULL; + nir_variable *clipvertex = NULL; + nir_variable *out[2] = { NULL }; + + if (!ucp_enables) + return false; + + /* find clipvertex/position outputs */ + if (!find_clipvertex_and_position_outputs(shader, &clipvertex, &position)) + return false; + + /* insert CLIPDIST outputs */ + create_clipdist_vars(shader, out, ucp_enables, true, + use_clipdist_array); - lower_clip_outputs(&b, position, clipvertex, out, ucp_enables, use_vars); + nir_builder_init(&b, impl); + + nir_foreach_block(block, impl) + lower_clip_in_gs_block(&b, block, position, clipvertex, out, + ucp_enables, use_clipdist_array, + clipplane_state_tokens); nir_metadata_preserve(impl, nir_metadata_dominance); @@ -296,7 +413,7 @@ nir_lower_clip_vs(nir_shader *shader, unsigned ucp_enables, bool use_vars) static void lower_clip_fs(nir_function_impl *impl, unsigned ucp_enables, - nir_variable **in) + nir_variable **in, bool use_clipdist_array) { nir_ssa_def *clipdist[MAX_CLIP_PLANES]; nir_builder b; @@ -304,10 +421,17 @@ lower_clip_fs(nir_function_impl *impl, unsigned ucp_enables, nir_builder_init(&b, impl); b.cursor = nir_before_cf_list(&impl->body); - if (ucp_enables & 0x0f) - load_clipdist_input(&b, in[0], &clipdist[0]); - if (ucp_enables & 0xf0) - load_clipdist_input(&b, in[1], &clipdist[4]); + if (!use_clipdist_array) { + if (ucp_enables & 0x0f) + load_clipdist_input(&b, in[0], 0, &clipdist[0]); + if (ucp_enables & 0xf0) + load_clipdist_input(&b, in[1], 0, &clipdist[4]); + } else { + if (ucp_enables & 0x0f) + load_clipdist_input(&b, in[0], 0, &clipdist[0]); + if (ucp_enables & 0xf0) + load_clipdist_input(&b, in[0], 1, &clipdist[4]); + } for (int plane = 0; plane < MAX_CLIP_PLANES; plane++) { if (ucp_enables & (1 << plane)) { @@ -328,36 +452,48 @@ lower_clip_fs(nir_function_impl *impl, unsigned ucp_enables, nir_metadata_preserve(impl, nir_metadata_dominance); } +static bool +fs_has_clip_dist_input_var(nir_shader *shader, nir_variable **io_vars, + unsigned *ucp_enables) +{ + assert(shader->info.stage == MESA_SHADER_FRAGMENT); + nir_foreach_shader_in_variable(var, shader) { + switch (var->data.location) { + case VARYING_SLOT_CLIP_DIST0: + assert(var->data.compact); + io_vars[0] = var; + *ucp_enables &= (1 << glsl_get_length(var->type)) - 1; + return true; + default: + break; + } + } + return false; +} + /* insert conditional kill based on interpolated CLIPDIST */ bool -nir_lower_clip_fs(nir_shader *shader, unsigned ucp_enables) +nir_lower_clip_fs(nir_shader *shader, unsigned ucp_enables, + bool use_clipdist_array) { - nir_variable *in[2]; - int maxloc = -1; + nir_variable *in[2] = {0}; if (!ucp_enables) return false; - nir_foreach_variable(var, &shader->inputs) { - int loc = var->data.driver_location; - - /* keep track of last used driver-location.. we'll be - * appending CLIP_DIST0/CLIP_DIST1 after last existing - * input: - */ - maxloc = MAX2(maxloc, loc); - } - - /* The shader won't normally have CLIPDIST inputs, so we - * must add our own: + /* Fragment shaders can't read gl_ClipDistance[] in OpenGL so it will not + * have the variable defined, but Vulkan allows this, in which case the + * SPIR-V compiler would have already added it as a compact array. */ - /* insert CLIPDIST inputs */ - create_clipdist_vars(shader, in, ucp_enables, &maxloc, false); + if (!fs_has_clip_dist_input_var(shader, in, &ucp_enables)) + create_clipdist_vars(shader, in, ucp_enables, false, use_clipdist_array); + else + assert(use_clipdist_array); nir_foreach_function(function, shader) { if (!strcmp(function->name, "main")) - lower_clip_fs(function->impl, ucp_enables, in); + lower_clip_fs(function->impl, ucp_enables, in, use_clipdist_array); } return true;