|
|
|
@@ -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; |