void brw_tes_populate_key(struct brw_context *brw, struct brw_tes_prog_key *key) { struct brw_program *tcp = (struct brw_program *) brw->programs[MESA_SHADER_TESS_CTRL]; struct brw_program *tep = (struct brw_program *) brw->programs[MESA_SHADER_TESS_EVAL]; struct gl_program *prog = &tep->program; uint64_t per_vertex_slots = prog->info.inputs_read; uint32_t per_patch_slots = prog->info.patch_inputs_read; memset(key, 0, sizeof(*key)); key->program_string_id = tep->id; /* The TCS may have additional outputs which aren't read by the * TES (possibly for cross-thread communication). These need to * be stored in the Patch URB Entry as well. */ if (tcp) { struct gl_program *tcp_prog = &tcp->program; per_vertex_slots |= tcp_prog->info.outputs_written & ~(VARYING_BIT_TESS_LEVEL_INNER | VARYING_BIT_TESS_LEVEL_OUTER); per_patch_slots |= tcp_prog->info.patch_outputs_written; } key->inputs_read = per_vertex_slots; key->patch_inputs_read = per_patch_slots; /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(&brw->ctx, prog, &key->tex); }
static void brw_vs_populate_key(struct brw_context *brw, struct brw_vs_prog_key *key) { struct gl_context *ctx = &brw->ctx; /* BRW_NEW_VERTEX_PROGRAM */ struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; struct gl_program *prog = (struct gl_program *) brw->vertex_program; int i; memset(key, 0, sizeof(*key)); /* Just upload the program verbatim for now. Always send it all * the inputs it asks for, whether they are varying or not. */ key->program_string_id = vp->id; if (ctx->Transform.ClipPlanesEnabled != 0 && (ctx->API == API_OPENGL_COMPAT || ctx->API == API_OPENGLES) && vp->program.Base.ClipDistanceArraySize == 0) { key->nr_userclip_plane_consts = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; } /* _NEW_POLYGON */ if (brw->gen < 6) { key->copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); } if (prog->OutputsWritten & (VARYING_BIT_COL0 | VARYING_BIT_COL1 | VARYING_BIT_BFC0 | VARYING_BIT_BFC1)) { /* _NEW_LIGHT | _NEW_BUFFERS */ key->clamp_vertex_color = ctx->Light._ClampVertexColor; } /* _NEW_POINT */ if (brw->gen < 6 && ctx->Point.PointSprite) { for (i = 0; i < 8; i++) { if (ctx->Point.CoordReplace[i]) key->point_coord_replace |= (1 << i); } } /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, brw->vs.base.sampler_count, &key->tex); /* BRW_NEW_VS_ATTRIB_WORKAROUNDS */ memcpy(key->gl_attrib_wa_flags, brw->vb.attrib_wa_flags, sizeof(brw->vb.attrib_wa_flags)); }
static void brw_upload_gs_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_stage_state *stage_state = &brw->gs.base; struct brw_gs_prog_key key; /* BRW_NEW_GEOMETRY_PROGRAM */ struct brw_geometry_program *gp = (struct brw_geometry_program *) brw->geometry_program; if (gp == NULL) { /* No geometry shader. Vertex data just passes straight through. */ if (brw->state.dirty.brw & BRW_NEW_VUE_MAP_VS) { brw->vue_map_geom_out = brw->vue_map_vs; brw->state.dirty.brw |= BRW_NEW_VUE_MAP_GEOM_OUT; } return; } struct gl_program *prog = &gp->program.Base; memset(&key, 0, sizeof(key)); key.base.program_string_id = gp->id; brw_setup_vec4_key_clip_info(brw, &key.base, gp->program.Base.UsesClipDistanceOut); /* _NEW_LIGHT | _NEW_BUFFERS */ key.base.clamp_vertex_color = ctx->Light._ClampVertexColor; /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, stage_state->sampler_count, &key.base.tex); /* BRW_NEW_VUE_MAP_VS */ key.input_varyings = brw->vue_map_vs.slots_valid; if (!brw_search_cache(&brw->cache, BRW_GS_PROG, &key, sizeof(key), &stage_state->prog_offset, &brw->gs.prog_data)) { bool success = do_gs_prog(brw, ctx->Shader.CurrentGeometryProgram, gp, &key); assert(success); } brw->gs.base.prog_data = &brw->gs.prog_data->base.base; if (memcmp(&brw->vs.prog_data->base.vue_map, &brw->vue_map_geom_out, sizeof(brw->vue_map_geom_out)) != 0) { brw->vue_map_geom_out = brw->gs.prog_data->base.vue_map; brw->state.dirty.brw |= BRW_NEW_VUE_MAP_GEOM_OUT; } }
void brw_gs_populate_key(struct brw_context *brw, struct brw_gs_prog_key *key) { struct gl_context *ctx = &brw->ctx; struct brw_program *gp = (struct brw_program *) brw->geometry_program; memset(key, 0, sizeof(*key)); key->program_string_id = gp->id; /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, &gp->program, &key->tex); }
static void brw_cs_populate_key(struct brw_context *brw, struct brw_cs_prog_key *key) { struct gl_context *ctx = &brw->ctx; /* BRW_NEW_COMPUTE_PROGRAM */ const struct brw_program *cp = (struct brw_program *) brw->compute_program; const struct gl_program *prog = (struct gl_program *) cp; memset(key, 0, sizeof(*key)); /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, &key->tex); /* The unique compute program ID */ key->program_string_id = cp->id; }
static void brw_gs_populate_key(struct brw_context *brw, struct brw_gs_prog_key *key) { struct gl_context *ctx = &brw->ctx; struct brw_stage_state *stage_state = &brw->gs.base; struct brw_geometry_program *gp = (struct brw_geometry_program *) brw->geometry_program; struct gl_program *prog = &gp->program.Base; memset(key, 0, sizeof(*key)); key->program_string_id = gp->id; /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, stage_state->sampler_count, &key->tex); }
static void brw_gs_populate_key(struct brw_context *brw, struct brw_gs_prog_key *key) { struct gl_context *ctx = &brw->ctx; struct brw_stage_state *stage_state = &brw->gs.base; struct brw_geometry_program *gp = (struct brw_geometry_program *) brw->geometry_program; struct gl_program *prog = &gp->program.Base; memset(key, 0, sizeof(*key)); key->base.program_string_id = gp->id; brw_setup_vue_key_clip_info(brw, &key->base, gp->program.Base.UsesClipDistanceOut); /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, stage_state->sampler_count, &key->base.tex); /* BRW_NEW_VUE_MAP_VS */ key->input_varyings = brw->vue_map_vs.slots_valid; }
void brw_wm_populate_key(struct brw_context *brw, struct brw_wm_prog_key *key) { const struct gen_device_info *devinfo = &brw->screen->devinfo; struct gl_context *ctx = &brw->ctx; /* BRW_NEW_FRAGMENT_PROGRAM */ const struct gl_program *prog = brw->programs[MESA_SHADER_FRAGMENT]; const struct brw_program *fp = brw_program_const(prog); GLuint lookup = 0; GLuint line_aa; memset(key, 0, sizeof(*key)); /* Build the index for table lookup */ if (devinfo->gen < 6) { struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH); /* _NEW_COLOR */ if (prog->info.fs.uses_discard || ctx->Color.AlphaEnabled) { lookup |= BRW_WM_IZ_PS_KILL_ALPHATEST_BIT; } if (prog->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { lookup |= BRW_WM_IZ_PS_COMPUTES_DEPTH_BIT; } /* _NEW_DEPTH */ if (depth_irb && ctx->Depth.Test) { lookup |= BRW_WM_IZ_DEPTH_TEST_ENABLE_BIT; if (brw_depth_writes_enabled(brw)) lookup |= BRW_WM_IZ_DEPTH_WRITE_ENABLE_BIT; } /* _NEW_STENCIL | _NEW_BUFFERS */ if (brw->stencil_enabled) { lookup |= BRW_WM_IZ_STENCIL_TEST_ENABLE_BIT; if (ctx->Stencil.WriteMask[0] || ctx->Stencil.WriteMask[ctx->Stencil._BackFace]) lookup |= BRW_WM_IZ_STENCIL_WRITE_ENABLE_BIT; } key->iz_lookup = lookup; } line_aa = BRW_WM_AA_NEVER; /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */ if (ctx->Line.SmoothFlag) { if (brw->reduced_primitive == GL_LINES) { line_aa = BRW_WM_AA_ALWAYS; } else if (brw->reduced_primitive == GL_TRIANGLES) { if (ctx->Polygon.FrontMode == GL_LINE) { line_aa = BRW_WM_AA_SOMETIMES; if (ctx->Polygon.BackMode == GL_LINE || (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_BACK)) line_aa = BRW_WM_AA_ALWAYS; } else if (ctx->Polygon.BackMode == GL_LINE) { line_aa = BRW_WM_AA_SOMETIMES; if ((ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT)) line_aa = BRW_WM_AA_ALWAYS; } } } key->line_aa = line_aa; /* _NEW_HINT */ key->high_quality_derivatives = prog->info.uses_fddx_fddy && ctx->Hint.FragmentShaderDerivative == GL_NICEST; if (devinfo->gen < 6) key->stats_wm = brw->stats_wm; /* _NEW_LIGHT */ key->flat_shade = (prog->info.inputs_read & (VARYING_BIT_COL0 | VARYING_BIT_COL1)) && (ctx->Light.ShadeModel == GL_FLAT); /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */ key->clamp_fragment_color = ctx->Color._ClampFragmentColor; /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, &key->tex); /* _NEW_BUFFERS */ key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers; /* _NEW_COLOR */ key->force_dual_color_blend = brw->dual_color_blend_by_location && (ctx->Color.BlendEnabled & 1) && ctx->Color.Blend[0]._UsesDualSrc; /* _NEW_MULTISAMPLE, _NEW_BUFFERS */ key->alpha_to_coverage = _mesa_is_alpha_to_coverage_enabled(ctx); /* _NEW_COLOR, _NEW_BUFFERS */ key->alpha_test_replicate_alpha = ctx->DrawBuffer->_NumColorDrawBuffers > 1 && _mesa_is_alpha_test_enabled(ctx); /* _NEW_BUFFERS _NEW_MULTISAMPLE */ /* Ignore sample qualifier while computing this flag. */ if (ctx->Multisample.Enabled) { key->persample_interp = ctx->Multisample.SampleShading && (ctx->Multisample.MinSampleShadingValue * _mesa_geometric_samples(ctx->DrawBuffer) > 1); key->multisample_fbo = _mesa_geometric_samples(ctx->DrawBuffer) > 1; } /* BRW_NEW_VUE_MAP_GEOM_OUT */ if (devinfo->gen < 6 || util_bitcount64(prog->info.inputs_read & BRW_FS_VARYING_INPUT_MASK) > 16) { key->input_slots_valid = brw->vue_map_geom_out.slots_valid; } /* _NEW_COLOR | _NEW_BUFFERS */ /* Pre-gen6, the hardware alpha test always used each render * target's alpha to do alpha test, as opposed to render target 0's alpha * like GL requires. Fix that by building the alpha test into the * shader, and we'll skip enabling the fixed function alpha test. */ if (devinfo->gen < 6 && ctx->DrawBuffer->_NumColorDrawBuffers > 1 && ctx->Color.AlphaEnabled) { key->alpha_test_func = ctx->Color.AlphaFunc; key->alpha_test_ref = ctx->Color.AlphaRef; } /* The unique fragment program ID */ key->program_string_id = fp->id; /* Whether reads from the framebuffer should behave coherently. */ key->coherent_fb_fetch = ctx->Extensions.EXT_shader_framebuffer_fetch; }
static void brw_wm_populate_key(struct brw_context *brw, struct brw_wm_prog_key *key) { struct gl_context *ctx = &brw->ctx; /* BRW_NEW_FRAGMENT_PROGRAM */ const struct brw_fragment_program *fp = (struct brw_fragment_program *) brw->fragment_program; const struct gl_program *prog = (struct gl_program *) brw->fragment_program; GLuint lookup = 0; GLuint line_aa; bool program_uses_dfdy = fp->program.UsesDFdy; const bool multisample_fbo = _mesa_geometric_samples(ctx->DrawBuffer) > 1; memset(key, 0, sizeof(*key)); /* Build the index for table lookup */ if (brw->gen < 6) { /* _NEW_COLOR */ if (fp->program.UsesKill || ctx->Color.AlphaEnabled) lookup |= IZ_PS_KILL_ALPHATEST_BIT; if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) lookup |= IZ_PS_COMPUTES_DEPTH_BIT; /* _NEW_DEPTH */ if (ctx->Depth.Test) lookup |= IZ_DEPTH_TEST_ENABLE_BIT; if (ctx->Depth.Test && ctx->Depth.Mask) /* ?? */ lookup |= IZ_DEPTH_WRITE_ENABLE_BIT; /* _NEW_STENCIL | _NEW_BUFFERS */ if (ctx->Stencil._Enabled) { lookup |= IZ_STENCIL_TEST_ENABLE_BIT; if (ctx->Stencil.WriteMask[0] || ctx->Stencil.WriteMask[ctx->Stencil._BackFace]) lookup |= IZ_STENCIL_WRITE_ENABLE_BIT; } key->iz_lookup = lookup; } line_aa = AA_NEVER; /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */ if (ctx->Line.SmoothFlag) { if (brw->reduced_primitive == GL_LINES) { line_aa = AA_ALWAYS; } else if (brw->reduced_primitive == GL_TRIANGLES) { if (ctx->Polygon.FrontMode == GL_LINE) { line_aa = AA_SOMETIMES; if (ctx->Polygon.BackMode == GL_LINE || (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_BACK)) line_aa = AA_ALWAYS; } else if (ctx->Polygon.BackMode == GL_LINE) { line_aa = AA_SOMETIMES; if ((ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT)) line_aa = AA_ALWAYS; } } } key->line_aa = line_aa; /* _NEW_HINT */ key->high_quality_derivatives = ctx->Hint.FragmentShaderDerivative == GL_NICEST; if (brw->gen < 6) key->stats_wm = brw->stats_wm; /* _NEW_LIGHT */ key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT); /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */ key->clamp_fragment_color = ctx->Color._ClampFragmentColor; /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, brw->wm.base.sampler_count, &key->tex); /* _NEW_BUFFERS */ /* * Include the draw buffer origin and height so that we can calculate * fragment position values relative to the bottom left of the drawable, * from the incoming screen origin relative position we get as part of our * payload. * * This is only needed for the WM_WPOSXY opcode when the fragment program * uses the gl_FragCoord input. * * We could avoid recompiling by including this as a constant referenced by * our program, but if we were to do that it would also be nice to handle * getting that constant updated at batchbuffer submit time (when we * hold the lock and know where the buffer really is) rather than at emit * time when we don't hold the lock and are just guessing. We could also * just avoid using this as key data if the program doesn't use * fragment.position. * * For DRI2 the origin_x/y will always be (0,0) but we still need the * drawable height in order to invert the Y axis. */ if (fp->program.Base.InputsRead & VARYING_BIT_POS) { key->drawable_height = _mesa_geometric_height(ctx->DrawBuffer); } if ((fp->program.Base.InputsRead & VARYING_BIT_POS) || program_uses_dfdy) { key->render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); } /* _NEW_BUFFERS */ key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers; /* _NEW_MULTISAMPLE, _NEW_COLOR, _NEW_BUFFERS */ key->replicate_alpha = ctx->DrawBuffer->_NumColorDrawBuffers > 1 && (ctx->Multisample.SampleAlphaToCoverage || ctx->Color.AlphaEnabled); /* _NEW_BUFFERS _NEW_MULTISAMPLE */ /* Ignore sample qualifier while computing this flag. */ key->persample_shading = _mesa_get_min_invocations_per_fragment(ctx, &fp->program, true) > 1; if (key->persample_shading) key->persample_2x = _mesa_geometric_samples(ctx->DrawBuffer) == 2; key->compute_pos_offset = _mesa_get_min_invocations_per_fragment(ctx, &fp->program, false) > 1 && fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_POS; key->compute_sample_id = multisample_fbo && ctx->Multisample.Enabled && (fp->program.Base.SystemValuesRead & SYSTEM_BIT_SAMPLE_ID); /* BRW_NEW_VUE_MAP_GEOM_OUT */ if (brw->gen < 6 || _mesa_bitcount_64(fp->program.Base.InputsRead & BRW_FS_VARYING_INPUT_MASK) > 16) key->input_slots_valid = brw->vue_map_geom_out.slots_valid; /* _NEW_COLOR | _NEW_BUFFERS */ /* Pre-gen6, the hardware alpha test always used each render * target's alpha to do alpha test, as opposed to render target 0's alpha * like GL requires. Fix that by building the alpha test into the * shader, and we'll skip enabling the fixed function alpha test. */ if (brw->gen < 6 && ctx->DrawBuffer->_NumColorDrawBuffers > 1 && ctx->Color.AlphaEnabled) { key->alpha_test_func = ctx->Color.AlphaFunc; key->alpha_test_ref = ctx->Color.AlphaRef; } /* The unique fragment program ID */ key->program_string_id = fp->id; }
static void brw_upload_vs_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_vs_prog_key key; /* BRW_NEW_VERTEX_PROGRAM */ struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; struct gl_program *prog = (struct gl_program *) brw->vertex_program; int i; memset(&key, 0, sizeof(key)); /* Just upload the program verbatim for now. Always send it all * the inputs it asks for, whether they are varying or not. */ key.base.program_string_id = vp->id; key.base.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); key.base.uses_clip_distance = vp->program.UsesClipDistance; if (key.base.userclip_active && !key.base.uses_clip_distance) { if (brw->gen < 6) { key.base.nr_userclip_plane_consts = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); key.base.userclip_planes_enabled_gen_4_5 = ctx->Transform.ClipPlanesEnabled; } else { key.base.nr_userclip_plane_consts = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; } } /* _NEW_POLYGON */ if (brw->gen < 6) { key.copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); } /* _NEW_LIGHT | _NEW_BUFFERS */ key.base.clamp_vertex_color = ctx->Light._ClampVertexColor; /* _NEW_POINT */ if (brw->gen < 6 && ctx->Point.PointSprite) { for (i = 0; i < 8; i++) { if (ctx->Point.CoordReplace[i]) key.point_coord_replace |= (1 << i); } } /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, &key.base.tex); /* BRW_NEW_VERTICES */ if (brw->gen < 8 && !brw->is_haswell) { /* Prior to Haswell, the hardware can't natively support GL_FIXED or * 2_10_10_10_REV vertex formats. Set appropriate workaround flags. */ for (i = 0; i < VERT_ATTRIB_MAX; i++) { if (!(vp->program.Base.InputsRead & BITFIELD64_BIT(i))) continue; uint8_t wa_flags = 0; switch (brw->vb.inputs[i].glarray->Type) { case GL_FIXED: wa_flags = brw->vb.inputs[i].glarray->Size; break; case GL_INT_2_10_10_10_REV: wa_flags |= BRW_ATTRIB_WA_SIGN; /* fallthough */ case GL_UNSIGNED_INT_2_10_10_10_REV: if (brw->vb.inputs[i].glarray->Format == GL_BGRA) wa_flags |= BRW_ATTRIB_WA_BGRA; if (brw->vb.inputs[i].glarray->Normalized) wa_flags |= BRW_ATTRIB_WA_NORMALIZE; else if (!brw->vb.inputs[i].glarray->Integer) wa_flags |= BRW_ATTRIB_WA_SCALE; break; } key.gl_attrib_wa_flags[i] = wa_flags; } } if (!brw_search_cache(&brw->cache, BRW_VS_PROG, &key, sizeof(key), &brw->vs.prog_offset, &brw->vs.prog_data)) { bool success = do_vs_prog(brw, ctx->Shader.CurrentVertexProgram, vp, &key); assert(success); } if (memcmp(&brw->vs.prog_data->base.vue_map, &brw->vue_map_geom_out, sizeof(brw->vue_map_geom_out)) != 0) { brw->vue_map_geom_out = brw->vs.prog_data->base.vue_map; brw->state.dirty.brw |= BRW_NEW_VUE_MAP_GEOM_OUT; } }
static void brw_upload_vs_prog(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct brw_vs_prog_key key; /* BRW_NEW_VERTEX_PROGRAM */ struct brw_vertex_program *vp = (struct brw_vertex_program *)brw->vertex_program; struct gl_program *prog = (struct gl_program *) brw->vertex_program; int i; memset(&key, 0, sizeof(key)); /* Just upload the program verbatim for now. Always send it all * the inputs it asks for, whether they are varying or not. */ key.program_string_id = vp->id; key.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); key.uses_clip_distance = vp->program.UsesClipDistance; if (key.userclip_active && !key.uses_clip_distance) { if (intel->gen < 6) { key.nr_userclip_plane_consts = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); key.userclip_planes_enabled_gen_4_5 = ctx->Transform.ClipPlanesEnabled; } else { key.nr_userclip_plane_consts = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; } } /* _NEW_POLYGON */ if (intel->gen < 6) { key.copy_edgeflag = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); } /* _NEW_LIGHT | _NEW_BUFFERS */ key.clamp_vertex_color = ctx->Light._ClampVertexColor; /* _NEW_POINT */ if (ctx->Point.PointSprite) { for (i = 0; i < 8; i++) { if (ctx->Point.CoordReplace[i]) key.point_coord_replace |= (1 << i); } } /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, &key.tex); /* BRW_NEW_VERTICES */ for (i = 0; i < VERT_ATTRIB_MAX; i++) { if (vp->program.Base.InputsRead & BITFIELD64_BIT(i) && brw->vb.inputs[i].glarray->Type == GL_FIXED) { key.gl_fixed_input_size[i] = brw->vb.inputs[i].glarray->Size; } } if (!brw_search_cache(&brw->cache, BRW_VS_PROG, &key, sizeof(key), &brw->vs.prog_offset, &brw->vs.prog_data)) { bool success = do_vs_prog(brw, ctx->Shader.CurrentVertexProgram, vp, &key); assert(success); } brw->vs.constant_map = ((int8_t *)brw->vs.prog_data + sizeof(*brw->vs.prog_data)); }
static void brw_wm_populate_key( struct brw_context *brw, struct brw_wm_prog_key *key ) { struct gl_context *ctx = &brw->intel.ctx; struct intel_context *intel = &brw->intel; /* BRW_NEW_FRAGMENT_PROGRAM */ const struct brw_fragment_program *fp = (struct brw_fragment_program *)brw->fragment_program; const struct gl_program *prog = (struct gl_program *) brw->fragment_program; GLuint lookup = 0; GLuint line_aa; bool program_uses_dfdy = fp->program.UsesDFdy; memset(key, 0, sizeof(*key)); /* Build the index for table lookup */ if (intel->gen < 6) { /* _NEW_COLOR */ if (fp->program.UsesKill || ctx->Color.AlphaEnabled) lookup |= IZ_PS_KILL_ALPHATEST_BIT; if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) lookup |= IZ_PS_COMPUTES_DEPTH_BIT; /* _NEW_DEPTH */ if (ctx->Depth.Test) lookup |= IZ_DEPTH_TEST_ENABLE_BIT; if (ctx->Depth.Test && ctx->Depth.Mask) /* ?? */ lookup |= IZ_DEPTH_WRITE_ENABLE_BIT; /* _NEW_STENCIL */ if (ctx->Stencil._Enabled) { lookup |= IZ_STENCIL_TEST_ENABLE_BIT; if (ctx->Stencil.WriteMask[0] || ctx->Stencil.WriteMask[ctx->Stencil._BackFace]) lookup |= IZ_STENCIL_WRITE_ENABLE_BIT; } key->iz_lookup = lookup; } line_aa = AA_NEVER; /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */ if (ctx->Line.SmoothFlag) { if (brw->intel.reduced_primitive == GL_LINES) { line_aa = AA_ALWAYS; } else if (brw->intel.reduced_primitive == GL_TRIANGLES) { if (ctx->Polygon.FrontMode == GL_LINE) { line_aa = AA_SOMETIMES; if (ctx->Polygon.BackMode == GL_LINE || (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_BACK)) line_aa = AA_ALWAYS; } else if (ctx->Polygon.BackMode == GL_LINE) { line_aa = AA_SOMETIMES; if ((ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT)) line_aa = AA_ALWAYS; } } } key->line_aa = line_aa; if (intel->gen < 6) key->stats_wm = brw->intel.stats_wm; /* BRW_NEW_WM_INPUT_DIMENSIONS */ /* Only set this for fixed function. The optimization it enables isn't * useful for programs using shaders. */ if (ctx->Shader.CurrentFragmentProgram) key->proj_attrib_mask = 0xffffffff; else key->proj_attrib_mask = brw->wm.input_size_masks[4-1]; /* _NEW_LIGHT */ key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT); /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */ key->clamp_fragment_color = ctx->Color._ClampFragmentColor; /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, &key->tex); /* _NEW_BUFFERS */ /* * Include the draw buffer origin and height so that we can calculate * fragment position values relative to the bottom left of the drawable, * from the incoming screen origin relative position we get as part of our * payload. * * This is only needed for the WM_WPOSXY opcode when the fragment program * uses the gl_FragCoord input. * * We could avoid recompiling by including this as a constant referenced by * our program, but if we were to do that it would also be nice to handle * getting that constant updated at batchbuffer submit time (when we * hold the lock and know where the buffer really is) rather than at emit * time when we don't hold the lock and are just guessing. We could also * just avoid using this as key data if the program doesn't use * fragment.position. * * For DRI2 the origin_x/y will always be (0,0) but we still need the * drawable height in order to invert the Y axis. */ if (fp->program.Base.InputsRead & FRAG_BIT_WPOS) { key->drawable_height = ctx->DrawBuffer->Height; } if ((fp->program.Base.InputsRead & FRAG_BIT_WPOS) || program_uses_dfdy) { key->render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); } /* _NEW_BUFFERS */ key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers; /* _NEW_MULTISAMPLE */ key->sample_alpha_to_coverage = ctx->Multisample.SampleAlphaToCoverage; /* CACHE_NEW_VS_PROG */ if (intel->gen < 6) key->vp_outputs_written = brw->vs.prog_data->outputs_written; /* The unique fragment program ID */ key->program_string_id = fp->id; }
static void brw_wm_populate_key(struct brw_context *brw, struct brw_wm_prog_key *key) { struct gl_context *ctx = &brw->ctx; /* BRW_NEW_FRAGMENT_PROGRAM */ const struct brw_fragment_program *fp = (struct brw_fragment_program *) brw->fragment_program; const struct gl_program *prog = (struct gl_program *) brw->fragment_program; GLuint lookup = 0; GLuint line_aa; memset(key, 0, sizeof(*key)); /* Build the index for table lookup */ if (brw->gen < 6) { /* _NEW_COLOR */ if (fp->program.UsesKill || ctx->Color.AlphaEnabled) lookup |= IZ_PS_KILL_ALPHATEST_BIT; if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) lookup |= IZ_PS_COMPUTES_DEPTH_BIT; /* _NEW_DEPTH */ if (ctx->Depth.Test) lookup |= IZ_DEPTH_TEST_ENABLE_BIT; if (ctx->Depth.Test && ctx->Depth.Mask) /* ?? */ lookup |= IZ_DEPTH_WRITE_ENABLE_BIT; /* _NEW_STENCIL | _NEW_BUFFERS */ if (ctx->Stencil._Enabled) { lookup |= IZ_STENCIL_TEST_ENABLE_BIT; if (ctx->Stencil.WriteMask[0] || ctx->Stencil.WriteMask[ctx->Stencil._BackFace]) lookup |= IZ_STENCIL_WRITE_ENABLE_BIT; } key->iz_lookup = lookup; } line_aa = AA_NEVER; /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */ if (ctx->Line.SmoothFlag) { if (brw->reduced_primitive == GL_LINES) { line_aa = AA_ALWAYS; } else if (brw->reduced_primitive == GL_TRIANGLES) { if (ctx->Polygon.FrontMode == GL_LINE) { line_aa = AA_SOMETIMES; if (ctx->Polygon.BackMode == GL_LINE || (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_BACK)) line_aa = AA_ALWAYS; } else if (ctx->Polygon.BackMode == GL_LINE) { line_aa = AA_SOMETIMES; if ((ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT)) line_aa = AA_ALWAYS; } } } key->line_aa = line_aa; /* _NEW_HINT */ key->high_quality_derivatives = ctx->Hint.FragmentShaderDerivative == GL_NICEST; if (brw->gen < 6) key->stats_wm = brw->stats_wm; /* _NEW_LIGHT */ key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT); /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */ key->clamp_fragment_color = ctx->Color._ClampFragmentColor; /* _NEW_TEXTURE */ brw_populate_sampler_prog_key_data(ctx, prog, brw->wm.base.sampler_count, &key->tex); /* _NEW_BUFFERS */ key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers; /* _NEW_COLOR */ key->force_dual_color_blend = brw->dual_color_blend_by_location && (ctx->Color.BlendEnabled & 1) && ctx->Color.Blend[0]._UsesDualSrc; /* _NEW_MULTISAMPLE, _NEW_COLOR, _NEW_BUFFERS */ key->replicate_alpha = ctx->DrawBuffer->_NumColorDrawBuffers > 1 && (ctx->Multisample.SampleAlphaToCoverage || ctx->Color.AlphaEnabled); /* _NEW_BUFFERS _NEW_MULTISAMPLE */ /* Ignore sample qualifier while computing this flag. */ if (ctx->Multisample.Enabled) { key->persample_interp = ctx->Multisample.SampleShading && (ctx->Multisample.MinSampleShadingValue * _mesa_geometric_samples(ctx->DrawBuffer) > 1); key->multisample_fbo = _mesa_geometric_samples(ctx->DrawBuffer) > 1; } /* BRW_NEW_VUE_MAP_GEOM_OUT */ if (brw->gen < 6 || _mesa_bitcount_64(fp->program.Base.InputsRead & BRW_FS_VARYING_INPUT_MASK) > 16) key->input_slots_valid = brw->vue_map_geom_out.slots_valid; /* _NEW_COLOR | _NEW_BUFFERS */ /* Pre-gen6, the hardware alpha test always used each render * target's alpha to do alpha test, as opposed to render target 0's alpha * like GL requires. Fix that by building the alpha test into the * shader, and we'll skip enabling the fixed function alpha test. */ if (brw->gen < 6 && ctx->DrawBuffer->_NumColorDrawBuffers > 1 && ctx->Color.AlphaEnabled) { key->alpha_test_func = ctx->Color.AlphaFunc; key->alpha_test_ref = ctx->Color.AlphaRef; } /* The unique fragment program ID */ key->program_string_id = fp->id; }