llvmpipe: add initial nir support
authorDave Airlie <airlied@redhat.com>
Thu, 5 Sep 2019 05:49:25 +0000 (15:49 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 28 Nov 2019 04:49:23 +0000 (14:49 +1000)
This adds the hooks between llvmpipe and the gallivm NIR
code, for compute and fragment shaders.

NIR support is hidden behind LP_DEBUG=nir for now until
all the intergration issues are solved

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
src/gallium/auxiliary/gallivm/lp_bld_limits.h
src/gallium/auxiliary/gallivm/lp_bld_nir.c
src/gallium/auxiliary/gallivm/lp_bld_nir.h
src/gallium/drivers/llvmpipe/SConscript
src/gallium/drivers/llvmpipe/lp_debug.h
src/gallium/drivers/llvmpipe/lp_screen.c
src/gallium/drivers/llvmpipe/lp_state_cs.c
src/gallium/drivers/llvmpipe/lp_state_fs.c
src/gallium/drivers/llvmpipe/lp_state_gs.c
src/gallium/drivers/llvmpipe/meson.build

index 91fc95e5c1118988eb43ae79f05fde6eacd44c10..014f5e84ca7a6687d486fd0230edba101a0d1ef4 100644 (file)
@@ -134,7 +134,7 @@ gallivm_get_shader_param(enum pipe_shader_cap param)
    case PIPE_SHADER_CAP_PREFERRED_IR:
       return PIPE_SHADER_IR_TGSI;
    case PIPE_SHADER_CAP_SUPPORTED_IRS:
-      return 1 << PIPE_SHADER_IR_TGSI;
+      return (1 << PIPE_SHADER_IR_TGSI) | (1 << PIPE_SHADER_IR_NIR);
    case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
    case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE:
       return 1;
index abaa82a03316f5c201bb8df44feed7967227dbf1..d69a5a4fb26d1d6e8bca5b7af818bf82628fda25 100644 (file)
@@ -1650,3 +1650,15 @@ bool lp_build_nir_llvm(
    ralloc_free(bld_base->regs);
    return true;
 }
+
+/* do some basic opts to remove some things we don't want to see. */
+void lp_build_opt_nir(struct nir_shader *nir)
+{
+   bool progress;
+   do {
+      progress = false;
+      NIR_PASS_V(nir, nir_opt_constant_folding);
+      NIR_PASS_V(nir, nir_opt_algebraic);
+   } while (progress);
+   nir_lower_bool_to_int32(nir);
+}
index b0d1671012247e5afc0ac4507b00f9e4046c9b46..194b109760c47af59952e581b6681e2d49e3c1d6 100644 (file)
@@ -192,6 +192,8 @@ bool
 lp_build_nir_llvm(struct lp_build_nir_context *bld_base,
                   struct nir_shader *nir);
 
+void lp_build_opt_nir(struct nir_shader *nir);
+
 static inline LLVMValueRef
 lp_nir_array_build_gather_values(LLVMBuilderRef builder,
                                  LLVMValueRef * values,
index 74d7a9e16730b183f70b53ce52b06cabbed62e9d..1af6867715c7c992b26cbeaf7753809bba5bf5a8 100644 (file)
@@ -18,6 +18,9 @@ llvmpipe = env.ConvenienceLibrary(
 
 env.Alias('llvmpipe', llvmpipe)
 
+env.Append(CPPPATH = [
+    '../../../compiler/nir',
+])
 
 if not env['embedded']:
     env = env.Clone()
index 1accf3b1d9287c0c12d59106cbc8d0322ad1f1fe..96af8936c5f423dc1aa7144d72b6049392c92412 100644 (file)
@@ -45,6 +45,7 @@
 #define DEBUG_MEM           0x4000
 #define DEBUG_FS            0x8000
 #define DEBUG_CS            0x10000
+#define DEBUG_NIR           0x20000
 
 /* Performance flags.  These are active even on release builds.
  */
index d2364c183d7f3414bc43379e876ab5dba5675162..c036108d318dbe9cc521def33b416e0a8fc6694f 100644 (file)
@@ -37,6 +37,7 @@
 #include "pipe/p_screen.h"
 #include "draw/draw_context.h"
 #include "gallivm/lp_bld_type.h"
+#include "gallivm/lp_bld_nir.h"
 
 #include "util/os_misc.h"
 #include "util/os_time.h"
@@ -53,6 +54,8 @@
 
 #include "state_tracker/sw_winsys.h"
 
+#include "nir.h"
+
 #ifdef DEBUG
 int LP_DEBUG = 0;
 
@@ -70,6 +73,7 @@ static const struct debug_named_value lp_debug_flags[] = {
    { "mem", DEBUG_MEM, NULL },
    { "fs", DEBUG_FS, NULL },
    { "cs", DEBUG_CS, NULL },
+   { "nir", DEBUG_NIR, NULL },
    DEBUG_NAMED_VALUE_END
 };
 #endif
@@ -366,7 +370,6 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_BINDLESS_TEXTURE:
    case PIPE_CAP_NIR_SAMPLERS_AS_DEREF:
    case PIPE_CAP_MEMOBJ:
-   case PIPE_CAP_LOAD_CONSTBUF:
    case PIPE_CAP_TGSI_ANY_REG_AS_ADDRESS:
    case PIPE_CAP_TILE_RASTER_ORDER:
    case PIPE_CAP_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
@@ -375,7 +378,6 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_CONTEXT_PRIORITY_MASK:
    case PIPE_CAP_FENCE_SIGNAL:
    case PIPE_CAP_CONSTBUF0_FLAGS:
-   case PIPE_CAP_PACKED_UNIFORMS:
    case PIPE_CAP_CONSERVATIVE_RASTER_POST_SNAP_TRIANGLES:
    case PIPE_CAP_CONSERVATIVE_RASTER_POST_SNAP_POINTS_LINES:
    case PIPE_CAP_CONSERVATIVE_RASTER_PRE_SNAP_TRIANGLES:
@@ -391,6 +393,9 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
    case PIPE_CAP_TGSI_TG4_COMPONENT_IN_SWIZZLE:
       return 1;
+   case PIPE_CAP_LOAD_CONSTBUF:
+   case PIPE_CAP_PACKED_UNIFORMS:
+      return !!(LP_DEBUG & DEBUG_NIR);
    default:
       return u_pipe_screen_get_param_defaults(screen, param);
    }
@@ -407,10 +412,15 @@ llvmpipe_get_shader_param(struct pipe_screen *screen,
    case PIPE_SHADER_COMPUTE:
       switch (param) {
       default:
+         if ((LP_DEBUG & DEBUG_NIR) && param == PIPE_SHADER_CAP_PREFERRED_IR)
+            return PIPE_SHADER_IR_NIR;
          return gallivm_get_shader_param(param);
       }
    case PIPE_SHADER_VERTEX:
    case PIPE_SHADER_GEOMETRY:
+      if ((LP_DEBUG & DEBUG_NIR) && param == PIPE_SHADER_CAP_PREFERRED_IR)
+         return PIPE_SHADER_IR_NIR;
+
       switch (param) {
       case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
          /* At this time, the draw module and llvmpipe driver only
@@ -515,6 +525,51 @@ llvmpipe_get_compute_param(struct pipe_screen *_screen,
    return 0;
 }
 
+static const struct nir_shader_compiler_options gallivm_nir_options = {
+   .lower_scmp = true,
+   .lower_flrp32 = true,
+   .lower_flrp64 = true,
+   .lower_fsat = true,
+   .lower_bitfield_insert_to_bitfield_select = true,
+   .lower_bitfield_extract = true,
+   .lower_sub = true,
+   .lower_ffma = true,
+   .lower_fmod = true,
+   .lower_pack_snorm_2x16 = true,
+   .lower_pack_snorm_4x8 = true,
+   .lower_pack_unorm_2x16 = true,
+   .lower_pack_unorm_4x8 = true,
+   .lower_unpack_snorm_2x16 = true,
+   .lower_unpack_snorm_4x8 = true,
+   .lower_unpack_unorm_2x16 = true,
+   .lower_unpack_unorm_4x8 = true,
+   .lower_extract_byte = true,
+   .lower_extract_word = true,
+   .lower_rotate = true,
+   .optimize_sample_mask_in = true,
+   .max_unroll_iterations = 32,
+   .use_interpolated_input_intrinsics = true,
+   .lower_to_scalar = true,
+};
+
+static void
+llvmpipe_finalize_nir(struct pipe_screen *screen,
+                      void *nirptr,
+                      bool optimize)
+{
+   struct nir_shader *nir = (struct nir_shader *)nirptr;
+   lp_build_opt_nir(nir);
+}
+
+static inline const void *
+llvmpipe_get_compiler_options(struct pipe_screen *screen,
+                              enum pipe_shader_ir ir,
+                              enum pipe_shader_type shader)
+{
+   assert(ir == PIPE_SHADER_IR_NIR);
+   return &gallivm_nir_options;
+}
+
 /**
  * Query format support for creating a texture, drawing surface, etc.
  * \param format  the format to test
@@ -752,6 +807,7 @@ llvmpipe_create_screen(struct sw_winsys *winsys)
    screen->base.get_shader_param = llvmpipe_get_shader_param;
    screen->base.get_compute_param = llvmpipe_get_compute_param;
    screen->base.get_paramf = llvmpipe_get_paramf;
+   screen->base.get_compiler_options = llvmpipe_get_compiler_options;
    screen->base.is_format_supported = llvmpipe_is_format_supported;
 
    screen->base.context_create = llvmpipe_create_context;
@@ -761,6 +817,7 @@ llvmpipe_create_screen(struct sw_winsys *winsys)
 
    screen->base.get_timestamp = llvmpipe_get_timestamp;
 
+   screen->base.finalize_nir = llvmpipe_finalize_nir;
    llvmpipe_init_screen_resource_funcs(&screen->base);
 
    screen->num_threads = util_cpu_caps.nr_cpus > 1 ? util_cpu_caps.nr_cpus : 0;
index a26cbf4df227e759c5956a53979b5235e7538721..e98927acf7bf62801bdb8a436fcf952fc0245ebd 100644 (file)
@@ -35,6 +35,7 @@
 #include "gallivm/lp_bld_flow.h"
 #include "gallivm/lp_bld_gather.h"
 #include "gallivm/lp_bld_coro.h"
+#include "gallivm/lp_bld_nir.h"
 #include "lp_state_cs.h"
 #include "lp_context.h"
 #include "lp_debug.h"
@@ -44,6 +45,7 @@
 #include "lp_memory.h"
 #include "lp_cs_tpool.h"
 #include "state_tracker/sw_winsys.h"
+#include "nir/nir_to_tgsi_info.h"
 
 struct lp_cs_job_info {
    unsigned grid_size[3];
@@ -272,7 +274,6 @@ generate_compute(struct llvmpipe_context *lp,
    block = LLVMAppendBasicBlockInContext(gallivm->context, coro, "entry");
    LLVMPositionBuilderAtEnd(builder, block);
    {
-      const struct tgsi_token *tokens = shader->base.tokens;
       LLVMValueRef consts_ptr, num_consts_ptr;
       LLVMValueRef ssbo_ptr, num_ssbo_ptr;
       LLVMValueRef shared_ptr;
@@ -360,7 +361,11 @@ generate_compute(struct llvmpipe_context *lp,
       params.shared_ptr = shared_ptr;
       params.coro = &coro_info;
 
-      lp_build_tgsi_soa(gallivm, tokens, &params, NULL);
+      if (shader->base.type == PIPE_SHADER_IR_TGSI)
+         lp_build_tgsi_soa(gallivm, shader->base.tokens, &params, NULL);
+      else
+         lp_build_nir_soa(gallivm, shader->base.ir.nir, &params,
+                          NULL);
 
       mask_val = lp_build_mask_end(&mask);
 
@@ -393,11 +398,19 @@ llvmpipe_create_compute_state(struct pipe_context *pipe,
    if (!shader)
       return NULL;
 
-   assert(templ->ir_type == PIPE_SHADER_IR_TGSI);
-   shader->base.tokens = tgsi_dup_tokens(templ->prog);
+   shader->base.type = templ->ir_type;
+   if (templ->ir_type == PIPE_SHADER_IR_TGSI) {
+      /* get/save the summary info for this shader */
+      lp_build_tgsi_info(templ->prog, &shader->info);
+
+      /* we need to keep a local copy of the tokens */
+      shader->base.tokens = tgsi_dup_tokens(templ->prog);
+   } else {
+      shader->base.ir.nir = (struct nir_shader *)templ->prog;
+      nir_tgsi_scan_shader(templ->prog, &shader->info.base, false);
+   }
 
    shader->req_local_mem = templ->req_local_mem;
-   lp_build_tgsi_info(shader->base.tokens, &shader->info);
    make_empty_list(&shader->variants);
 
    nr_samplers = shader->info.base.file_max[TGSI_FILE_SAMPLER] + 1;
@@ -590,7 +603,10 @@ lp_debug_cs_variant(const struct lp_compute_shader_variant *variant)
 {
    debug_printf("llvmpipe: Compute shader #%u variant #%u:\n",
                 variant->shader->no, variant->no);
-   tgsi_dump(variant->shader->base.tokens, 0);
+   if (variant->shader->base.type == PIPE_SHADER_IR_TGSI)
+      tgsi_dump(variant->shader->base.tokens, 0);
+   else
+      nir_print_shader(variant->shader->base.ir.nir, stderr);
    dump_cs_variant_key(&variant->key);
    debug_printf("\n");
 }
index 5831d935bd44c60ae163c31b229e77de07187dbd..d72c1a7498ce36aca994c8b2be075089799062af 100644 (file)
@@ -80,6 +80,7 @@
 #include "gallivm/lp_bld_intr.h"
 #include "gallivm/lp_bld_logic.h"
 #include "gallivm/lp_bld_tgsi.h"
+#include "gallivm/lp_bld_nir.h"
 #include "gallivm/lp_bld_swizzle.h"
 #include "gallivm/lp_bld_flow.h"
 #include "gallivm/lp_bld_debug.h"
 #include "lp_flush.h"
 #include "lp_state_fs.h"
 #include "lp_rast.h"
-
+#include "nir/nir_to_tgsi_info.h"
 
 /** Fragment shader number (for debugging) */
 static unsigned fs_no = 0;
@@ -501,8 +502,12 @@ generate_fs_loop(struct gallivm_state *gallivm,
    params.image = image;
 
    /* Build the actual shader */
-   lp_build_tgsi_soa(gallivm, tokens, &params,
-                     outputs);
+   if (shader->base.type == PIPE_SHADER_IR_TGSI)
+      lp_build_tgsi_soa(gallivm, tokens, &params,
+                        outputs);
+   else
+      lp_build_nir_soa(gallivm, shader->base.ir.nir, &params,
+                       outputs);
 
    /* Alpha test */
    if (key->alpha.enabled) {
@@ -2839,9 +2844,12 @@ dump_fs_variant_key(struct lp_fragment_shader_variant_key *key)
 void
 lp_debug_fs_variant(struct lp_fragment_shader_variant *variant)
 {
-   debug_printf("llvmpipe: Fragment shader #%u variant #%u:\n", 
+   debug_printf("llvmpipe: Fragment shader #%u variant #%u:\n",
                 variant->shader->no, variant->no);
-   tgsi_dump(variant->shader->base.tokens, 0);
+   if (variant->shader->base.type == PIPE_SHADER_IR_TGSI)
+      tgsi_dump(variant->shader->base.tokens, 0);
+   else
+      nir_print_shader(variant->shader->base.ir.nir, stderr);
    dump_fs_variant_key(&variant->key);
    debug_printf("variant->opaque = %u\n", variant->opaque);
    debug_printf("\n");
@@ -2966,11 +2974,17 @@ llvmpipe_create_fs_state(struct pipe_context *pipe,
    shader->no = fs_no++;
    make_empty_list(&shader->variants);
 
-   /* get/save the summary info for this shader */
-   lp_build_tgsi_info(templ->tokens, &shader->info);
+   shader->base.type = templ->type;
+   if (templ->type == PIPE_SHADER_IR_TGSI) {
+      /* get/save the summary info for this shader */
+      lp_build_tgsi_info(templ->tokens, &shader->info);
 
-   /* we need to keep a local copy of the tokens */
-   shader->base.tokens = tgsi_dup_tokens(templ->tokens);
+      /* we need to keep a local copy of the tokens */
+      shader->base.tokens = tgsi_dup_tokens(templ->tokens);
+   } else {
+      shader->base.ir.nir = templ->ir.nir;
+      nir_tgsi_scan_shader(templ->ir.nir, &shader->info.base, false);
+   }
 
    shader->draw_data = draw_create_fragment_shader(llvmpipe->draw, templ);
    if (shader->draw_data == NULL) {
index 405a415624e2bd794f2b9058441bbed5e4cf54e5..b2a918ca957dd3e0f990078ab4145cf6f2d5eefe 100644 (file)
@@ -60,7 +60,7 @@ llvmpipe_create_gs_state(struct pipe_context *pipe,
    state->no_tokens = !templ->tokens;
    memcpy(&state->stream_output, &templ->stream_output, sizeof state->stream_output);
 
-   if (templ->tokens) {
+   if (templ->tokens || templ->type == PIPE_SHADER_IR_NIR) {
       state->dgs = draw_create_geometry_shader(llvmpipe->draw, templ);
       if (state->dgs == NULL) {
          goto no_dgs;
index 7882beb358d5042630d4fee5111fcad891adaf77..d3542fa156d7e0ea01cbb0f134d8e4e3437ff16a 100644 (file)
@@ -101,7 +101,7 @@ libllvmpipe = static_library(
   c_args : [c_vis_args, c_msvc_compat_args],
   cpp_args : [cpp_vis_args, cpp_msvc_compat_args],
   include_directories : [inc_gallium, inc_gallium_aux, inc_include, inc_src],
-  dependencies : dep_llvm,
+  dependencies : [ dep_llvm, idep_nir_headers, ],
 )
 
 # This overwrites the softpipe driver dependency, but itself depends on the