void brw_upload_cs_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_cs_prog_key key; struct brw_compute_program *cp = (struct brw_compute_program *) brw->compute_program; if (!cp) return; if (!brw_state_dirty(brw, 0, BRW_NEW_COMPUTE_PROGRAM)) return; brw_cs_populate_key(brw, &key); if (!brw_search_cache(&brw->cache, BRW_CACHE_CS_PROG, &key, sizeof(key), &brw->cs.base.prog_offset, &brw->cs.prog_data)) { bool success = brw_codegen_cs_prog(brw, ctx->Shader.CurrentProgram[MESA_SHADER_COMPUTE], cp, &key); (void) success; assert(success); } brw->cs.base.prog_data = &brw->cs.prog_data->base; }
void brw_upload_tes_prog(struct brw_context *brw) { struct brw_stage_state *stage_state = &brw->tes.base; struct brw_tes_prog_key key; /* BRW_NEW_TESS_PROGRAMS */ struct brw_program *tep = (struct brw_program *) brw->programs[MESA_SHADER_TESS_EVAL]; if (!brw_state_dirty(brw, _NEW_TEXTURE, BRW_NEW_TESS_PROGRAMS)) return; brw_tes_populate_key(brw, &key); if (brw_search_cache(&brw->cache, BRW_CACHE_TES_PROG, &key, sizeof(key), &stage_state->prog_offset, &brw->tes.base.prog_data, true)) return; if (brw_disk_cache_upload_program(brw, MESA_SHADER_TESS_EVAL)) return; tep = (struct brw_program *) brw->programs[MESA_SHADER_TESS_EVAL]; tep->id = key.program_string_id; MAYBE_UNUSED bool success = brw_codegen_tes_prog(brw, tep, &key); assert(success); }
static bool brw_gs_state_dirty(struct brw_context *brw) { return brw_state_dirty(brw, _NEW_TEXTURE, BRW_NEW_GEOMETRY_PROGRAM | BRW_NEW_TRANSFORM_FEEDBACK); }
static bool brw_ff_gs_state_dirty(struct brw_context *brw) { return brw_state_dirty(brw, _NEW_LIGHT, BRW_NEW_PRIMITIVE | BRW_NEW_TRANSFORM_FEEDBACK | BRW_NEW_VS_PROG_DATA); }
static bool brw_vs_state_dirty(struct brw_context *brw) { return brw_state_dirty(brw, _NEW_BUFFERS | _NEW_LIGHT | _NEW_POINT | _NEW_POLYGON | _NEW_TEXTURE | _NEW_TRANSFORM, BRW_NEW_VERTEX_PROGRAM | BRW_NEW_VS_ATTRIB_WORKAROUNDS); }
static bool brw_wm_state_dirty(const struct brw_context *brw) { return brw_state_dirty(brw, _NEW_BUFFERS | _NEW_COLOR | _NEW_DEPTH | _NEW_FRAG_CLAMP | _NEW_HINT | _NEW_LIGHT | _NEW_LINE | _NEW_MULTISAMPLE | _NEW_POLYGON | _NEW_STENCIL | _NEW_TEXTURE, BRW_NEW_FRAGMENT_PROGRAM | BRW_NEW_REDUCED_PRIMITIVE | BRW_NEW_STATS_WM | BRW_NEW_VUE_MAP_GEOM_OUT); }
/* Calculate interpolants for triangle and line rasterization. */ void brw_upload_sf_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_sf_prog_key key; if (!brw_state_dirty(brw, _NEW_BUFFERS | _NEW_HINT | _NEW_LIGHT | _NEW_POINT | _NEW_POLYGON | _NEW_PROGRAM | _NEW_TRANSFORM, BRW_NEW_BLORP | BRW_NEW_FS_PROG_DATA | BRW_NEW_REDUCED_PRIMITIVE | BRW_NEW_VUE_MAP_GEOM_OUT)) return; /* _NEW_BUFFERS */ bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); memset(&key, 0, sizeof(key)); /* Populate the key, noting state dependencies: */ /* BRW_NEW_VUE_MAP_GEOM_OUT */ key.attrs = brw->vue_map_geom_out.slots_valid; /* BRW_NEW_REDUCED_PRIMITIVE */ switch (brw->reduced_primitive) { case GL_TRIANGLES: /* NOTE: We just use the edgeflag attribute as an indicator that * unfilled triangles are active. We don't actually do the * edgeflag testing here, it is already done in the clip * program. */ if (key.attrs & BITFIELD64_BIT(VARYING_SLOT_EDGE)) key.primitive = BRW_SF_PRIM_UNFILLED_TRIS; else key.primitive = BRW_SF_PRIM_TRIANGLES; break; case GL_LINES: key.primitive = BRW_SF_PRIM_LINES; break; case GL_POINTS: key.primitive = BRW_SF_PRIM_POINTS; break; } /* _NEW_TRANSFORM */ key.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); /* _NEW_POINT */ key.do_point_sprite = ctx->Point.PointSprite; if (key.do_point_sprite) { key.point_sprite_coord_replace = ctx->Point.CoordReplace & 0xff; } if (brw->programs[MESA_SHADER_FRAGMENT]->info.inputs_read & BITFIELD64_BIT(VARYING_SLOT_PNTC)) { key.do_point_coord = 1; } /* * Window coordinates in a FBO are inverted, which means point * sprite origin must be inverted, too. */ if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) key.sprite_origin_lower_left = true; /* BRW_NEW_FS_PROG_DATA */ const struct brw_wm_prog_data *wm_prog_data = brw_wm_prog_data(brw->wm.base.prog_data); if (wm_prog_data) { key.contains_flat_varying = wm_prog_data->contains_flat_varying; STATIC_ASSERT(sizeof(key.interp_mode) == sizeof(wm_prog_data->interp_mode)); memcpy(key.interp_mode, wm_prog_data->interp_mode, sizeof(key.interp_mode)); } /* _NEW_LIGHT | _NEW_PROGRAM */ key.do_twoside_color = _mesa_vertex_program_two_side_enabled(ctx); /* _NEW_POLYGON */ if (key.do_twoside_color) { /* If we're rendering to a FBO, we have to invert the polygon * face orientation, just as we invert the viewport in * sf_unit_create_from_key(). */ key.frontface_ccw = brw->polygon_front_bit == render_to_fbo; } if (!brw_search_cache(&brw->cache, BRW_CACHE_SF_PROG, &key, sizeof(key), &brw->sf.prog_offset, &brw->sf.prog_data)) { compile_sf_prog( brw, &key ); } }
/* Calculate interpolants for triangle and line rasterization. */ void brw_upload_clip_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_clip_prog_key key; if (!brw_state_dirty(brw, _NEW_BUFFERS | _NEW_LIGHT | _NEW_POLYGON | _NEW_TRANSFORM, BRW_NEW_BLORP | BRW_NEW_FS_PROG_DATA | BRW_NEW_REDUCED_PRIMITIVE | BRW_NEW_VUE_MAP_GEOM_OUT)) return; memset(&key, 0, sizeof(key)); /* Populate the key: */ /* BRW_NEW_FS_PROG_DATA */ const struct brw_wm_prog_data *wm_prog_data = brw_wm_prog_data(brw->wm.base.prog_data); if (wm_prog_data) { key.contains_flat_varying = wm_prog_data->contains_flat_varying; key.contains_noperspective_varying = wm_prog_data->contains_noperspective_varying; STATIC_ASSERT(sizeof(key.interp_mode) == sizeof(wm_prog_data->interp_mode)); memcpy(key.interp_mode, wm_prog_data->interp_mode, sizeof(key.interp_mode)); } /* BRW_NEW_REDUCED_PRIMITIVE */ key.primitive = brw->reduced_primitive; /* BRW_NEW_VUE_MAP_GEOM_OUT */ key.attrs = brw->vue_map_geom_out.slots_valid; /* _NEW_LIGHT */ key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION); /* _NEW_TRANSFORM (also part of VUE map)*/ if (ctx->Transform.ClipPlanesEnabled) key.nr_userclip = _mesa_logbase2(ctx->Transform.ClipPlanesEnabled) + 1; if (brw->gen == 5) key.clip_mode = BRW_CLIP_MODE_KERNEL_CLIP; else key.clip_mode = BRW_CLIP_MODE_NORMAL; /* _NEW_POLYGON */ if (key.primitive == GL_TRIANGLES) { if (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) key.clip_mode = BRW_CLIP_MODE_REJECT_ALL; else { GLuint fill_front = BRW_CLIP_FILL_MODE_CULL; GLuint fill_back = BRW_CLIP_FILL_MODE_CULL; GLuint offset_front = 0; GLuint offset_back = 0; if (!ctx->Polygon.CullFlag || ctx->Polygon.CullFaceMode != GL_FRONT) { switch (ctx->Polygon.FrontMode) { case GL_FILL: fill_front = BRW_CLIP_FILL_MODE_FILL; offset_front = 0; break; case GL_LINE: fill_front = BRW_CLIP_FILL_MODE_LINE; offset_front = ctx->Polygon.OffsetLine; break; case GL_POINT: fill_front = BRW_CLIP_FILL_MODE_POINT; offset_front = ctx->Polygon.OffsetPoint; break; } } if (!ctx->Polygon.CullFlag || ctx->Polygon.CullFaceMode != GL_BACK) { switch (ctx->Polygon.BackMode) { case GL_FILL: fill_back = BRW_CLIP_FILL_MODE_FILL; offset_back = 0; break; case GL_LINE: fill_back = BRW_CLIP_FILL_MODE_LINE; offset_back = ctx->Polygon.OffsetLine; break; case GL_POINT: fill_back = BRW_CLIP_FILL_MODE_POINT; offset_back = ctx->Polygon.OffsetPoint; break; } } if (ctx->Polygon.BackMode != GL_FILL || ctx->Polygon.FrontMode != GL_FILL) { key.do_unfilled = 1; /* Most cases the fixed function units will handle. Cases where * one or more polygon faces are unfilled will require help: */ key.clip_mode = BRW_CLIP_MODE_CLIP_NON_REJECTED; if (offset_back || offset_front) { /* _NEW_POLYGON, _NEW_BUFFERS */ key.offset_units = ctx->Polygon.OffsetUnits * ctx->DrawBuffer->_MRD * 2; key.offset_factor = ctx->Polygon.OffsetFactor * ctx->DrawBuffer->_MRD; key.offset_clamp = ctx->Polygon.OffsetClamp * ctx->DrawBuffer->_MRD; } if (!brw->polygon_front_bit) { key.fill_ccw = fill_front; key.fill_cw = fill_back; key.offset_ccw = offset_front; key.offset_cw = offset_back; if (ctx->Light.Model.TwoSide && key.fill_cw != BRW_CLIP_FILL_MODE_CULL) key.copy_bfc_cw = 1; } else { key.fill_cw = fill_front; key.fill_ccw = fill_back; key.offset_cw = offset_front; key.offset_ccw = offset_back; if (ctx->Light.Model.TwoSide && key.fill_ccw != BRW_CLIP_FILL_MODE_CULL) key.copy_bfc_ccw = 1; } } } } if (!brw_search_cache(&brw->cache, BRW_CACHE_CLIP_PROG, &key, sizeof(key), &brw->clip.prog_offset, &brw->clip.prog_data)) { compile_clip_prog( brw, &key ); } }
/* Calculate interpolants for triangle and line rasterization. */ void brw_upload_sf_prog(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; struct brw_sf_prog_key key; if (!brw_state_dirty(brw, _NEW_BUFFERS | _NEW_HINT | _NEW_LIGHT | _NEW_POINT | _NEW_POLYGON | _NEW_PROGRAM | _NEW_TRANSFORM, BRW_NEW_BLORP | BRW_NEW_INTERPOLATION_MAP | BRW_NEW_REDUCED_PRIMITIVE | BRW_NEW_VUE_MAP_GEOM_OUT)) return; /* _NEW_BUFFERS */ bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); memset(&key, 0, sizeof(key)); /* Populate the key, noting state dependencies: */ /* BRW_NEW_VUE_MAP_GEOM_OUT */ key.attrs = brw->vue_map_geom_out.slots_valid; /* BRW_NEW_REDUCED_PRIMITIVE */ switch (brw->reduced_primitive) { case GL_TRIANGLES: /* NOTE: We just use the edgeflag attribute as an indicator that * unfilled triangles are active. We don't actually do the * edgeflag testing here, it is already done in the clip * program. */ if (key.attrs & BITFIELD64_BIT(VARYING_SLOT_EDGE)) key.primitive = SF_UNFILLED_TRIS; else key.primitive = SF_TRIANGLES; break; case GL_LINES: key.primitive = SF_LINES; break; case GL_POINTS: key.primitive = SF_POINTS; break; } /* _NEW_TRANSFORM */ key.userclip_active = (ctx->Transform.ClipPlanesEnabled != 0); /* _NEW_POINT */ key.do_point_sprite = ctx->Point.PointSprite; if (key.do_point_sprite) { key.point_sprite_coord_replace = ctx->Point.CoordReplace & 0xff; } if (brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(VARYING_SLOT_PNTC)) key.do_point_coord = 1; /* * Window coordinates in a FBO are inverted, which means point * sprite origin must be inverted, too. */ if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo) key.sprite_origin_lower_left = true; /* BRW_NEW_INTERPOLATION_MAP */ key.interpolation_mode = brw->interpolation_mode; /* _NEW_LIGHT | _NEW_PROGRAM */ key.do_twoside_color = ((ctx->Light.Enabled && ctx->Light.Model.TwoSide) || ctx->VertexProgram._TwoSideEnabled); /* _NEW_POLYGON */ if (key.do_twoside_color) { /* If we're rendering to a FBO, we have to invert the polygon * face orientation, just as we invert the viewport in * sf_unit_create_from_key(). */ key.frontface_ccw = ctx->Polygon._FrontBit == render_to_fbo; } if (!brw_search_cache(&brw->cache, BRW_CACHE_SF_PROG, &key, sizeof(key), &brw->sf.prog_offset, &brw->sf.prog_data)) { compile_sf_prog( brw, &key ); } }
/* Set up interpolation modes for every element in the VUE */ void brw_setup_vue_interpolation(struct brw_context *brw) { const struct gl_fragment_program *fprog = brw->fragment_program; struct brw_vue_map *vue_map = &brw->vue_map_geom_out; if (!brw_state_dirty(brw, _NEW_LIGHT, BRW_NEW_BLORP | BRW_NEW_FRAGMENT_PROGRAM | BRW_NEW_VUE_MAP_GEOM_OUT)) return; memset(&brw->interpolation_mode, INTERP_MODE_NONE, sizeof(brw->interpolation_mode)); brw->ctx.NewDriverState |= BRW_NEW_INTERPOLATION_MAP; if (!fprog) return; for (int i = 0; i < vue_map->num_slots; i++) { int varying = vue_map->slot_to_varying[i]; if (varying == -1) continue; /* HPOS always wants noperspective. setting it up here allows * us to not need special handling in the SF program. */ if (varying == VARYING_SLOT_POS) { brw->interpolation_mode.mode[i] = INTERP_MODE_NOPERSPECTIVE; continue; } int frag_attrib = varying; if (varying == VARYING_SLOT_BFC0 || varying == VARYING_SLOT_BFC1) frag_attrib = varying - VARYING_SLOT_BFC0 + VARYING_SLOT_COL0; if (!(fprog->Base.nir->info.inputs_read & BITFIELD64_BIT(frag_attrib))) continue; enum glsl_interp_mode mode = fprog->InterpQualifier[frag_attrib]; /* If the mode is not specified, the default varies: Color values * follow GL_SHADE_MODEL; everything else is smooth. */ if (mode == INTERP_MODE_NONE) { if (frag_attrib == VARYING_SLOT_COL0 || frag_attrib == VARYING_SLOT_COL1) mode = brw->ctx.Light.ShadeModel == GL_FLAT ? INTERP_MODE_FLAT : INTERP_MODE_SMOOTH; else mode = INTERP_MODE_SMOOTH; } brw->interpolation_mode.mode[i] = mode; } if (unlikely(INTEL_DEBUG & DEBUG_VUE)) { fprintf(stderr, "VUE map:\n"); for (int i = 0; i < vue_map->num_slots; i++) { int varying = vue_map->slot_to_varying[i]; if (varying == -1) { fprintf(stderr, "%d: --\n", i); continue; } fprintf(stderr, "%d: %d %s ofs %d\n", i, varying, get_qual_name(brw->interpolation_mode.mode[i]), brw_vue_slot_to_offset(i)); } } }