Module: Mesa
Branch: master
Commit: 180c1b924e1ed3a2918fad9c5cbb653524de8233
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=180c1b924e1ed3a2918fad9c5cbb653524de8233

Author: Bas Nieuwenhuizen <b...@basnieuwenhuizen.nl>
Date:   Wed Aug 16 09:09:56 2017 +0200

ac/nir: Add shader support for multiviews.

It uses an user SGPR to pass the view index to the shaders, except
for the fragment shader where we use layer=view (which comes in
handy when we want to do the NV ext that allows us to execute pre-FS
stages once instead of per view).

Reviewed-by: Dave Airlie <airl...@redhat.com>

---

 src/amd/common/ac_nir_to_llvm.c | 38 +++++++++++++++++++++++++++++++++++++-
 src/amd/common/ac_nir_to_llvm.h |  4 +++-
 src/amd/common/ac_shader_info.c |  3 +++
 src/amd/common/ac_shader_info.h |  1 +
 4 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c
index c0c4f3a78d..664d83bd2e 100644
--- a/src/amd/common/ac_nir_to_llvm.c
+++ b/src/amd/common/ac_nir_to_llvm.c
@@ -90,6 +90,7 @@ struct nir_to_llvm_context {
        LLVMValueRef descriptor_sets[AC_UD_MAX_SETS];
        LLVMValueRef ring_offsets;
        LLVMValueRef push_constants;
+       LLVMValueRef view_index;
        LLVMValueRef num_work_groups;
        LLVMValueRef workgroup_ids;
        LLVMValueRef local_invocation_ids;
@@ -744,6 +745,8 @@ static void create_function(struct nir_to_llvm_context *ctx)
                        if (ctx->shader_info->info.vs.needs_draw_id)
                                add_user_sgpr_argument(&args, ctx->i32, 
&ctx->abi.draw_id); // draw id
                }
+               if (ctx->shader_info->info.needs_multiview_view_index || 
(!ctx->options->key.vs.as_es && !ctx->options->key.vs.as_ls && 
ctx->options->key.has_multiview_view_index))
+                       add_user_sgpr_argument(&args, ctx->i32, 
&ctx->view_index);
                if (ctx->options->key.vs.as_es)
                        add_sgpr_argument(&args, ctx->i32, &ctx->es2gs_offset); 
// es2gs offset
                else if (ctx->options->key.vs.as_ls)
@@ -760,6 +763,8 @@ static void create_function(struct nir_to_llvm_context *ctx)
                add_user_sgpr_argument(&args, ctx->i32, &ctx->tcs_out_offsets); 
// tcs out offsets
                add_user_sgpr_argument(&args, ctx->i32, &ctx->tcs_out_layout); 
// tcs out layout
                add_user_sgpr_argument(&args, ctx->i32, &ctx->tcs_in_layout); 
// tcs in layout
+               if (ctx->shader_info->info.needs_multiview_view_index)
+                       add_user_sgpr_argument(&args, ctx->i32, 
&ctx->view_index);
                add_sgpr_argument(&args, ctx->i32, &ctx->oc_lds); // param oc 
lds
                add_sgpr_argument(&args, ctx->i32, &ctx->tess_factor_offset); 
// tess factor offset
                add_vgpr_argument(&args, ctx->i32, &ctx->tcs_patch_id); // 
patch id
@@ -767,6 +772,8 @@ static void create_function(struct nir_to_llvm_context *ctx)
                break;
        case MESA_SHADER_TESS_EVAL:
                add_user_sgpr_argument(&args, ctx->i32, 
&ctx->tcs_offchip_layout); // tcs offchip layout
+               if (ctx->shader_info->info.needs_multiview_view_index || 
(!ctx->options->key.tes.as_es && ctx->options->key.has_multiview_view_index))
+                       add_user_sgpr_argument(&args, ctx->i32, 
&ctx->view_index);
                if (ctx->options->key.tes.as_es) {
                        add_sgpr_argument(&args, ctx->i32, &ctx->oc_lds); // OC 
LDS
                        add_sgpr_argument(&args, ctx->i32, NULL); //
@@ -783,6 +790,8 @@ static void create_function(struct nir_to_llvm_context *ctx)
        case MESA_SHADER_GEOMETRY:
                add_user_sgpr_argument(&args, ctx->i32, 
&ctx->gsvs_ring_stride); // gsvs stride
                add_user_sgpr_argument(&args, ctx->i32, 
&ctx->gsvs_num_entries); // gsvs num entires
+               if (ctx->shader_info->info.needs_multiview_view_index)
+                       add_user_sgpr_argument(&args, ctx->i32, 
&ctx->view_index);
                add_sgpr_argument(&args, ctx->i32, &ctx->gs2vs_offset); // 
gs2vs offset
                add_sgpr_argument(&args, ctx->i32, &ctx->gs_wave_id); // wave id
                add_vgpr_argument(&args, ctx->i32, &ctx->gs_vtx_offset[0]); // 
vtx0
@@ -894,6 +903,8 @@ static void create_function(struct nir_to_llvm_context *ctx)
 
                        set_userdata_location_shader(ctx, 
AC_UD_VS_BASE_VERTEX_START_INSTANCE, &user_sgpr_idx, vs_num);
                }
+               if (ctx->view_index)
+                       set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, 
&user_sgpr_idx, 1);
                if (ctx->options->key.vs.as_ls) {
                        set_userdata_location_shader(ctx, 
AC_UD_VS_LS_TCS_IN_LAYOUT, &user_sgpr_idx, 1);
                }
@@ -902,13 +913,19 @@ static void create_function(struct nir_to_llvm_context 
*ctx)
                break;
        case MESA_SHADER_TESS_CTRL:
                set_userdata_location_shader(ctx, AC_UD_TCS_OFFCHIP_LAYOUT, 
&user_sgpr_idx, 4);
+               if (ctx->view_index)
+                       set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, 
&user_sgpr_idx, 1);
                declare_tess_lds(ctx);
                break;
        case MESA_SHADER_TESS_EVAL:
                set_userdata_location_shader(ctx, AC_UD_TES_OFFCHIP_LAYOUT, 
&user_sgpr_idx, 1);
+               if (ctx->view_index)
+                       set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, 
&user_sgpr_idx, 1);
                break;
        case MESA_SHADER_GEOMETRY:
                set_userdata_location_shader(ctx, 
AC_UD_GS_VS_RING_STRIDE_ENTRIES, &user_sgpr_idx, 2);
+               if (ctx->view_index)
+                       set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, 
&user_sgpr_idx, 1);
                break;
        case MESA_SHADER_FRAGMENT:
                if (ctx->shader_info->info.ps.needs_sample_positions) {
@@ -4022,6 +4039,9 @@ static void visit_intrinsic(struct ac_nir_context *ctx,
        case nir_intrinsic_load_draw_id:
                result = ctx->abi->draw_id;
                break;
+       case nir_intrinsic_load_view_index:
+               result = ctx->nctx->view_index ? ctx->nctx->view_index : 
ctx->ac.i32_0;
+               break;
        case nir_intrinsic_load_invocation_id:
                if (ctx->stage == MESA_SHADER_TESS_CTRL)
                        result = unpack_param(&ctx->ac, ctx->nctx->tcs_rel_ids, 
8, 5);
@@ -5068,7 +5088,8 @@ handle_fs_inputs(struct nir_to_llvm_context *ctx,
 
        unsigned index = 0;
 
-       if (ctx->shader_info->info.ps.uses_input_attachments)
+       if (ctx->shader_info->info.ps.uses_input_attachments ||
+           ctx->shader_info->info.needs_multiview_view_index)
                ctx->input_mask |= 1ull << VARYING_SLOT_LAYER;
 
        for (unsigned i = 0; i < RADEON_LLVM_MAX_INPUTS; ++i) {
@@ -5103,6 +5124,9 @@ handle_fs_inputs(struct nir_to_llvm_context *ctx,
        if (ctx->input_mask & (1 << VARYING_SLOT_LAYER))
                ctx->shader_info->fs.layer_input = true;
        ctx->shader_info->fs.input_mask = ctx->input_mask >> VARYING_SLOT_VAR0;
+
+       if (ctx->shader_info->info.needs_multiview_view_index)
+               ctx->view_index = 
ctx->inputs[radeon_llvm_reg_index_soa(VARYING_SLOT_LAYER, 0)];
 }
 
 static LLVMValueRef
@@ -5507,6 +5531,18 @@ handle_vs_outputs_post(struct nir_to_llvm_context *ctx,
        LLVMValueRef psize_value = NULL, layer_value = NULL, 
viewport_index_value = NULL;
        int i;
 
+       if (ctx->options->key.has_multiview_view_index) {
+               LLVMValueRef* tmp_out = 
&ctx->nir->outputs[radeon_llvm_reg_index_soa(VARYING_SLOT_LAYER, 0)];
+               if(!*tmp_out) {
+                       for(unsigned i = 0; i < 4; ++i)
+                               
ctx->nir->outputs[radeon_llvm_reg_index_soa(VARYING_SLOT_LAYER, i)] =
+                                           si_build_alloca_undef(&ctx->ac, 
ctx->ac.f32, "");
+               }
+
+               LLVMBuildStore(ctx->builder, to_float(&ctx->ac, 
ctx->view_index),  *tmp_out);
+               ctx->output_mask |= 1ull << VARYING_SLOT_LAYER;
+       }
+
        memset(outinfo->vs_output_param_offset, AC_EXP_PARAM_UNDEFINED,
               sizeof(outinfo->vs_output_param_offset));
 
diff --git a/src/amd/common/ac_nir_to_llvm.h b/src/amd/common/ac_nir_to_llvm.h
index a6e01782ba..6621d7bc5a 100644
--- a/src/amd/common/ac_nir_to_llvm.h
+++ b/src/amd/common/ac_nir_to_llvm.h
@@ -70,6 +70,7 @@ struct ac_shader_variant_key {
                struct ac_tes_variant_key tes;
                struct ac_tcs_variant_key tcs;
        };
+       bool has_multiview_view_index;
 };
 
 struct ac_nir_compiler_options {
@@ -92,7 +93,8 @@ enum ac_ud_index {
        AC_UD_SCRATCH_RING_OFFSETS = 0,
        AC_UD_PUSH_CONSTANTS = 1,
        AC_UD_INDIRECT_DESCRIPTOR_SETS = 2,
-       AC_UD_SHADER_START = 3,
+       AC_UD_VIEW_INDEX = 3,
+       AC_UD_SHADER_START = 4,
        AC_UD_VS_VERTEX_BUFFERS = AC_UD_SHADER_START,
        AC_UD_VS_BASE_VERTEX_START_INSTANCE,
        AC_UD_VS_LS_TCS_IN_LAYOUT,
diff --git a/src/amd/common/ac_shader_info.c b/src/amd/common/ac_shader_info.c
index ca59965e2d..979b120b73 100644
--- a/src/amd/common/ac_shader_info.c
+++ b/src/amd/common/ac_shader_info.c
@@ -51,6 +51,9 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, struct 
ac_shader_info *info)
        case nir_intrinsic_load_sample_pos:
                info->ps.force_persample = true;
                break;
+       case nir_intrinsic_load_view_index:
+               info->needs_multiview_view_index = true;
+               break;
        case nir_intrinsic_vulkan_resource_index:
                info->desc_set_used_mask |= (1 << 
nir_intrinsic_desc_set(instr));
                break;
diff --git a/src/amd/common/ac_shader_info.h b/src/amd/common/ac_shader_info.h
index 886b5e84b5..c1d36a667e 100644
--- a/src/amd/common/ac_shader_info.h
+++ b/src/amd/common/ac_shader_info.h
@@ -30,6 +30,7 @@ struct ac_nir_compiler_options;
 struct ac_shader_info {
        bool needs_push_constants;
        uint32_t desc_set_used_mask;
+       bool needs_multiview_view_index;
        struct {
                bool has_vertex_buffers; /* needs vertex buffers and base/start 
*/
                bool needs_draw_id;

_______________________________________________
mesa-commit mailing list
mesa-commit@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to