radeonsi: use si_set_rw_shader_buffer for setting streamout buffers
[mesa.git] / src / gallium / drivers / radeonsi / si_state_viewport.c
index c69a56dffaed9443d93e05fd881ffa7d123802c0..76c56447eb03b8a0147ec6cc88935f76e08fd52f 100644 (file)
@@ -107,6 +107,7 @@ static void si_scissor_make_union(struct si_signed_scissor *out,
        out->miny = MIN2(out->miny, in->miny);
        out->maxx = MAX2(out->maxx, in->maxx);
        out->maxy = MAX2(out->maxy, in->maxy);
+       out->quant_mode = MIN2(out->quant_mode, in->quant_mode);
 }
 
 static void si_emit_one_scissor(struct si_context *ctx,
@@ -145,9 +146,6 @@ static void si_emit_one_scissor(struct si_context *ctx,
                        S_028254_BR_Y(final.maxy));
 }
 
-/* the range is [-MAX, MAX] */
-#define SI_MAX_VIEWPORT_RANGE 32768
-
 static void si_emit_guardband(struct si_context *ctx)
 {
        const struct si_state_rasterizer *rs = ctx->queued.named.rasterizer;
@@ -168,21 +166,28 @@ static void si_emit_guardband(struct si_context *ctx)
                vp_as_scissor = ctx->viewports.as_scissor[0];
        }
 
+       /* Blits don't set the viewport state. The vertex shader determines
+        * the viewport size by scaling the coordinates, so we don't know
+        * how large the viewport is. Assume the worst case.
+        */
+       if (ctx->vs_disables_clipping_viewport)
+               vp_as_scissor.quant_mode = SI_QUANT_MODE_16_8_FIXED_POINT_1_256TH;
+
        /* Determine the optimal hardware screen offset to center the viewport
         * within the viewport range in order to maximize the guardband size.
         */
-       int hw_screen_offset_x = (vp_as_scissor.maxx - vp_as_scissor.minx) / 2;
-       int hw_screen_offset_y = (vp_as_scissor.maxy - vp_as_scissor.miny) / 2;
+       int hw_screen_offset_x = (vp_as_scissor.maxx + vp_as_scissor.minx) / 2;
+       int hw_screen_offset_y = (vp_as_scissor.maxy + vp_as_scissor.miny) / 2;
 
        const unsigned hw_screen_offset_max = 8176;
        /* SI-CI need to align the offset to an ubertile consisting of all SEs. */
        const unsigned hw_screen_offset_alignment =
                ctx->chip_class >= VI ? 16 : MAX2(ctx->screen->se_tile_repeat, 16);
 
-       hw_screen_offset_x = MIN2(hw_screen_offset_x, hw_screen_offset_max);
-       hw_screen_offset_y = MIN2(hw_screen_offset_y, hw_screen_offset_max);
+       hw_screen_offset_x = CLAMP(hw_screen_offset_x, 0, hw_screen_offset_max);
+       hw_screen_offset_y = CLAMP(hw_screen_offset_y, 0, hw_screen_offset_max);
 
-       /* Align the screen offset by dropping the low bits. */
+       /* Align the screen offset by dropping the low bits. */
        hw_screen_offset_x &= ~(hw_screen_offset_alignment - 1);
        hw_screen_offset_y &= ~(hw_screen_offset_alignment - 1);
 
@@ -211,9 +216,11 @@ static void si_emit_guardband(struct si_context *ctx)
         * This is done by applying the inverse viewport transformation
         * on the viewport limits to get those limits in clip space.
         *
-        * Use a limit one pixel smaller to allow for some precision error.
+        * The viewport range is [-max_viewport_size/2, max_viewport_size/2].
         */
-       max_range = SI_MAX_VIEWPORT_RANGE - 1;
+       static unsigned max_viewport_size[] = {65535, 16383, 4095};
+       assert(vp_as_scissor.quant_mode < ARRAY_SIZE(max_viewport_size));
+       max_range = max_viewport_size[vp_as_scissor.quant_mode] / 2;
        left   = (-max_range - vp.translate[0]) / vp.scale[0];
        right  = ( max_range - vp.translate[0]) / vp.scale[0];
        top    = (-max_range - vp.translate[1]) / vp.scale[1];
@@ -251,6 +258,7 @@ static void si_emit_guardband(struct si_context *ctx)
         * R_028BE8_PA_CL_GB_VERT_CLIP_ADJ, R_028BEC_PA_CL_GB_VERT_DISC_ADJ
         * R_028BF0_PA_CL_GB_HORZ_CLIP_ADJ, R_028BF4_PA_CL_GB_HORZ_DISC_ADJ
         */
+       unsigned initial_cdw = ctx->gfx_cs->current.cdw;
        radeon_opt_set_context_reg4(ctx, R_028BE8_PA_CL_GB_VERT_CLIP_ADJ,
                                    SI_TRACKED_PA_CL_GB_VERT_CLIP_ADJ,
                                    fui(guardband_y), fui(discard_y),
@@ -262,7 +270,10 @@ static void si_emit_guardband(struct si_context *ctx)
        radeon_opt_set_context_reg(ctx, R_028BE4_PA_SU_VTX_CNTL,
                                   SI_TRACKED_PA_SU_VTX_CNTL,
                                   S_028BE4_PIX_CENTER(rs->half_pixel_center) |
-                                  S_028BE4_QUANT_MODE(V_028BE4_X_16_8_FIXED_POINT_1_256TH));
+                                  S_028BE4_QUANT_MODE(V_028BE4_X_16_8_FIXED_POINT_1_256TH +
+                                                      vp_as_scissor.quant_mode));
+       if (initial_cdw != ctx->gfx_cs->current.cdw)
+               ctx->context_roll_counter++;
 }
 
 static void si_emit_scissors(struct si_context *ctx)
@@ -311,10 +322,33 @@ static void si_set_viewport_states(struct pipe_context *pctx,
 
        for (i = 0; i < num_viewports; i++) {
                unsigned index = start_slot + i;
+               struct si_signed_scissor *scissor = &ctx->viewports.as_scissor[index];
 
                ctx->viewports.states[index] = state[i];
-               si_get_scissor_from_viewport(ctx, &state[i],
-                                            &ctx->viewports.as_scissor[index]);
+
+               si_get_scissor_from_viewport(ctx, &state[i], scissor);
+
+               unsigned w = scissor->maxx - scissor->minx;
+               unsigned h = scissor->maxy - scissor->miny;
+               unsigned max_extent = MAX2(w, h);
+
+               /* Determine the best quantization mode (subpixel precision),
+                * but also leave enough space for the guardband.
+                *
+                * Note that primitive binning requires QUANT_MODE == 16_8 on Vega10
+                * and Raven1. What we do depends on the chip:
+                * - Vega10: Never use primitive binning.
+                * - Raven1: Always use QUANT_MODE == 16_8.
+                */
+               if (ctx->family == CHIP_RAVEN)
+                       max_extent = 16384; /* Use QUANT_MODE == 16_8. */
+
+               if (max_extent <= 1024) /* 4K scanline area for guardband */
+                       scissor->quant_mode = SI_QUANT_MODE_12_12_FIXED_POINT_1_4096TH;
+               else if (max_extent <= 4096) /* 16K scanline area for guardband */
+                       scissor->quant_mode = SI_QUANT_MODE_14_10_FIXED_POINT_1_1024TH;
+               else /* 64K scanline area for guardband */
+                       scissor->quant_mode = SI_QUANT_MODE_16_8_FIXED_POINT_1_256TH;
        }
 
        mask = ((1 << num_viewports) - 1) << start_slot;
@@ -565,4 +599,7 @@ void si_init_viewport_functions(struct si_context *ctx)
        ctx->b.set_scissor_states = si_set_scissor_states;
        ctx->b.set_viewport_states = si_set_viewport_states;
        ctx->b.set_window_rectangles = si_set_window_rectangles;
+
+       for (unsigned i = 0; i < 16; i++)
+               ctx->viewports.as_scissor[i].quant_mode = SI_QUANT_MODE_16_8_FIXED_POINT_1_256TH;
 }