From 18f896e55d96c63b11de7ed0cbe484988a1184c5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Sep 2019 15:49:25 +1000 Subject: llvmpipe: add initial nir support 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 --- src/gallium/auxiliary/gallivm/lp_bld_limits.h | 2 +- src/gallium/auxiliary/gallivm/lp_bld_nir.c | 12 ++++++ src/gallium/auxiliary/gallivm/lp_bld_nir.h | 2 + src/gallium/drivers/llvmpipe/SConscript | 3 ++ src/gallium/drivers/llvmpipe/lp_debug.h | 1 + src/gallium/drivers/llvmpipe/lp_screen.c | 61 ++++++++++++++++++++++++++- src/gallium/drivers/llvmpipe/lp_state_cs.c | 28 +++++++++--- src/gallium/drivers/llvmpipe/lp_state_fs.c | 32 ++++++++++---- src/gallium/drivers/llvmpipe/lp_state_gs.c | 2 +- src/gallium/drivers/llvmpipe/meson.build | 2 +- 10 files changed, 125 insertions(+), 20 deletions(-) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_limits.h b/src/gallium/auxiliary/gallivm/lp_bld_limits.h index 91fc95e5c11..014f5e84ca7 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_limits.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_limits.h @@ -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; diff --git a/src/gallium/auxiliary/gallivm/lp_bld_nir.c b/src/gallium/auxiliary/gallivm/lp_bld_nir.c index abaa82a0331..d69a5a4fb26 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_nir.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_nir.c @@ -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); +} diff --git a/src/gallium/auxiliary/gallivm/lp_bld_nir.h b/src/gallium/auxiliary/gallivm/lp_bld_nir.h index b0d16710122..194b109760c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_nir.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_nir.h @@ -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, diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript index 74d7a9e1673..1af6867715c 100644 --- a/src/gallium/drivers/llvmpipe/SConscript +++ b/src/gallium/drivers/llvmpipe/SConscript @@ -18,6 +18,9 @@ llvmpipe = env.ConvenienceLibrary( env.Alias('llvmpipe', llvmpipe) +env.Append(CPPPATH = [ + '../../../compiler/nir', +]) if not env['embedded']: env = env.Clone() diff --git a/src/gallium/drivers/llvmpipe/lp_debug.h b/src/gallium/drivers/llvmpipe/lp_debug.h index 1accf3b1d92..96af8936c5f 100644 --- a/src/gallium/drivers/llvmpipe/lp_debug.h +++ b/src/gallium/drivers/llvmpipe/lp_debug.h @@ -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. */ diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index d2364c183d7..c036108d318 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -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; diff --git a/src/gallium/drivers/llvmpipe/lp_state_cs.c b/src/gallium/drivers/llvmpipe/lp_state_cs.c index a26cbf4df22..e98927acf7b 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_cs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_cs.c @@ -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, ¶ms, NULL); + if (shader->base.type == PIPE_SHADER_IR_TGSI) + lp_build_tgsi_soa(gallivm, shader->base.tokens, ¶ms, NULL); + else + lp_build_nir_soa(gallivm, shader->base.ir.nir, ¶ms, + 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"); } diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 5831d935bd4..d72c1a7498c 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -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" @@ -102,7 +103,7 @@ #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, ¶ms, - outputs); + if (shader->base.type == PIPE_SHADER_IR_TGSI) + lp_build_tgsi_soa(gallivm, tokens, ¶ms, + outputs); + else + lp_build_nir_soa(gallivm, shader->base.ir.nir, ¶ms, + 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) { diff --git a/src/gallium/drivers/llvmpipe/lp_state_gs.c b/src/gallium/drivers/llvmpipe/lp_state_gs.c index 405a415624e..b2a918ca957 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_gs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_gs.c @@ -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; diff --git a/src/gallium/drivers/llvmpipe/meson.build b/src/gallium/drivers/llvmpipe/meson.build index 7882beb358d..d3542fa156d 100644 --- a/src/gallium/drivers/llvmpipe/meson.build +++ b/src/gallium/drivers/llvmpipe/meson.build @@ -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 -- cgit v1.2.3