X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_atom_shader.c;h=d0c2429dcefe16bffed72c585accab99158a1795;hb=b5dd8e0cf877db2adc249db8e132beeea79ba1cf;hp=09baff875bc1e7f9d58877935a89a52091be18ce;hpb=a3eb0f718e19653a2ad8e49396c904183be456f3;p=mesa.git diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 09baff875bc..d0c2429dcef 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2003 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -35,155 +35,126 @@ * Brian Paul */ - - #include "main/imports.h" #include "main/mtypes.h" -#include "main/macros.h" -#include "shader/program.h" +#include "main/framebuffer.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_atom_shader.h" -#include "st_mesa_to_tgsi.h" - - - -/* - * Translate fragment program if needed. - */ -static void -translate_fp(struct st_context *st, - struct st_fragment_program *stfp) +/** Compress the fog function enums into a 2-bit value */ +static GLuint +translate_fog_mode(GLenum mode) { - const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead; - - if (!stfp->state.tokens) { - GLuint inAttr, numIn = 0; - - for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) { - if (fragInputsRead & (1 << inAttr)) { - stfp->input_to_slot[inAttr] = numIn; - numIn++; - } - else { - stfp->input_to_slot[inAttr] = -1; - } - } - - stfp->num_input_slots = numIn; - - assert(stfp->Base.Base.NumInstructions > 1); - - st_translate_fragment_program(st, stfp, stfp->input_to_slot); + switch (mode) { + case GL_LINEAR: return 1; + case GL_EXP: return 2; + case GL_EXP2: return 3; + default: + return 0; } } - - -/** - * Find a translated vertex program that corresponds to stvp and - * has outputs matched to stfp's inputs. - * This performs vertex and fragment translation (to TGSI) when needed. - */ -static struct st_vp_varient * -find_translated_vp(struct st_context *st, - struct st_vertex_program *stvp ) +static unsigned +get_texture_target(struct gl_context *ctx, const unsigned unit) { - struct st_vp_varient *vpv; - struct st_vp_varient_key key; - - /* Nothing in our key yet. This will change: - */ - memset(&key, 0, sizeof key); - key.dummy = 0; - - /* Do we need to throw away old translations after a change in the - * GL program string? - */ - if (stvp->serialNo != stvp->lastSerialNo) { - /* These may have changed if the program string changed. - */ - st_prepare_vertex_program( st, stvp ); - - /* We are now up-to-date: - */ - stvp->lastSerialNo = stvp->serialNo; - } - - /* See if we've got a translated vertex program whose outputs match - * the fragment program's inputs. - */ - for (vpv = stvp->varients; vpv; vpv = vpv->next) { - if (memcmp(&vpv->key, &key, sizeof key) == 0) { - break; - } + 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; } - /* No? Perform new translation here. */ - if (!vpv) { - vpv = st_translate_vertex_program(st, stvp, &key); - if (!vpv) - return NULL; - - vpv->next = stvp->varients; - stvp->varients = vpv; + /* 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; } - - return vpv; } - - -static void * -get_passthrough_fs(struct st_context *st) -{ - if (!st->passthrough_fs) { - st->passthrough_fs = - util_make_fragment_passthrough_shader(st->pipe); - } - - return st->passthrough_fs; -} - +/** + * 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 ) { 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); - translate_fp(st, stfp); + memset(&key, 0, sizeof(key)); + key.st = st->has_shareable_shaders ? NULL : st; - st_reference_fragprog(st, &st->fp, stfp); + /* _NEW_FRAG_CLAMP */ + key.clamp_color = st->clamp_frag_color_in_shader && + st->ctx->Color._ClampFragmentColor; - if (st->missing_textures) { - /* use a pass-through frag shader that uses no textures */ - void *fs = get_passthrough_fs(st); - cso_set_fragment_shader_handle(st->cso_context, fs); - } - else { - cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); + /* _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; + + if (stfp->ati_fs) { + unsigned u; + + if (st->ctx->Fog.Enabled) { + key.fog = translate_fog_mode(st->ctx->Fog.Mode); + } + + for (u = 0; u < MAX_NUM_FRAGMENT_REGISTERS_ATI; u++) { + key.texture_targets[u] = get_texture_target(st->ctx, u); + } } + + st->fp_variant = st_get_fp_variant(st, stfp, &key); + + st_reference_fragprog(st, &st->fp, stfp); + + cso_set_fragment_shader_handle(st->cso_context, + st->fp_variant->driver_shader); } + const struct st_tracked_state st_update_fp = { "st_update_fp", /* name */ { /* dirty */ - 0, /* mesa */ + _NEW_BUFFERS | _NEW_MULTISAMPLE | _NEW_FOG, /* mesa */ ST_NEW_FRAGMENT_PROGRAM /* st */ }, update_fp /* update */ @@ -191,11 +162,15 @@ const struct st_tracked_state st_update_fp = { - +/** + * 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 ) { struct st_vertex_program *stvp; + struct st_vp_variant_key key; /* find active shader and params -- Should be covered by * ST_NEW_VERTEX_PROGRAM @@ -204,12 +179,31 @@ update_vp( struct st_context *st ) stvp = st_vertex_program(st->ctx->VertexProgram._Current); assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); - st->vp_varient = find_translated_vp(st, stvp); + 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); st_reference_vertprog(st, &st->vp, stvp); cso_set_vertex_shader_handle(st->cso_context, - st->vp_varient->driver_shader); + st->vp_variant->driver_shader); st->vertex_result_to_slot = stvp->result_to_output; } @@ -218,8 +212,139 @@ update_vp( struct st_context *st ) const struct st_tracked_state st_update_vp = { "st_update_vp", /* name */ { /* dirty */ - 0, /* mesa */ + 0, /* mesa */ ST_NEW_VERTEX_PROGRAM /* st */ }, - update_vp /* update */ + update_vp /* update */ +}; + + + +static void +update_gp( struct st_context *st ) +{ + struct st_geometry_program *stgp; + + if (!st->ctx->GeometryProgram._Current) { + cso_set_geometry_shader_handle(st->cso_context, NULL); + return; + } + + stgp = st_geometry_program(st->ctx->GeometryProgram._Current); + assert(stgp->Base.Base.Target == GL_GEOMETRY_PROGRAM_NV); + + st->gp_variant = st_get_basic_variant(st, PIPE_SHADER_GEOMETRY, + &stgp->tgsi, &stgp->variants); + + 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 */ +}; + + + +static void +update_tcp( struct st_context *st ) +{ + struct st_tessctrl_program *sttcp; + + 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); +} + +const struct st_tracked_state st_update_tcp = { + "st_update_tcp", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_TESSCTRL_PROGRAM /* st */ + }, + update_tcp /* update */ +}; + + + +static void +update_tep( struct st_context *st ) +{ + struct st_tesseval_program *sttep; + + if (!st->ctx->TessEvalProgram._Current) { + cso_set_tesseval_shader_handle(st->cso_context, NULL); + return; + } + + 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); + + st_reference_tesseprog(st, &st->tep, sttep); + + cso_set_tesseval_shader_handle(st->cso_context, + st->tep_variant->driver_shader); +} + +const struct st_tracked_state st_update_tep = { + "st_update_tep", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_TESSEVAL_PROGRAM /* st */ + }, + update_tep /* update */ +}; + + + +static void +update_cp( struct st_context *st ) +{ + struct st_compute_program *stcp; + + if (!st->ctx->ComputeProgram._Current) { + cso_set_compute_shader_handle(st->cso_context, NULL); + return; + } + + stcp = st_compute_program(st->ctx->ComputeProgram._Current); + assert(stcp->Base.Base.Target == GL_COMPUTE_PROGRAM_NV); + + st->cp_variant = st_get_cp_variant(st, &stcp->tgsi, &stcp->variants); + + st_reference_compprog(st, &st->cp, stcp); + + cso_set_compute_shader_handle(st->cso_context, + st->cp_variant->driver_shader); +} + +const struct st_tracked_state st_update_cp = { + "st_update_cp", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_COMPUTE_PROGRAM /* st */ + }, + update_cp /* update */ };