st/mesa: Add NIR versions of the drawpixels Z/stencil fragment shaders.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Tested-by: Rob Clark <robdclark@gmail.com>
Tested-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
Kenneth Graunke
2018-09-16 19:08:07 -07:00
parent 2d45f9fa25
commit 3f28b245b5

View File

@@ -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);
}
/**
* 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_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);
}
static void *
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;