radv: fix passing clip/cull distances from VS to PS
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Wed, 29 Aug 2018 20:13:52 +0000 (22:13 +0200)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Fri, 31 Aug 2018 15:34:36 +0000 (17:34 +0200)
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 <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
src/amd/vulkan/radv_nir_to_llvm.c
src/amd/vulkan/radv_pipeline.c
src/amd/vulkan/radv_shader.h
src/amd/vulkan/radv_shader_info.c

index 4940e3230f9045aab9ecb796266c34f26af44549..d7cd8cc0699a0e0fddf8cdd3b4e888dd13a5c3fd 100644 (file)
@@ -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};
index e63c481d1e74454b6b7a591d82a0d837fd21e795..13477231a4f2a8433c73601daea4fe58eb9c8c54 100644 (file)
@@ -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;
index 03760b689c33c71afaa6bbae5e6b762fb904afff..897e2fc5e19b3a9e066038da652e0252f79449b9 100644 (file)
@@ -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;
index 8026cca46c868ebe518ff9ab15a8709a56baf8ce..a45c847c46c0b5d5e19bab42afb9c622d477135b 100644 (file)
@@ -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;
        }