Paul Berry <stereotype...@gmail.com> writes: > Ivy Bridge hardware doesn't support primitve restart under all > circumstances--when it doesn't, we emulate it in software by splitting > up each logical draw operation into multiple 3DPRIMITIVE commands. > This causes the hardware's primitive ID counter to be reset to 0, > producing incorrect values for gl_PrimitiveIDIn. > > To work around that problem, we create a hidden uniform which is added > to the hardware's primitive ID counter at the top of the geometry > shader; the software primitive restart mechanism ensures that this > uniform always contains the number of primitives that were sent down > the pipeline by previous 3DPRIMITIVE commands within the same logical > draw operation. > > To reduce the performance impact of the workaround, we only compile it > into the shader when the hardware is Ivy Bridge and the shader > accesses gl_PrimitiveIDIn. To reduce unnecessary state updates, we > only flag _NEW_PROGRAM_CONSTANTS when when the workaround is compiled > in *and* software primitive restart is active. > > On Ivy Bridge, fixes all variants of > "glsl-1.50-geometry-primitive-id-restart" except the GL_LINE_LOOP > variants, which are broken due to an unrelated hardware limitation.
> diff --git a/src/mesa/drivers/dri/i965/brw_vec4_gs_visitor.cpp > b/src/mesa/drivers/dri/i965/brw_vec4_gs_visitor.cpp > index 96636e8..50feb89 100644 > --- a/src/mesa/drivers/dri/i965/brw_vec4_gs_visitor.cpp > +++ b/src/mesa/drivers/dri/i965/brw_vec4_gs_visitor.cpp > @@ -116,9 +116,39 @@ vec4_gs_visitor::setup_payload() > } > > > +/** > + * When using software primitive restart, Ivy Bridge resets the primitive ID > + * on each restart. Work around this by creating a hidden uniform whose > value > + * will be added to the incoming primitive ID. > + */ > +void > +vec4_gs_visitor::primitive_id_workaround() > +{ > + /* Set up the uniform */ > + this->uniform_vector_size[this->uniforms] = 1; > + dst_reg primitive_id_offset(UNIFORM, this->uniforms); Or src_reg primitive_id_offset(UNIFORM, this->uniforms, glsl_type::uint_type); That'll get you a reasonable swizzle that won't be pulling in other weird stuff when the uniform gets repacked. > + primitive_id_offset.type = BRW_REGISTER_TYPE_UD; > + for (int i = 0; i < 4; i++) { > + prog_data->param[this->uniforms * 4 + i] = > + reinterpret_cast<const float *>(&brw->prim_restart.sw_prim_counter); > + } In other cases param components beyond uniform_vector_size have had a pointer to a static zero, but I don't see a harm from doing this, either. (I would have used a normal C cast, but oh well) > + this->uniforms++; > + > + /* Emit code to add the uniform to primitive ID */ > + this->current_annotation = "primitive ID workaround"; > + dst_reg dst(ATTR, VARYING_SLOT_PRIMITIVE_ID); > + dst.type = BRW_REGISTER_TYPE_UD; > + emit(ADD(dst, src_reg(dst), src_reg(primitive_id_offset))); Note: This overwrites .yzw of g1, but it looks like those are delivered as zero, and I suspect they're not used afterwards. You may want to use dst(ATTR, VARYING_SLOT_PRIMITIVE_ID, glsl_type::uint_type, WRITEMASK_X) for sanity. > + this->current_annotation = NULL; > +} I don't think any of this feedback has an actual runtime effect. Either way, these two patches are: Reviewed-by: Eric Anholt <e...@anholt.net>
pgpoEszrmNyb8.pgp
Description: PGP signature
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev