From patchwork Mon Oct 19 19:47:57 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 7439481 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 31CD3BEEA4 for ; Mon, 19 Oct 2015 19:48:28 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E59B2207F8 for ; Mon, 19 Oct 2015 19:48:26 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id A2ACB207E6 for ; Mon, 19 Oct 2015 19:48:25 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id BA6E0720F2; Mon, 19 Oct 2015 12:48:24 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qg0-f44.google.com (mail-qg0-f44.google.com [209.85.192.44]) by gabe.freedesktop.org (Postfix) with ESMTPS id B84E36EABE for ; Mon, 19 Oct 2015 12:48:14 -0700 (PDT) Received: by qgad10 with SMTP id d10so74517092qga.3 for ; Mon, 19 Oct 2015 12:48:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=axwuivVSgqSCKXq/M0/UqCFNba5YuOdWs3I8lp/68O0=; b=uj+WAb5swNnB5AHKzFG8BrHgcRthSwz5zqL3XUGBH+M12YBCUW4rlYi4oL+gnDMnlo zTrAseYP7dgwDYxbGwRKC/gSsQseYNAht9By1EPOt8WgsOl3ltTjJppmIBllJFOSQpwG GucJ7m00DC1T78uq+cNYMviHOkTfRGO5/9BKDXYVSEcfuO4aKd2GZe031RQlhusWscvJ +4iqPqLgthzbNS+Sh8DAkrtXeWhoF8VU0Cx8Rn3cVsa3ZTHI+W5ClJLktgK79XxhtLS7 ear+8YrP1hV8OfCCW8YJ9iXOg1DnqJftlcBo3A4eW+ps0QwHaCFNHY8hWtm1gRM1MYbv TLSw== X-Received: by 10.140.98.183 with SMTP id o52mr37936343qge.70.1445284094032; Mon, 19 Oct 2015 12:48:14 -0700 (PDT) Received: from localhost ([2601:184:4000:26d7:6af7:28ff:fe77:e429]) by smtp.gmail.com with ESMTPSA id k4sm15019310qkl.26.2015.10.19.12.48.13 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 19 Oct 2015 12:48:13 -0700 (PDT) From: Rob Clark To: dri-devel@lists.freedesktop.org Subject: [RFCv0 4/8] mesa/st: add support for NIR as possible driver IR Date: Mon, 19 Oct 2015 15:47:57 -0400 Message-Id: <1445284081-29532-5-git-send-email-robdclark@gmail.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1445284081-29532-1-git-send-email-robdclark@gmail.com> References: <1445284081-29532-1-git-send-email-robdclark@gmail.com> Cc: Jason Ekstrand X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP --- src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 223 ++++++++++++++++++++++++++++- src/mesa/state_tracker/st_program.c | 43 +++++- 2 files changed, 260 insertions(+), 6 deletions(-) diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 06f510d..49f496f 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -35,6 +35,9 @@ #include "glsl_parser_extras.h" #include "ir_optimization.h" +#include "nir.h" +#include "glsl_to_nir.h" + #include "main/errors.h" #include "main/shaderobj.h" #include "main/uniforms.h" @@ -5486,9 +5489,9 @@ out: * generating Mesa IR. */ static struct gl_program * -get_mesa_program(struct gl_context *ctx, - struct gl_shader_program *shader_program, - struct gl_shader *shader) +get_mesa_program_tgsi(struct gl_context *ctx, + struct gl_shader_program *shader_program, + struct gl_shader *shader) { glsl_to_tgsi_visitor* v; struct gl_program *prog; @@ -5680,6 +5683,220 @@ get_mesa_program(struct gl_context *ctx, return prog; } +/* TODO dup'd from brw_vec4_vistor.cpp.. what should we do? */ +static int +type_size_vec4(const struct glsl_type *type) +{ + unsigned int i; + int size; + + switch (type->base_type) { + case GLSL_TYPE_UINT: + case GLSL_TYPE_INT: + case GLSL_TYPE_FLOAT: + case GLSL_TYPE_BOOL: + if (type->is_matrix()) { + return type->matrix_columns; + } else { + /* Regardless of size of vector, it gets a vec4. This is bad + * packing for things like floats, but otherwise arrays become a + * mess. Hopefully a later pass over the code can pack scalars + * down if appropriate. + */ + return 1; + } + case GLSL_TYPE_ARRAY: + assert(type->length > 0); + return type_size_vec4(type->fields.array) * type->length; + case GLSL_TYPE_STRUCT: + size = 0; + for (i = 0; i < type->length; i++) { + size += type_size_vec4(type->fields.structure[i].type); + } + return size; + case GLSL_TYPE_SUBROUTINE: + return 1; + + case GLSL_TYPE_SAMPLER: + /* Samplers take up no register space, since they're baked in at + * link time. + */ + return 0; + case GLSL_TYPE_ATOMIC_UINT: + return 0; + case GLSL_TYPE_IMAGE: +// return DIV_ROUND_UP(BRW_IMAGE_PARAM_SIZE, 4); + case GLSL_TYPE_VOID: + case GLSL_TYPE_DOUBLE: + case GLSL_TYPE_ERROR: + case GLSL_TYPE_INTERFACE: + unreachable("not reached"); + } + + return 0; +} + +static struct gl_program * +get_mesa_program_nir(struct gl_context *ctx, + struct gl_shader_program *shader_program, + struct gl_shader *shader) +{ + struct gl_program *prog; + GLenum target = _mesa_shader_stage_to_program(shader->Stage); + struct gl_shader_compiler_options *options = + &ctx->Const.ShaderCompilerOptions[_mesa_shader_enum_to_shader_stage(shader->Type)]; + struct pipe_screen *pscreen = ctx->st->pipe->screen; + unsigned ptarget = st_shader_stage_to_ptarget(shader->Stage); + nir_shader_compiler_options nir_options = {0}; + nir_shader *nir; + + /* TODO maybe options marked with 'XXX' should be PIPE_SHADER_CAP_x's */ + nir_options.lower_ffma = + !pscreen->get_shader_param(pscreen, ptarget, PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED); + nir_options.lower_flrp = true; // XXX + nir_options.lower_fpow = options->EmitNoPow; + nir_options.lower_fsat = options->EmitNoSat; + nir_options.lower_fsqrt = + !pscreen->get_shader_param(pscreen, ptarget, PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED); + nir_options.lower_negate = false; // XXX + nir_options.lower_sub = false; // XXX + nir_options.lower_scmp = true; // XXX + nir_options.fdot_replicates = false;// XXX + nir_options.lower_ffract = true; // XXX + nir_options.native_integers = ctx->Const.NativeIntegers; + + validate_ir_tree(shader->ir); + + prog = ctx->Driver.NewProgram(ctx, target, shader_program->Name); + if (!prog) + return NULL; + prog->Parameters = _mesa_new_parameter_list(); + + _mesa_copy_linked_program_data(shader->Stage, shader_program, prog); + _mesa_generate_parameters_list_for_uniforms(shader_program, shader, + prog->Parameters); + +// /* Remove reads from output registers. */ +// lower_output_reads(shader->Stage, shader->ir); + + /* Make a pass over the IR to add state references for any built-in + * uniforms that are used. This has to be done now (during linking). + * Code generation doesn't happen until the first time this shader is + * used for rendering. Waiting until then to generate the parameters is + * too late. At that point, the values for the built-in uniforms won't + * get sent to the shader. + */ + foreach_in_list(ir_instruction, node, shader->ir) { + ir_variable *var = node->as_variable(); + + if ((var == NULL) || (var->data.mode != ir_var_uniform) || + (strncmp(var->name, "gl_", 3) != 0)) + continue; + + const ir_state_slot *const slots = var->get_state_slots(); + assert(slots != NULL); + + for (unsigned int i = 0; i < var->get_num_state_slots(); i++) { + _mesa_add_state_reference(prog->Parameters, + (gl_state_index *) slots[i].tokens); + } + } + + if (ctx->_Shader->Flags & GLSL_DUMP) { + _mesa_log("\n"); + _mesa_log("GLSL IR for linked %s program %d:\n", + _mesa_shader_stage_to_string(shader->Stage), + shader_program->Name); + _mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL); + _mesa_log("\n\n"); + } + + prog->Instructions = NULL; + prog->NumInstructions = 0; + + do_set_program_inouts(shader->ir, prog, shader->Stage); + + prog->SamplersUsed = shader->active_samplers; + prog->ShadowSamplers = shader->shadow_samplers; + _mesa_update_shader_textures_used(shader_program, prog); + + _mesa_reference_program(ctx, &shader->Program, prog); + + nir = glsl_to_nir(shader_program, shader->Stage, &nir_options); + prog->nir = nir; + + nir_validate_shader(nir); + + if (shader->Stage == MESA_SHADER_GEOMETRY) { + nir_lower_gs_intrinsics(nir); + nir_validate_shader(nir); + } + + nir_print_shader(nir, _mesa_get_log_file()); + + nir_lower_global_vars_to_local(nir); + nir_validate_shader(nir); + + nir_lower_var_copies(nir); + nir_validate_shader(nir); + + nir_assign_var_locations(&nir->inputs, + &nir->num_inputs, + type_size_vec4); + nir_assign_var_locations(&nir->outputs, + &nir->num_outputs, + type_size_vec4); + nir_assign_var_locations(&nir->uniforms, + &nir->num_uniforms, + type_size_vec4); + + nir_lower_io(nir, nir_var_all, type_size_vec4); + nir_validate_shader(nir); + + + // XXX do we need anything else from brw_create_nir().. and what + // is best way to split up which things should be here vs driver? + // currently just trying to make the result here similar to what + // we get from tgsi_to_nir().. so lower_io, etc.. + + // XXX new flag, probably? + if (ctx->_Shader->Flags & GLSL_DUMP) { + _mesa_log("\n"); + _mesa_log("NIR IR for linked %s program %d:\n", + _mesa_shader_stage_to_string(shader->Stage), + shader_program->Name); + nir_print_shader(nir, _mesa_get_log_file()); + _mesa_log("\n\n"); + } + + /* This has to be done last. Any operation the can cause + * prog->ParameterValues to get reallocated (e.g., anything that adds a + * program constant) has to happen before creating this linkage. + */ + _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters); + + return prog; +} + +static struct gl_program * +get_mesa_program(struct gl_context *ctx, + struct gl_shader_program *shader_program, + struct gl_shader *shader) +{ + struct pipe_screen *pscreen = ctx->st->pipe->screen; + unsigned ptarget = st_shader_stage_to_ptarget(shader->Stage); + enum pipe_shader_ir preferred_ir = (enum pipe_shader_ir) + pscreen->get_shader_param(pscreen, ptarget, PIPE_SHADER_CAP_PREFERRED_IR); + /* TODO: only do this for VERTEX stage for now: */ + if ((preferred_ir == PIPE_SHADER_IR_NIR) && + (shader->Type == GL_VERTEX_SHADER)) { + return get_mesa_program_nir(ctx, shader_program, shader); + } else { + return get_mesa_program_tgsi(ctx, shader_program, shader); + } +} + + extern "C" { static void diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 6a69ba7..3617160 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -38,6 +38,8 @@ #include "program/prog_print.h" #include "program/programopt.h" +#include "nir.h" + #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_shader_tokens.h" @@ -70,8 +72,13 @@ delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv) if (vpv->draw_shader) draw_delete_vertex_shader( st->draw, vpv->draw_shader ); - if (vpv->tgsi.tokens) - ureg_free_tokens(vpv->tgsi.tokens); + if (vpv->tgsi.ir == PIPE_SHADER_IR_NIR) { + if (vpv->tgsi.nir) + ralloc_free(vpv->tgsi.nir); + } else { + if (vpv->tgsi.tokens) + ureg_free_tokens(vpv->tgsi.tokens); + } free( vpv ); } @@ -270,6 +277,20 @@ st_translate_vertex_program(struct st_context *st, stvp->num_inputs = 0; + if (stvp->Base.Base.nir) { + /* TODO should we be doing glsl_to_nir() here instead of in + * get_mesa_program_nir()? + * + * NOTE glsl_to_nir() path doesn't apply for GL_*_PROGRAM_ARB + * so I *think* that simplifies some things.. + */ + nir_shader *nir = stvp->Base.Base.nir; + stvp->tgsi.ir = PIPE_SHADER_IR_NIR; + stvp->tgsi.nir = nir; + stvp->num_inputs = nir->num_inputs; + return true; + } + if (stvp->Base.IsPositionInvariant) _mesa_insert_mvp_code(st->ctx, &stvp->Base); @@ -466,10 +487,26 @@ st_create_vp_variant(struct st_context *st, struct pipe_context *pipe = st->pipe; vpv->key = *key; - vpv->tgsi.tokens = tgsi_dup_tokens(stvp->tgsi.tokens); vpv->tgsi.stream_output = stvp->tgsi.stream_output; vpv->num_inputs = stvp->num_inputs; + if (stvp->tgsi.ir == PIPE_SHADER_IR_NIR) { + vpv->tgsi.ir = PIPE_SHADER_IR_NIR; + /* TODO, we need nir_clone() here for dealing w/ variants + * that are maintained at the mesa-st layer. (Otoh, the + * pipe-drivers already maintain their own variants, it + * might be nicer to just expose the variant-key to the + * driver and let it decide what to lower, since it is + * doing that already for other things..) + */ + vpv->tgsi.nir = stvp->tgsi.nir; + + vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi); + return vpv; + } + + vpv->tgsi.tokens = tgsi_dup_tokens(stvp->tgsi.tokens); + /* Emulate features. */ if (key->clamp_color || key->passthrough_edgeflags) { const struct tgsi_token *tokens;