CTS doesn't test input clip distances with the fragment shader stage, which explains why it was broken. I wrote a simple test locally that does pass now. I'm quite sure that cull distances are broken as well but that can be fixed later.
This fixes a crash with GTA V and DXVK. Cc: mesa-sta...@lists.freedesktop.org Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107477 Signed-off-by: Samuel Pitoiset <samuel.pitoi...@gmail.com> --- src/amd/vulkan/radv_nir_to_llvm.c | 41 ++++++++++++++++++++++++++++--- src/amd/vulkan/radv_pipeline.c | 15 +++++++++++ src/amd/vulkan/radv_shader.h | 1 + src/amd/vulkan/radv_shader_info.c | 11 +++++++++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/amd/vulkan/radv_nir_to_llvm.c b/src/amd/vulkan/radv_nir_to_llvm.c index 4940e3230f..80d991c904 100644 --- a/src/amd/vulkan/radv_nir_to_llvm.c +++ b/src/amd/vulkan/radv_nir_to_llvm.c @@ -2098,9 +2098,10 @@ handle_fs_input_decl(struct radv_shader_context *ctx, int idx = variable->data.location; unsigned attrib_count = glsl_count_attribute_slots(variable->type, false); LLVMValueRef interp = NULL; + uint64_t mask; variable->data.driver_location = idx * 4; - ctx->input_mask |= ((1ull << attrib_count) - 1) << variable->data.location; + mask = ((1ull << attrib_count) - 1) << variable->data.location; if (glsl_get_base_type(glsl_without_array(variable->type)) == GLSL_TYPE_FLOAT) { unsigned interp_type; @@ -2121,6 +2122,16 @@ handle_fs_input_decl(struct radv_shader_context *ctx, for (unsigned i = 0; i < attrib_count; ++i) ctx->inputs[ac_llvm_reg_index_soa(idx + i, 0)] = interp; + if (idx == VARYING_SLOT_CLIP_DIST0) { + /* Do not account for the number of attribute slots because + * we only want to know if clip distances are present. + */ + mask = 1ull << VARYING_SLOT_CLIP_DIST0; + if (attrib_count > 4) + mask |= 1ull << VARYING_SLOT_CLIP_DIST1; + } + + ctx->input_mask |= mask; } static void @@ -2179,7 +2190,8 @@ handle_fs_inputs(struct radv_shader_context *ctx, continue; if (i >= VARYING_SLOT_VAR0 || i == VARYING_SLOT_PNTC || - i == VARYING_SLOT_PRIMITIVE_ID || i == VARYING_SLOT_LAYER) { + i == VARYING_SLOT_PRIMITIVE_ID || i == VARYING_SLOT_LAYER || + i == VARYING_SLOT_CLIP_DIST0 || i == VARYING_SLOT_CLIP_DIST1) { interp_param = *inputs; interp_fs_input(ctx, index, interp_param, ctx->abi.prim_mask, inputs); @@ -2238,7 +2250,21 @@ scan_shader_output_decl(struct radv_shader_context *ctx, attrib_count = 2; else attrib_count = 1; - mask_attribs = 1ull << idx; + + mask_attribs = 1ull << VARYING_SLOT_CLIP_DIST0; + + /* Use CLIP_DIST1 when the number of components is > 4 + * because we have to export two parameters. Also it's + * only for VS->PS because other stages don't need it. + */ + if (((stage == MESA_SHADER_VERTEX && + !ctx->options->key.vs.as_ls && + !ctx->options->key.vs.as_es && + !ctx->is_gs_copy_shader) || + (stage == MESA_SHADER_TESS_EVAL && + !ctx->options->key.tes.as_es)) && + shader->info.clip_distance_array_size > 4) + mask_attribs |= 1ull << VARYING_SLOT_CLIP_DIST1; } } @@ -2569,6 +2595,8 @@ handle_vs_outputs_post(struct radv_shader_context *ctx, if (i != VARYING_SLOT_LAYER && i != VARYING_SLOT_PRIMITIVE_ID && + i != VARYING_SLOT_CLIP_DIST0 && + i != VARYING_SLOT_CLIP_DIST1 && i < VARYING_SLOT_VAR0) continue; @@ -2590,6 +2618,13 @@ handle_vs_outputs_post(struct radv_shader_context *ctx, ctx->shader_info->info.gs.output_usage_mask[i]; } + if (i == VARYING_SLOT_CLIP_DIST0 || + i == VARYING_SLOT_CLIP_DIST1) { + /* The output usage mask is wrong for clip distances. + * Use all channels. */ + output_usage_mask = 0xf; + } + radv_export_param(ctx, param_count, values, output_usage_mask); outinfo->vs_output_param_offset[i] = param_count++; diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index e63c481d1e..21a8b0c5e9 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -3052,6 +3052,21 @@ radv_pipeline_generate_ps_inputs(struct radeon_cmdbuf *cs, ps_offset++; } + if (ps->info.info.ps.has_clipdist) { + unsigned vs_offset = outinfo->vs_output_param_offset[VARYING_SLOT_CLIP_DIST0]; + + if (vs_offset != AC_EXP_PARAM_UNDEFINED) { + ps_input_cntl[ps_offset] = offset_to_ps_input(vs_offset, true); + ++ps_offset; + } + + vs_offset = outinfo->vs_output_param_offset[VARYING_SLOT_CLIP_DIST1]; + if (vs_offset != AC_EXP_PARAM_UNDEFINED) { + ps_input_cntl[ps_offset] = offset_to_ps_input(vs_offset, true); + ++ps_offset; + } + } + for (unsigned i = 0; i < 32 && (1u << i) <= ps->info.fs.input_mask; ++i) { unsigned vs_offset; bool flat_shade; diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h index 03760b689c..c60185cd93 100644 --- a/src/amd/vulkan/radv_shader.h +++ b/src/amd/vulkan/radv_shader.h @@ -174,6 +174,7 @@ struct radv_shader_info { bool has_pcoord; bool prim_id_input; bool layer_input; + bool has_clipdist; } ps; struct { bool uses_grid_size; diff --git a/src/amd/vulkan/radv_shader_info.c b/src/amd/vulkan/radv_shader_info.c index 8026cca46c..a9b36d8ba8 100644 --- a/src/amd/vulkan/radv_shader_info.c +++ b/src/amd/vulkan/radv_shader_info.c @@ -127,6 +127,14 @@ gather_intrinsic_store_deref_info(const nir_shader *nir, unsigned comp = var->data.location_frac; unsigned const_offset = 0; + if (idx == VARYING_SLOT_CLIP_DIST0 || + idx == VARYING_SLOT_CLIP_DIST1) { + /* FIXME: Gathering the output usage mask for clip distances + * is currently broken, we will always use 0xf. + */ + return; + } + get_deref_offset(nir_instr_as_deref(instr->src[0].ssa->parent_instr), &const_offset); switch (nir->info.stage) { @@ -354,6 +362,9 @@ gather_info_input_decl_ps(const nir_shader *nir, const nir_variable *var, case VARYING_SLOT_LAYER: info->ps.layer_input = true; break; + case VARYING_SLOT_CLIP_DIST0: + info->ps.has_clipdist = true; + break; default: break; } -- 2.18.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev