From 6f47df312943b05653efc0494551ebf8c3903d43 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Wed, 29 Aug 2018 22:13:52 +0200 Subject: [PATCH] radv: fix passing clip/cull distances from VS to PS CTS doesn't test input clip/cull distances for the fragment shader stage, which explains why this was totally broken. I wrote a simple test locally that works now. This fixes a crash with GTA V and DXVK. Note that we are exporting unused parameters from the vertex shader now, but this can't be optimized easily because we don't keep the fragment shader info... Cc: mesa-stable@lists.freedesktop.org Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107477 Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen --- src/amd/vulkan/radv_nir_to_llvm.c | 30 +++++++++++++++++++++++++++++- src/amd/vulkan/radv_pipeline.c | 17 +++++++++++++++++ src/amd/vulkan/radv_shader.h | 1 + src/amd/vulkan/radv_shader_info.c | 4 ++++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/amd/vulkan/radv_nir_to_llvm.c b/src/amd/vulkan/radv_nir_to_llvm.c index 4940e3230f9..d7cd8cc0699 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,15 @@ 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 components inside the array + * of clip/cull distances because this might wrongly set other + * bits like primitive ID or layer. + */ + mask = 1ull << VARYING_SLOT_CLIP_DIST0; + } + + ctx->input_mask |= mask; } static void @@ -2187,6 +2197,17 @@ handle_fs_inputs(struct radv_shader_context *ctx, if (LLVMIsUndef(interp_param)) ctx->shader_info->fs.flat_shaded_mask |= 1u << index; ++index; + } else if (i == VARYING_SLOT_CLIP_DIST0) { + int length = ctx->shader_info->info.ps.num_input_clips_culls; + + for (unsigned j = 0; j < length; j += 4) { + inputs = ctx->inputs + ac_llvm_reg_index_soa(i, j); + + interp_param = *inputs; + interp_fs_input(ctx, index, interp_param, + ctx->abi.prim_mask, inputs); + ++index; + } } else if (i == VARYING_SLOT_POS) { for(int i = 0; i < 3; ++i) inputs[i] = ctx->abi.frag_pos[i]; @@ -2482,6 +2503,13 @@ handle_vs_outputs_post(struct radv_shader_context *ctx, memcpy(&pos_args[target - V_008DFC_SQ_EXP_POS], &args, sizeof(args)); + /* Export the clip/cull distances values to the next stage. */ + radv_export_param(ctx, param_count, &slots[0], 0xf); + outinfo->vs_output_param_offset[VARYING_SLOT_CLIP_DIST0] = param_count++; + if (ctx->num_output_clips + ctx->num_output_culls > 4) { + radv_export_param(ctx, param_count, &slots[4], 0xf); + outinfo->vs_output_param_offset[VARYING_SLOT_CLIP_DIST1] = param_count++; + } } LLVMValueRef pos_values[4] = {ctx->ac.f32_0, ctx->ac.f32_0, ctx->ac.f32_0, ctx->ac.f32_1}; diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index e63c481d1e7..13477231a4f 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -3052,6 +3052,23 @@ radv_pipeline_generate_ps_inputs(struct radeon_cmdbuf *cs, ps_offset++; } + if (ps->info.info.ps.num_input_clips_culls) { + unsigned vs_offset; + + 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->info.info.ps.num_input_clips_culls > 4) { + 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 03760b689c3..897e2fc5e19 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; + uint8_t num_input_clips_culls; } 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 8026cca46c8..a45c847c46c 100644 --- a/src/amd/vulkan/radv_shader_info.c +++ b/src/amd/vulkan/radv_shader_info.c @@ -341,6 +341,7 @@ static void gather_info_input_decl_ps(const nir_shader *nir, const nir_variable *var, struct radv_shader_info *info) { + unsigned attrib_count = glsl_count_attribute_slots(var->type, false); const struct glsl_type *type = glsl_without_array(var->type); int idx = var->data.location; @@ -354,6 +355,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.num_input_clips_culls = attrib_count; + break; default: break; } -- 2.30.2