From: Marek Olšák <marek.ol...@amd.com>

Cc: 17.1 <mesa-sta...@lists.freedesktop.org>
---
 src/gallium/drivers/radeonsi/si_shader.c        | 43 +++++++++++++++++++++----
 src/gallium/drivers/radeonsi/si_state_shaders.c | 13 ++++++--
 2 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_shader.c 
b/src/gallium/drivers/radeonsi/si_shader.c
index aa5ba8d..f19073d 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -2374,22 +2374,22 @@ handle_semantic:
                pos_args[0].out[3] = base->one;  /* W */
        }
 
        /* Write the misc vector (point size, edgeflag, layer, viewport). */
        if (shader->selector->info.writes_psize ||
            shader->selector->info.writes_edgeflag ||
            shader->selector->info.writes_viewport_index ||
            shader->selector->info.writes_layer) {
                pos_args[1].enabled_channels = 
shader->selector->info.writes_psize |
                                               
(shader->selector->info.writes_edgeflag << 1) |
-                                              
(shader->selector->info.writes_layer << 2) |
-                                              
(shader->selector->info.writes_viewport_index << 3);
+                                              
(shader->selector->info.writes_layer << 2);
+
                pos_args[1].valid_mask = 0; /* EXEC mask */
                pos_args[1].done = 0; /* last export? */
                pos_args[1].target = V_008DFC_SQ_EXP_POS + 1;
                pos_args[1].compr = 0; /* COMPR flag */
                pos_args[1].out[0] = base->zero; /* X */
                pos_args[1].out[1] = base->zero; /* Y */
                pos_args[1].out[2] = base->zero; /* Z */
                pos_args[1].out[3] = base->zero; /* W */
 
                if (shader->selector->info.writes_psize)
@@ -2404,25 +2404,56 @@ handle_semantic:
                        edgeflag_value = lp_build_min(&bld_base->int_bld,
                                                      edgeflag_value,
                                                      ctx->i32_1);
 
                        /* The LLVM intrinsic expects a float. */
                        pos_args[1].out[1] = 
LLVMBuildBitCast(ctx->gallivm.builder,
                                                          edgeflag_value,
                                                          ctx->f32, "");
                }
 
-               if (shader->selector->info.writes_layer)
-                       pos_args[1].out[2] = layer_value;
+               if (ctx->screen->b.chip_class >= GFX9) {
+                       /* GFX9 has the layer in out.z[10:0] and the viewport
+                        * index in out.z[19:16].
+                        */
+                       if (shader->selector->info.writes_layer) {
+                               LLVMValueRef v = layer_value;
+
+                               v = bitcast(bld_base, TGSI_TYPE_UNSIGNED, v);
+                               v = LLVMBuildAnd(ctx->gallivm.builder, v,
+                                                LLVMConstInt(ctx->i32, 0x7ff, 
0), "");
+                               pos_args[1].out[2] = bitcast(bld_base, 
TGSI_TYPE_FLOAT, v);
+                       }
+
+                       if (shader->selector->info.writes_viewport_index) {
+                               LLVMValueRef v = viewport_index_value;
+
+                               v = bitcast(bld_base, TGSI_TYPE_UNSIGNED, v);
+                               v = LLVMBuildAnd(ctx->gallivm.builder, v,
+                                                LLVMConstInt(ctx->i32, 0xf, 
0), "");
+                               v = LLVMBuildShl(ctx->gallivm.builder, v,
+                                                LLVMConstInt(ctx->i32, 16, 0), 
"");
+                               v = LLVMBuildOr(ctx->gallivm.builder, v,
+                                               bitcast(bld_base, 
TGSI_TYPE_UNSIGNED,
+                                                       pos_args[1].out[2]), 
"");
+                               pos_args[1].out[2] = bitcast(bld_base, 
TGSI_TYPE_FLOAT, v);
+                               pos_args[1].enabled_channels |= 1 << 2;
+                       }
+               } else {
+                       if (shader->selector->info.writes_layer)
+                               pos_args[1].out[2] = layer_value;
 
-               if (shader->selector->info.writes_viewport_index)
-                       pos_args[1].out[3] = viewport_index_value;
+                       if (shader->selector->info.writes_viewport_index) {
+                               pos_args[1].out[3] = viewport_index_value;
+                               pos_args[1].enabled_channels |= 1 << 3;
+                       }
+               }
        }
 
        for (i = 0; i < 4; i++)
                if (pos_args[i].out[0])
                        shader->info.nr_pos_exports++;
 
        pos_idx = 0;
        for (i = 0; i < 4; i++) {
                if (!pos_args[i].out[0])
                        continue;
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c 
b/src/gallium/drivers/radeonsi/si_state_shaders.c
index a5260f5..8c09ff1 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -850,22 +850,31 @@ static void si_shader_vs(struct si_screen *sscreen, 
struct si_shader *shader,
                return;
 
        /* We always write VGT_GS_MODE in the VS state, because every switch
         * between different shader pipelines involving a different GS or no
         * GS at all involves a switch of the VS (different GS use different
         * copy shaders). On the other hand, when the API switches from a GS to
         * no GS and then back to the same GS used originally, the GS state is
         * not sent again.
         */
        if (!gs) {
-               si_pm4_set_reg(pm4, R_028A40_VGT_GS_MODE,
-                              S_028A40_MODE(enable_prim_id ? 
V_028A40_GS_SCENARIO_A : 0));
+               unsigned mode = 0;
+
+               /* PrimID needs GS scenario A.
+                * GFX9 also needs it when ViewportIndex is enabled.
+                */
+               if (enable_prim_id ||
+                   (sscreen->b.chip_class >= GFX9 &&
+                    shader->selector->info.writes_viewport_index))
+                       mode = V_028A40_GS_SCENARIO_A;
+
+               si_pm4_set_reg(pm4, R_028A40_VGT_GS_MODE, S_028A40_MODE(mode));
                si_pm4_set_reg(pm4, R_028A84_VGT_PRIMITIVEID_EN, 
enable_prim_id);
        } else {
                si_pm4_set_reg(pm4, R_028A40_VGT_GS_MODE, si_vgt_gs_mode(gs));
                si_pm4_set_reg(pm4, R_028A84_VGT_PRIMITIVEID_EN, 0);
        }
 
        va = shader->bo->gpu_address;
        si_pm4_add_bo(pm4, shader->bo, RADEON_USAGE_READ, 
RADEON_PRIO_SHADER_BINARY);
 
        if (gs) {
-- 
2.7.4

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

Reply via email to