[Mesa-dev] [PATCH 2/2] i965/gs: Fix gl_PrimitiveIDIn when using SW primitive restart.
Eric Anholt
eric at anholt.net
Fri Nov 22 18:12:41 PST 2013
Paul Berry <stereotype441 at 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 <eric at anholt.net>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 835 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20131122/4561b62f/attachment-0001.pgp>
More information about the mesa-dev
mailing list