X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_atom_shader.c;h=c784ea8c59debdff3a81666edb865b2742b32519;hb=28543f1640d459404413c244740291fe68a75a5c;hp=c8650a5899ad8227d0790e285144045bbb7e9d9a;hpb=ff8895ba5606372f368917b97b8c4380bb822234;p=mesa.git diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index c8650a5899a..c784ea8c59d 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -37,221 +37,290 @@ #include "main/imports.h" #include "main/mtypes.h" +#include "main/framebuffer.h" +#include "main/state.h" +#include "main/texobj.h" +#include "main/texstate.h" #include "program/program.h" #include "pipe/p_context.h" #include "pipe/p_shader_tokens.h" #include "util/u_simple_shaders.h" #include "cso_cache/cso_context.h" +#include "util/u_debug.h" #include "st_context.h" #include "st_atom.h" #include "st_program.h" +#include "st_texture.h" +#include "st_util.h" + + +static unsigned +get_texture_target(struct gl_context *ctx, const unsigned unit) +{ + struct gl_texture_object *texObj = _mesa_get_tex_unit(ctx, unit)->_Current; + gl_texture_index index; + + if (texObj) { + index = _mesa_tex_target_to_index(ctx, texObj->Target); + } else { + /* fallback for missing texture */ + index = TEXTURE_2D_INDEX; + } + + /* Map mesa texture target to TGSI texture target. + * Copied from st_mesa_to_tgsi.c, the shadow part is omitted */ + switch(index) { + case TEXTURE_2D_MULTISAMPLE_INDEX: return TGSI_TEXTURE_2D_MSAA; + case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY_MSAA; + case TEXTURE_BUFFER_INDEX: return TGSI_TEXTURE_BUFFER; + case TEXTURE_1D_INDEX: return TGSI_TEXTURE_1D; + case TEXTURE_2D_INDEX: return TGSI_TEXTURE_2D; + case TEXTURE_3D_INDEX: return TGSI_TEXTURE_3D; + case TEXTURE_CUBE_INDEX: return TGSI_TEXTURE_CUBE; + case TEXTURE_CUBE_ARRAY_INDEX: return TGSI_TEXTURE_CUBE_ARRAY; + case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_RECT; + case TEXTURE_1D_ARRAY_INDEX: return TGSI_TEXTURE_1D_ARRAY; + case TEXTURE_2D_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY; + case TEXTURE_EXTERNAL_INDEX: return TGSI_TEXTURE_2D; + default: + debug_assert(0); + return TGSI_TEXTURE_1D; + } +} /** * Update fragment program state/atom. This involves translating the * Mesa fragment program into a gallium fragment program and binding it. */ -static void -update_fp( struct st_context *st ) +void +st_update_fp( struct st_context *st ) { struct st_fragment_program *stfp; - struct st_fp_variant_key key; assert(st->ctx->FragmentProgram._Current); stfp = st_fragment_program(st->ctx->FragmentProgram._Current); - assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); + assert(stfp->Base.Target == GL_FRAGMENT_PROGRAM_ARB); - memset(&key, 0, sizeof(key)); - key.st = st->has_shareable_shaders ? NULL : st; + void *shader; - /* _NEW_FRAG_CLAMP */ - key.clamp_color = st->clamp_frag_color_in_shader && - st->ctx->Color._ClampFragmentColor; + if (st->shader_has_one_variant[MESA_SHADER_FRAGMENT] && + !stfp->ati_fs && /* ATI_fragment_shader always has multiple variants */ + !stfp->Base.ExternalSamplersUsed && /* external samplers need variants */ + stfp->variants && + !stfp->variants->key.drawpixels && + !stfp->variants->key.bitmap) { + shader = stfp->variants->driver_shader; + } else { + struct st_fp_variant_key key; - /* Don't set it if the driver can force the interpolation by itself. - * If SAMPLE_ID or SAMPLE_POS are used, the interpolation is set - * automatically. - * Ignore sample qualifier while computing this flag. - */ - key.persample_shading = - st->force_persample_in_shader && - !(stfp->Base.Base.SystemValuesRead & (SYSTEM_BIT_SAMPLE_ID | - SYSTEM_BIT_SAMPLE_POS)) && - _mesa_get_min_invocations_per_fragment(st->ctx, &stfp->Base, true) > 1; + /* use memset, not an initializer to be sure all memory is zeroed */ + memset(&key, 0, sizeof(key)); - st->fp_variant = st_get_fp_variant(st, stfp, &key); + key.st = st->has_shareable_shaders ? NULL : st; - st_reference_fragprog(st, &st->fp, stfp); + key.lower_flatshade = st->lower_flatshade && + st->ctx->Light.ShadeModel == GL_FLAT; - cso_set_fragment_shader_handle(st->cso_context, - st->fp_variant->driver_shader); -} + /* _NEW_COLOR */ + key.lower_alpha_func = COMPARE_FUNC_NEVER; + if (st->lower_alpha_test && _mesa_is_alpha_test_enabled(st->ctx)) + key.lower_alpha_func = st->ctx->Color.AlphaFunc; + + /* _NEW_LIGHT | _NEW_PROGRAM */ + key.lower_two_sided_color = st->lower_two_sided_color && + _mesa_vertex_program_two_side_enabled(st->ctx); + /* _NEW_FRAG_CLAMP */ + key.clamp_color = st->clamp_frag_color_in_shader && + st->ctx->Color._ClampFragmentColor; -const struct st_tracked_state st_update_fp = { - "st_update_fp", /* name */ - { /* dirty */ - _NEW_BUFFERS | _NEW_MULTISAMPLE, /* mesa */ - ST_NEW_FRAGMENT_PROGRAM /* st */ - }, - update_fp /* update */ -}; + /* _NEW_MULTISAMPLE | _NEW_BUFFERS */ + key.persample_shading = + st->force_persample_in_shader && + _mesa_is_multisample_enabled(st->ctx) && + st->ctx->Multisample.SampleShading && + st->ctx->Multisample.MinSampleShadingValue * + _mesa_geometric_samples(st->ctx->DrawBuffer) > 1; + key.lower_depth_clamp = + st->clamp_frag_depth_in_shader && + (st->ctx->Transform.DepthClampNear || + st->ctx->Transform.DepthClampFar); + + if (stfp->ati_fs) { + key.fog = st->ctx->Fog._PackedEnabledMode; + + for (unsigned u = 0; u < MAX_NUM_FRAGMENT_REGISTERS_ATI; u++) { + key.texture_targets[u] = get_texture_target(st->ctx, u); + } + } + + key.external = st_get_external_sampler_key(st, &stfp->Base); + + shader = st_get_fp_variant(st, stfp, &key)->driver_shader; + } + + st_reference_fragprog(st, &st->fp, stfp); + + cso_set_fragment_shader_handle(st->cso_context, shader); +} /** * Update vertex program state/atom. This involves translating the * Mesa vertex program into a gallium fragment program and binding it. */ -static void -update_vp( struct st_context *st ) +void +st_update_vp( struct st_context *st ) { struct st_vertex_program *stvp; - struct st_vp_variant_key key; /* find active shader and params -- Should be covered by * ST_NEW_VERTEX_PROGRAM */ assert(st->ctx->VertexProgram._Current); stvp = st_vertex_program(st->ctx->VertexProgram._Current); - assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); - - memset(&key, 0, sizeof key); - key.st = st->has_shareable_shaders ? NULL : st; - - /* When this is true, we will add an extra input to the vertex - * shader translation (for edgeflags), an extra output with - * edgeflag semantics, and extend the vertex shader to pass through - * the input to the output. We'll need to use similar logic to set - * up the extra vertex_element input for edgeflags. - */ - key.passthrough_edgeflags = st->vertdata_edgeflags; - - key.clamp_color = st->clamp_vert_color_in_shader && - st->ctx->Light._ClampVertexColor && - (stvp->Base.Base.OutputsWritten & - (VARYING_SLOT_COL0 | - VARYING_SLOT_COL1 | - VARYING_SLOT_BFC0 | - VARYING_SLOT_BFC1)); - - st->vp_variant = st_get_vp_variant(st, stvp, &key); + assert(stvp->Base.Target == GL_VERTEX_PROGRAM_ARB); + + if (st->shader_has_one_variant[MESA_SHADER_VERTEX] && + stvp->variants && + stvp->variants->key.passthrough_edgeflags == st->vertdata_edgeflags) { + st->vp_variant = stvp->variants; + } else { + struct st_vp_variant_key key; + + memset(&key, 0, sizeof(key)); + + key.st = st->has_shareable_shaders ? NULL : st; + + /* When this is true, we will add an extra input to the vertex + * shader translation (for edgeflags), an extra output with + * edgeflag semantics, and extend the vertex shader to pass through + * the input to the output. We'll need to use similar logic to set + * up the extra vertex_element input for edgeflags. + */ + key.passthrough_edgeflags = st->vertdata_edgeflags; + + key.clamp_color = st->clamp_vert_color_in_shader && + st->ctx->Light._ClampVertexColor && + (stvp->Base.info.outputs_written & + (VARYING_SLOT_COL0 | + VARYING_SLOT_COL1 | + VARYING_SLOT_BFC0 | + VARYING_SLOT_BFC1)); + + key.lower_depth_clamp = + !st->gp && !st->tep && + st->clamp_frag_depth_in_shader && + (st->ctx->Transform.DepthClampNear || + st->ctx->Transform.DepthClampFar); + + if (key.lower_depth_clamp) + key.clip_negative_one_to_one = + st->ctx->Transform.ClipDepthMode == GL_NEGATIVE_ONE_TO_ONE; + + /* _NEW_POINT */ + key.lower_point_size = st->lower_point_size && + !st_point_size_per_vertex(st->ctx); + + st->vp_variant = st_get_vp_variant(st, stvp, &key); + } st_reference_vertprog(st, &st->vp, stvp); cso_set_vertex_shader_handle(st->cso_context, st->vp_variant->driver_shader); - - st->vertex_result_to_slot = stvp->result_to_output; } -const struct st_tracked_state st_update_vp = { - "st_update_vp", /* name */ - { /* dirty */ - 0, /* mesa */ - ST_NEW_VERTEX_PROGRAM /* st */ - }, - update_vp /* update */ -}; - - - -static void -update_gp( struct st_context *st ) +static void * +st_update_common_program(struct st_context *st, struct gl_program *prog, + unsigned pipe_shader, struct st_common_program **dst) { - struct st_geometry_program *stgp; + struct st_common_program *stp; - if (!st->ctx->GeometryProgram._Current) { - cso_set_geometry_shader_handle(st->cso_context, NULL); - return; + if (!prog) { + st_reference_prog(st, dst, NULL); + return NULL; } - stgp = st_geometry_program(st->ctx->GeometryProgram._Current); - assert(stgp->Base.Base.Target == GL_GEOMETRY_PROGRAM_NV); + stp = st_common_program(prog); + st_reference_prog(st, dst, stp); - st->gp_variant = st_get_basic_variant(st, PIPE_SHADER_GEOMETRY, - &stgp->tgsi, &stgp->variants); + if (st->shader_has_one_variant[prog->info.stage] && stp->variants) + return stp->variants->driver_shader; - st_reference_geomprog(st, &st->gp, stgp); - - cso_set_geometry_shader_handle(st->cso_context, - st->gp_variant->driver_shader); -} - -const struct st_tracked_state st_update_gp = { - "st_update_gp", /* name */ - { /* dirty */ - 0, /* mesa */ - ST_NEW_GEOMETRY_PROGRAM /* st */ - }, - update_gp /* update */ -}; + struct st_basic_variant_key key; + /* use memset, not an initializer to be sure all memory is zeroed */ + memset(&key, 0, sizeof(key)); + key.st = st->has_shareable_shaders ? NULL : st; -static void -update_tcp( struct st_context *st ) -{ - struct st_tessctrl_program *sttcp; + if (pipe_shader == PIPE_SHADER_GEOMETRY || + pipe_shader == PIPE_SHADER_TESS_EVAL) { + key.clamp_color = st->clamp_vert_color_in_shader && + st->ctx->Light._ClampVertexColor && + (stp->Base.info.outputs_written & + (VARYING_SLOT_COL0 | + VARYING_SLOT_COL1 | + VARYING_SLOT_BFC0 | + VARYING_SLOT_BFC1)); + + key.lower_depth_clamp = + (pipe_shader == PIPE_SHADER_GEOMETRY || !st->gp) && + st->clamp_frag_depth_in_shader && + (st->ctx->Transform.DepthClampNear || + st->ctx->Transform.DepthClampFar); + + if (key.lower_depth_clamp) + key.clip_negative_one_to_one = + st->ctx->Transform.ClipDepthMode == GL_NEGATIVE_ONE_TO_ONE; - if (!st->ctx->TessCtrlProgram._Current) { - cso_set_tessctrl_shader_handle(st->cso_context, NULL); - return; } - sttcp = st_tessctrl_program(st->ctx->TessCtrlProgram._Current); - assert(sttcp->Base.Base.Target == GL_TESS_CONTROL_PROGRAM_NV); - - st->tcp_variant = st_get_basic_variant(st, PIPE_SHADER_TESS_CTRL, - &sttcp->tgsi, &sttcp->variants); - - st_reference_tesscprog(st, &st->tcp, sttcp); - - cso_set_tessctrl_shader_handle(st->cso_context, - st->tcp_variant->driver_shader); + return st_get_basic_variant(st, stp, &key)->driver_shader; } -const struct st_tracked_state st_update_tcp = { - "st_update_tcp", /* name */ - { /* dirty */ - 0, /* mesa */ - ST_NEW_TESSCTRL_PROGRAM /* st */ - }, - update_tcp /* update */ -}; +void +st_update_gp(struct st_context *st) +{ + void *shader = st_update_common_program(st, + st->ctx->GeometryProgram._Current, + PIPE_SHADER_GEOMETRY, &st->gp); + cso_set_geometry_shader_handle(st->cso_context, shader); +} -static void -update_tep( struct st_context *st ) +void +st_update_tcp(struct st_context *st) { - struct st_tesseval_program *sttep; - - if (!st->ctx->TessEvalProgram._Current) { - cso_set_tesseval_shader_handle(st->cso_context, NULL); - return; - } + void *shader = st_update_common_program(st, + st->ctx->TessCtrlProgram._Current, + PIPE_SHADER_TESS_CTRL, &st->tcp); + cso_set_tessctrl_shader_handle(st->cso_context, shader); +} - sttep = st_tesseval_program(st->ctx->TessEvalProgram._Current); - assert(sttep->Base.Base.Target == GL_TESS_EVALUATION_PROGRAM_NV); - st->tep_variant = st_get_basic_variant(st, PIPE_SHADER_TESS_EVAL, - &sttep->tgsi, &sttep->variants); +void +st_update_tep(struct st_context *st) +{ + void *shader = st_update_common_program(st, + st->ctx->TessEvalProgram._Current, + PIPE_SHADER_TESS_EVAL, &st->tep); + cso_set_tesseval_shader_handle(st->cso_context, shader); +} - st_reference_tesseprog(st, &st->tep, sttep); - cso_set_tesseval_shader_handle(st->cso_context, - st->tep_variant->driver_shader); +void +st_update_cp(struct st_context *st) +{ + void *shader = st_update_common_program(st, + st->ctx->ComputeProgram._Current, + PIPE_SHADER_COMPUTE, &st->cp); + cso_set_compute_shader_handle(st->cso_context, shader); } - -const struct st_tracked_state st_update_tep = { - "st_update_tep", /* name */ - { /* dirty */ - 0, /* mesa */ - ST_NEW_TESSEVAL_PROGRAM /* st */ - }, - update_tep /* update */ -};