This fixes glxgears rendering, which had surprisingly been broken since
late October! Specifically, commit
91d61fbf7cb61a44adcaae51ee08ad0dd6b.
glxgears uses glShadeModel(GL_FLAT) when drawing the main portion of the
gears, then uses glShadeModel(GL_SMOOTH) for drawing the Gouraud-shaded
inner portion of the gears. This results in the same fragment program
having two different state-dependent interpolation maps: one where
gl_Color is flat, and another where it's smooth.
The problem is that there's only one gen4_fragment_program, so it can't
store both. Each FS compile would trash the last one. But, the FS
compiles are cached, so the first one would store FLAT, and the second
would see a matching program in the cache and never bother to compile
one with SMOOTH. (Clearing the program cache on every draw made it
render correctly.)
Instead, move it to brw_wm_prog_data, where we can keep a copy for
every specialization of the program. The only downside is bloating
the structure a bit, but we can tighten that up a bit if we need to.
This also lets us kill gen4_fragment_program entirely!
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Timothy Arceri <timothy.arceri@collabora.com>
_NEW_POLYGON |
_NEW_TRANSFORM,
BRW_NEW_BLORP |
- BRW_NEW_FRAGMENT_PROGRAM |
+ BRW_NEW_FS_PROG_DATA |
BRW_NEW_REDUCED_PRIMITIVE |
BRW_NEW_VUE_MAP_GEOM_OUT))
return;
/* Populate the key:
*/
- const struct gl_program *fprog = brw->fragment_program;
- if (fprog) {
- assert(brw->gen < 6);
- struct gen4_fragment_program *p = (struct gen4_fragment_program *) fprog;
-
- /* BRW_NEW_FRAGMENT_PROGRAM */
- key.contains_flat_varying = p->contains_flat_varying;
- key.contains_noperspective_varying = p->contains_noperspective_varying;
- key.interp_mode = p->interp_mode;
+ /* 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;
+ key.interp_mode = wm_prog_data->interp_mode;
}
/* BRW_NEW_REDUCED_PRIMITIVE */
GLbitfield64 attrs;
bool contains_flat_varying;
bool contains_noperspective_varying;
- unsigned char *interp_mode;
+ const unsigned char *interp_mode;
GLuint primitive:4;
GLuint nr_userclip:4;
GLuint pv_first:1;
bool has_side_effects;
bool pulls_bary;
+ bool contains_flat_varying;
+ bool contains_noperspective_varying;
+
/**
* Mask of which interpolation modes are required by the fragment shader.
* Used in hardware setup on gen6+.
*/
uint32_t flat_inputs;
+ /* Mapping of VUE slots to interpolation modes.
+ * Used by the Gen4-5 clip/sf/wm stages.
+ */
+ unsigned char interp_mode[65]; /* BRW_VARYING_SLOT_COUNT */
+
/**
* Map from gl_varying_slot to the position within the FS setup data
* payload where the varying's attribute vertex deltas should be delivered.
/* brw_interpolation_map.c */
void brw_setup_vue_interpolation(struct brw_vue_map *vue_map,
struct nir_shader *nir,
- struct gl_program *prog,
+ struct brw_wm_prog_data *prog_data,
const struct gen_device_info *devinfo);
enum shader_dispatch_mode {
};
-struct gen4_fragment_program {
- struct brw_program base;
-
- bool contains_flat_varying;
- bool contains_noperspective_varying;
-
- /*
- * Mapping of varying slots to interpolation modes.
- * Used Gen4/5 by the clip|sf|wm stages.
- */
- unsigned char interp_mode[BRW_VARYING_SLOT_COUNT];
-};
-
-
/**
* Bitmask indicating which fragment shader inputs represent varyings (and
* hence have to be delivered to the fragment shader by the SF/SBE stage).
unsigned *final_assembly_size,
char **error_str)
{
+ const struct gen_device_info *devinfo = compiler->devinfo;
+
nir_shader *shader = nir_shader_clone(mem_ctx, src_shader);
shader = brw_nir_apply_sampler_key(shader, compiler, &key->tex, true);
- brw_nir_lower_fs_inputs(shader, vue_map, prog, compiler->devinfo, key);
+ brw_nir_lower_fs_inputs(shader, devinfo, key);
brw_nir_lower_fs_outputs(shader);
+
+ if (devinfo->gen < 6) {
+ brw_setup_vue_interpolation(vue_map, shader, prog_data, devinfo);
+ }
+
if (!key->multisample_fbo)
NIR_PASS_V(shader, demote_sample_qualifiers);
NIR_PASS_V(shader, move_interpolation_to_top);
}
static void
-gen4_frag_prog_set_interp_modes(struct gen4_fragment_program *prog,
+gen4_frag_prog_set_interp_modes(struct brw_wm_prog_data *prog_data,
struct brw_vue_map *vue_map,
unsigned location, unsigned slot_count,
enum glsl_interp_mode interp)
{
for (unsigned k = 0; k < slot_count; k++) {
unsigned slot = vue_map->varying_to_slot[location + k];
- if (slot != -1 && prog->interp_mode[slot] == INTERP_MODE_NONE) {
- prog->interp_mode[slot] = interp;
+ if (slot != -1 && prog_data->interp_mode[slot] == INTERP_MODE_NONE) {
+ prog_data->interp_mode[slot] = interp;
- if (prog->interp_mode[slot] == INTERP_MODE_FLAT) {
- prog->contains_flat_varying = true;
- } else if (prog->interp_mode[slot] == INTERP_MODE_NOPERSPECTIVE) {
- prog->contains_noperspective_varying = true;
+ if (prog_data->interp_mode[slot] == INTERP_MODE_FLAT) {
+ prog_data->contains_flat_varying = true;
+ } else if (prog_data->interp_mode[slot] == INTERP_MODE_NOPERSPECTIVE) {
+ prog_data->contains_noperspective_varying = true;
}
}
}
/* Set up interpolation modes for every element in the VUE */
void
brw_setup_vue_interpolation(struct brw_vue_map *vue_map, nir_shader *nir,
- struct gl_program *prog,
+ struct brw_wm_prog_data *prog_data,
const struct gen_device_info *devinfo)
{
- struct gen4_fragment_program *fprog = (struct gen4_fragment_program *) prog;
-
/* Initialise interp_mode. INTERP_MODE_NONE == 0 */
- memset(fprog->interp_mode, 0, sizeof(fprog->interp_mode));
+ memset(prog_data->interp_mode, 0, sizeof(prog_data->interp_mode));
if (!vue_map)
return;
*/
unsigned pos_slot = vue_map->varying_to_slot[VARYING_SLOT_POS];
if (pos_slot != -1) {;
- fprog->interp_mode[pos_slot] = INTERP_MODE_NOPERSPECTIVE;
- fprog->contains_noperspective_varying = true;
+ prog_data->interp_mode[pos_slot] = INTERP_MODE_NOPERSPECTIVE;
+ prog_data->contains_noperspective_varying = true;
}
foreach_list_typed(nir_variable, var, node, &nir->inputs) {
unsigned location = var->data.location;
unsigned slot_count = glsl_count_attribute_slots(var->type, false);
- gen4_frag_prog_set_interp_modes(fprog, vue_map, location, slot_count,
+ gen4_frag_prog_set_interp_modes(prog_data, vue_map, location, slot_count,
var->data.interpolation);
if (location == VARYING_SLOT_COL0 || location == VARYING_SLOT_COL1) {
location = location + VARYING_SLOT_BFC0 - VARYING_SLOT_COL0;
- gen4_frag_prog_set_interp_modes(fprog, vue_map, location,
+ gen4_frag_prog_set_interp_modes(prog_data, vue_map, location,
slot_count, var->data.interpolation);
}
}
fprintf(stderr, "%d: %d %s ofs %d\n",
i, varying,
- get_qual_name(fprog->interp_mode[i]),
+ get_qual_name(prog_data->interp_mode[i]),
brw_vue_slot_to_offset(i));
}
}
}
void
-brw_nir_lower_fs_inputs(nir_shader *nir, struct brw_vue_map *vue_map,
- struct gl_program *prog,
+brw_nir_lower_fs_inputs(nir_shader *nir,
const struct gen_device_info *devinfo,
const struct brw_wm_prog_key *key)
{
}
}
- if (devinfo->gen < 6) {
- assert(prog); /* prog will be NULL when called from Vulkan */
- brw_setup_vue_interpolation(vue_map, nir, prog, devinfo);
- }
-
nir_lower_io_options lower_io_options = 0;
if (key->persample_interp)
lower_io_options |= nir_lower_io_force_sample_interpolation;
void brw_nir_lower_vue_inputs(nir_shader *nir, bool is_scalar,
const struct brw_vue_map *vue_map);
void brw_nir_lower_tes_inputs(nir_shader *nir, const struct brw_vue_map *vue);
-void brw_nir_lower_fs_inputs(nir_shader *nir, struct brw_vue_map *vue_map,
- struct gl_program *prog,
+void brw_nir_lower_fs_inputs(nir_shader *nir,
const struct gen_device_info *devinfo,
const struct brw_wm_prog_key *key);
void brw_nir_lower_vue_outputs(nir_shader *nir, bool is_scalar);
}
case GL_FRAGMENT_PROGRAM_ARB: {
- struct brw_program *prog;
- if (brw->gen < 6) {
- struct gen4_fragment_program *g4_prog =
- rzalloc(NULL, struct gen4_fragment_program);
- prog = &g4_prog->base;
- } else {
- prog = rzalloc(NULL, struct brw_program);
- }
+ struct brw_program *prog = rzalloc(NULL, struct brw_program);
if (prog) {
prog->id = get_new_program_id(brw->screen);
_NEW_PROGRAM |
_NEW_TRANSFORM,
BRW_NEW_BLORP |
- BRW_NEW_FRAGMENT_PROGRAM |
+ BRW_NEW_FS_PROG_DATA |
BRW_NEW_REDUCED_PRIMITIVE |
BRW_NEW_VUE_MAP_GEOM_OUT))
return;
if ((ctx->Point.SpriteOrigin == GL_LOWER_LEFT) != render_to_fbo)
key.sprite_origin_lower_left = true;
- const struct gl_program *fprog = brw->fragment_program;
- if (fprog) {
- assert(brw->gen < 6);
- struct gen4_fragment_program *p = (struct gen4_fragment_program *) fprog;
-
- /* BRW_NEW_FRAGMENT_PROGRAM */
- key.contains_flat_varying = p->contains_flat_varying;
- key.interp_mode = p->interp_mode;
+ /* 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.interp_mode = wm_prog_data->interp_mode;
}
/* _NEW_LIGHT | _NEW_PROGRAM */
struct brw_sf_prog_key {
GLbitfield64 attrs;
bool contains_flat_varying;
- unsigned char *interp_mode;
+ const unsigned char *interp_mode;
uint8_t point_sprite_coord_replace;
GLuint primitive:2;
GLuint do_twoside_color:1;