*/
#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)
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;