radeonsi: disable NGG culling on gfx10.3 because of hangs
[mesa.git] / src / gallium / drivers / radeonsi / si_pipe.c
index 7fdbfa24c574ab6b70f1f6a27e4bcd6eed6f38c2..2bd96eaef1cbbe53ea8f132e68d5a0454f9d24cd 100644 (file)
@@ -33,6 +33,7 @@
 #include "si_public.h"
 #include "si_shader_internal.h"
 #include "sid.h"
+#include "ac_shadowed_regs.h"
 #include "util/disk_cache.h"
 #include "util/u_log.h"
 #include "util/u_memory.h"
@@ -90,11 +91,13 @@ static const struct debug_named_value debug_options[] = {
    {"check_vm", DBG(CHECK_VM), "Check VM faults and dump debug info."},
    {"reserve_vmid", DBG(RESERVE_VMID), "Force VMID reservation per context."},
    {"zerovram", DBG(ZERO_VRAM), "Clear VRAM allocations."},
+   {"shadowregs", DBG(SHADOW_REGS), "Enable CP register shadowing."},
 
    /* 3D engine options: */
    {"nogfx", DBG(NO_GFX), "Disable graphics. Only multimedia compute paths can be used."},
    {"nongg", DBG(NO_NGG), "Disable NGG and use the legacy pipeline."},
-   {"nggc", DBG(ALWAYS_NGG_CULLING), "Always use NGG culling even when it can hurt."},
+   {"nggc", DBG(ALWAYS_NGG_CULLING_ALL), "Always use NGG culling even when it can hurt."},
+   {"nggctess", DBG(ALWAYS_NGG_CULLING_TESS), "Always use NGG culling for tessellation."},
    {"nonggc", DBG(NO_NGG_CULLING), "Disable NGG culling."},
    {"alwayspd", DBG(ALWAYS_PD), "Always enable the primitive discard compute shader."},
    {"pd", DBG(PD), "Enable the primitive discard compute shader for large draw calls."},
@@ -141,8 +144,8 @@ void si_init_compiler(struct si_screen *sscreen, struct ac_llvm_compiler *compil
 
    enum ac_target_machine_options tm_options =
       (sscreen->debug_flags & DBG(GISEL) ? AC_TM_ENABLE_GLOBAL_ISEL : 0) |
-      (sscreen->info.chip_class >= GFX9 ? AC_TM_FORCE_ENABLE_XNACK : 0) |
-      (sscreen->info.chip_class < GFX9 ? AC_TM_FORCE_DISABLE_XNACK : 0) |
+      (sscreen->info.chip_class <= GFX8 ? AC_TM_FORCE_DISABLE_XNACK :
+       sscreen->info.chip_class <= GFX10 ? AC_TM_FORCE_ENABLE_XNACK : 0) |
       (!sscreen->llvm_has_working_vgpr_indexing ? AC_TM_PROMOTE_ALLOCA_TO_SCRATCH : 0) |
       (sscreen->debug_flags & DBG(CHECK_IR) ? AC_TM_CHECK_IR : 0) |
       (create_low_opt_compiler ? AC_TM_CREATE_LOW_OPT : 0);
@@ -194,9 +197,10 @@ static void si_destroy_context(struct pipe_context *context)
    si_resource_reference(&sctx->wait_mem_scratch, NULL);
    si_resource_reference(&sctx->small_prim_cull_info_buf, NULL);
 
-   si_pm4_free_state(sctx, sctx->init_config, ~0);
-   if (sctx->init_config_gs_rings)
-      si_pm4_free_state(sctx, sctx->init_config_gs_rings, ~0);
+   if (sctx->cs_preamble_state)
+      si_pm4_free_state(sctx, sctx->cs_preamble_state, ~0);
+   if (sctx->cs_preamble_gs_rings)
+      si_pm4_free_state(sctx, sctx->cs_preamble_gs_rings, ~0);
    for (i = 0; i < ARRAY_SIZE(sctx->vgt_shader_config); i++)
       si_pm4_delete_state(sctx, vgt_shader_config, sctx->vgt_shader_config[i]);
 
@@ -295,6 +299,7 @@ static void si_destroy_context(struct pipe_context *context)
    si_resource_reference(&sctx->index_ring, NULL);
    si_resource_reference(&sctx->barrier_buf, NULL);
    si_resource_reference(&sctx->last_ib_barrier_buf, NULL);
+   si_resource_reference(&sctx->shadowed_regs, NULL);
    pb_reference(&sctx->gds, NULL);
    pb_reference(&sctx->gds_oa, NULL);
 
@@ -322,7 +327,7 @@ static enum pipe_reset_status si_get_reset_status(struct pipe_context *ctx)
    enum pipe_reset_status status = sctx->ws->ctx_query_reset_status(sctx->ctx);
 
    if (status != PIPE_NO_RESET) {
-               /* Call the gallium frontend to set a no-op API dispatch. */
+      /* Call the gallium frontend to set a no-op API dispatch. */
       if (sctx->device_reset_callback.reset) {
          sctx->device_reset_callback.reset(sctx->device_reset_callback.data, status);
       }
@@ -478,6 +483,14 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, unsign
         *    https://gitlab.freedesktop.org/mesa/mesa/-/issues/1889
         */
        (sctx->chip_class != GFX8 || sscreen->debug_flags & DBG(FORCE_SDMA)) &&
+       /* SDMA causes corruption on gfx9 APUs:
+        *    https://gitlab.freedesktop.org/mesa/mesa/-/issues/2814
+        *
+        * While we could keep buffer copies and clears enabled, let's disable
+        * everything, because neither gfx8 nor gfx10 enable SDMA, and it's not
+        * easy to test.
+        */
+       (sctx->chip_class != GFX9 || sscreen->debug_flags & DBG(FORCE_SDMA)) &&
        /* SDMA timeouts sometimes on gfx10 so disable it for now. See:
         *    https://bugs.freedesktop.org/show_bug.cgi?id=111481
         *    https://gitlab.freedesktop.org/mesa/mesa/-/issues/1907
@@ -598,13 +611,12 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, unsign
    }
 
    if (sctx->chip_class >= GFX9 || si_compute_prim_discard_enabled(sctx)) {
-      sctx->wait_mem_scratch = si_resource(pipe_buffer_create(screen, 0, PIPE_USAGE_DEFAULT, 8));
+      sctx->wait_mem_scratch =
+           si_aligned_buffer_create(screen, SI_RESOURCE_FLAG_UNMAPPABLE,
+                                    PIPE_USAGE_DEFAULT, 8,
+                                    sscreen->info.tcc_cache_line_size);
       if (!sctx->wait_mem_scratch)
          goto fail;
-
-      /* Initialize the memory. */
-      si_cp_write_data(sctx, sctx->wait_mem_scratch, 0, 4, V_370_MEM, V_370_ME,
-                       &sctx->wait_mem_number);
    }
 
    /* GFX7 cannot unbind a constant buffer (S_BUFFER_LOAD doesn't skip loads
@@ -665,8 +677,21 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, unsign
    pipe_buffer_write(&sctx->b, sctx->sample_pos_buffer, 0, sizeof(sctx->sample_positions),
                      &sctx->sample_positions);
 
-   /* this must be last */
-   si_begin_new_gfx_cs(sctx);
+   /* The remainder of this function initializes the gfx CS and must be last. */
+   assert(sctx->gfx_cs->current.cdw == 0);
+
+   if (sctx->has_graphics) {
+      si_init_cp_reg_shadowing(sctx);
+   }
+
+   si_begin_new_gfx_cs(sctx, true);
+   assert(sctx->gfx_cs->current.cdw == sctx->initial_gfx_cs_size);
+
+   /* Initialize per-context buffers. */
+   if (sctx->wait_mem_scratch) {
+      si_cp_write_data(sctx, sctx->wait_mem_scratch, 0, 4, V_370_MEM, V_370_ME,
+                       &sctx->wait_mem_number);
+   }
 
    if (sctx->chip_class == GFX7) {
       /* Clear the NULL constant buffer, because loads should return zeros.
@@ -677,6 +702,8 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, unsign
       si_clear_buffer(sctx, sctx->null_const_buf.buffer, 0, sctx->null_const_buf.buffer->width0,
                       &clear_value, 4, SI_COHERENCY_SHADER, true);
    }
+
+   sctx->initial_gfx_cs_size = sctx->gfx_cs->current.cdw;
    return &sctx->b;
 fail:
    fprintf(stderr, "radeonsi: Failed to create a context.\n");
@@ -925,6 +952,12 @@ static struct pipe_screen *radeonsi_screen_create_impl(struct radeon_winsys *ws,
    sscreen->ws = ws;
    ws->query_info(ws, &sscreen->info);
 
+   if (sscreen->info.chip_class == GFX10_3 && LLVM_VERSION_MAJOR < 11) {
+      fprintf(stderr, "radeonsi: GFX 10.3 requires LLVM 11 or higher\n");
+      FREE(sscreen);
+      return NULL;
+   }
+
    if (sscreen->info.chip_class == GFX10 && LLVM_VERSION_MAJOR < 9) {
       fprintf(stderr, "radeonsi: Navi family support requires LLVM 9 or higher\n");
       FREE(sscreen);
@@ -1064,7 +1097,7 @@ static struct pipe_screen *radeonsi_screen_create_impl(struct radeon_winsys *ws,
    unsigned max_offchip_buffers_per_se;
 
    if (sscreen->info.chip_class >= GFX10)
-      max_offchip_buffers_per_se = 256;
+      max_offchip_buffers_per_se = 128;
    /* Only certain chips can use the maximum value. */
    else if (sscreen->info.family == CHIP_VEGA12 || sscreen->info.family == CHIP_VEGA20)
       max_offchip_buffers_per_se = double_offchip_buffers ? 128 : 64;
@@ -1119,11 +1152,18 @@ static struct pipe_screen *radeonsi_screen_create_impl(struct radeon_winsys *ws,
       driQueryOptionb(config->options, "radeonsi_commutative_blend_add") ||
       driQueryOptionb(config->options, "allow_draw_out_of_order");
 
+   /* TODO: Find out why NGG culling hangs on gfx10.3 */
+   if (sscreen->info.chip_class == GFX10_3 &&
+       !(sscreen->debug_flags & (DBG(ALWAYS_NGG_CULLING_ALL) | DBG(ALWAYS_NGG_CULLING_TESS))))
+      sscreen->debug_flags |= DBG(NO_NGG_CULLING);
+
    sscreen->use_ngg = sscreen->info.chip_class >= GFX10 && sscreen->info.family != CHIP_NAVI14 &&
                       !(sscreen->debug_flags & DBG(NO_NGG));
    sscreen->use_ngg_culling = sscreen->use_ngg && !(sscreen->debug_flags & DBG(NO_NGG_CULLING));
-   sscreen->always_use_ngg_culling =
-      sscreen->use_ngg_culling && sscreen->debug_flags & DBG(ALWAYS_NGG_CULLING);
+   sscreen->always_use_ngg_culling_all =
+      sscreen->use_ngg_culling && sscreen->debug_flags & DBG(ALWAYS_NGG_CULLING_ALL);
+   sscreen->always_use_ngg_culling_tess =
+      sscreen->use_ngg_culling && sscreen->debug_flags & DBG(ALWAYS_NGG_CULLING_TESS);
    sscreen->use_ngg_streamout = false;
 
    /* Only enable primitive binning on APUs by default. */
@@ -1199,11 +1239,15 @@ static struct pipe_screen *radeonsi_screen_create_impl(struct radeon_winsys *ws,
    sscreen->compute_wave_size = 64;
 
    if (sscreen->info.chip_class >= GFX10) {
-      /* Pixels shaders: Wave64 is recommended.
-       * Compute shaders: There are piglit failures with Wave32.
+      /* Pixel shaders: Wave64 is always fastest.
+       * Vertex shaders: Wave64 is probably better, because:
+       * - greater chance of L0 cache hits, because more threads are assigned
+       *   to the same CU
+       * - scalar instructions are only executed once for 64 threads instead of twice
+       * - VGPR allocation granularity is half of Wave32, so 1 Wave64 can
+       *   sometimes use fewer VGPRs than 2 Wave32
+       * - TessMark X64 with NGG culling is faster with Wave64
        */
-      sscreen->ge_wave_size = 32;
-
       if (sscreen->debug_flags & DBG(W32_GE))
          sscreen->ge_wave_size = 32;
       if (sscreen->debug_flags & DBG(W32_PS))
@@ -1251,6 +1295,8 @@ static struct pipe_screen *radeonsi_screen_create_impl(struct radeon_winsys *ws,
                                     RADEON_DOMAIN_OA);
    }
 
+   ac_print_shadowed_regs(&sscreen->info);
+
    STATIC_ASSERT(sizeof(union si_vgt_stages_key) == 4);
    return &sscreen->b;
 }