From 3f28b245b5d7f82546da7c889227f3b77a338786 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Sun, 16 Sep 2018 19:08:07 -0700 Subject: [PATCH] st/mesa: Add NIR versions of the drawpixels Z/stencil fragment shaders. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reviewed-by: Marek Olšák Tested-by: Rob Clark Tested-by: Eric Anholt --- src/mesa/state_tracker/st_cb_drawpixels.c | 140 ++++++++++++++++++---- 1 file changed, 119 insertions(+), 21 deletions(-) diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index e5d5035c63d..881655003c4 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -108,34 +108,97 @@ */ #define USE_DRAWPIXELS_CACHE 1 +static nir_ssa_def * +sample_via_nir(nir_builder *b, nir_variable *texcoord, + const char *name, int sampler) +{ + const struct glsl_type *sampler2D = + glsl_sampler_type(GLSL_SAMPLER_DIM_2D, false, false, GLSL_TYPE_FLOAT); + + nir_variable *var = + nir_variable_create(b->shader, nir_var_uniform, sampler2D, name); + var->data.binding = sampler; + + nir_tex_instr *tex = nir_tex_instr_create(b->shader, 1); + tex->op = nir_texop_tex; + tex->sampler_dim = GLSL_SAMPLER_DIM_2D; + tex->coord_components = 2; + tex->sampler_index = sampler; + tex->texture_index = sampler; + tex->dest_type = nir_type_float; + tex->src[0].src_type = nir_tex_src_coord; + tex->src[0].src = + nir_src_for_ssa(nir_channels(b, nir_load_var(b, texcoord), + (1 << tex->coord_components) - 1)); + + nir_ssa_dest_init(&tex->instr, &tex->dest, 4, 32, NULL); + nir_builder_instr_insert(b, &tex->instr); + return nir_channel(b, &tex->dest.ssa, 0); +} + +static void * +make_drawpix_z_stencil_program_nir(struct st_context *st, + bool write_depth, + bool write_stencil) +{ + struct nir_builder b; + const nir_shader_compiler_options *options = + st->ctx->Const.ShaderCompilerOptions[MESA_SHADER_FRAGMENT].NirOptions; + + nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, options); + + nir_variable *texcoord = + nir_variable_create(b.shader, nir_var_shader_in, glsl_vec_type(2), + "texcoord"); + texcoord->data.location = VARYING_SLOT_TEX0; + + if (write_depth) { + nir_variable *out = + nir_variable_create(b.shader, nir_var_shader_out, glsl_float_type(), + "gl_FragDepth"); + out->data.location = FRAG_RESULT_DEPTH; + nir_ssa_def *depth = sample_via_nir(&b, texcoord, "depth", 0); + nir_store_var(&b, out, depth, 0x1); + + /* Also copy color */ + nir_variable *color_in = + nir_variable_create(b.shader, nir_var_shader_in, glsl_vec_type(4), + "v_color"); + color_in->data.location = VARYING_SLOT_COL0; + + nir_variable *color_out = + nir_variable_create(b.shader, nir_var_shader_out, glsl_vec_type(4), + "gl_FragColor"); + color_out->data.location = FRAG_RESULT_COLOR; + nir_copy_var(&b, color_out, color_in); + } + + if (write_stencil) { + nir_variable *out = + nir_variable_create(b.shader, nir_var_shader_out, glsl_uint_type(), + "gl_FragStencilRefARB"); + out->data.location = FRAG_RESULT_STENCIL; + nir_ssa_def *stencil = sample_via_nir(&b, texcoord, "stencil", 1); + nir_store_var(&b, out, stencil, 0x1); + } + + char name[14]; + snprintf(name, 14, "drawpixels %s%s", + write_depth ? "Z" : "", write_stencil ? "S" : ""); + + return st_nir_finish_builtin_shader(st, b.shader, name); +} -/** - * Create fragment program that does a TEX() instruction to get a Z and/or - * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL. - * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX). - * Pass fragment color through as-is. - * - * \return CSO of the fragment shader. - */ static void * -get_drawpix_z_stencil_program(struct st_context *st, - GLboolean write_depth, - GLboolean write_stencil) +make_drawpix_z_stencil_program_tgsi(struct st_context *st, + bool write_depth, + bool write_stencil) { struct ureg_program *ureg; struct ureg_src depth_sampler, stencil_sampler; struct ureg_src texcoord, color; struct ureg_dst out_color, out_depth, out_stencil; - const GLuint shaderIndex = write_depth * 2 + write_stencil; - void *cso; - - assert(shaderIndex < ARRAY_SIZE(st->drawpix.zs_shaders)); - - if (st->drawpix.zs_shaders[shaderIndex]) { - /* already have the proper shader */ - return st->drawpix.zs_shaders[shaderIndex]; - } ureg = ureg_create(PIPE_SHADER_FRAGMENT); if (ureg == NULL) @@ -184,7 +247,42 @@ get_drawpix_z_stencil_program(struct st_context *st, TGSI_TEXTURE_2D, texcoord, stencil_sampler); ureg_END(ureg); - cso = ureg_create_shader_and_destroy(ureg, st->pipe); + return ureg_create_shader_and_destroy(ureg, st->pipe); +} + + +/** + * Create fragment program that does a TEX() instruction to get a Z and/or + * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL. + * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX). + * Pass fragment color through as-is. + * + * \return CSO of the fragment shader. + */ +static void * +get_drawpix_z_stencil_program(struct st_context *st, + bool write_depth, + bool write_stencil) +{ + struct pipe_screen *pscreen = st->pipe->screen; + const GLuint shaderIndex = write_depth * 2 + write_stencil; + void *cso; + + assert(shaderIndex < ARRAY_SIZE(st->drawpix.zs_shaders)); + + if (st->drawpix.zs_shaders[shaderIndex]) { + /* already have the proper shader */ + return st->drawpix.zs_shaders[shaderIndex]; + } + + enum pipe_shader_ir preferred_ir = + pscreen->get_shader_param(pscreen, PIPE_SHADER_FRAGMENT, + PIPE_SHADER_CAP_PREFERRED_IR); + + if (preferred_ir == PIPE_SHADER_IR_NIR) + cso = make_drawpix_z_stencil_program_nir(st, write_depth, write_stencil); + else + cso = make_drawpix_z_stencil_program_tgsi(st, write_depth, write_stencil); /* save the new shader */ st->drawpix.zs_shaders[shaderIndex] = cso; -- 2.30.2