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 <sroland@vmware.com>
This commit is contained in:
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -18,6 +18,9 @@ llvmpipe = env.ConvenienceLibrary(
|
||||
|
||||
env.Alias('llvmpipe', llvmpipe)
|
||||
|
||||
env.Append(CPPPATH = [
|
||||
'../../../compiler/nir',
|
||||
])
|
||||
|
||||
if not env['embedded']:
|
||||
env = env.Clone()
|
||||
|
@@ -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.
|
||||
*/
|
||||
|
@@ -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;
|
||||
|
@@ -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");
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user