Bug 27286

Summary: swrast/glsl: Mod function returns wrong value
Product: Mesa Reporter: Karthik Hariharakrishnan <karhar01>
Component: Drivers/DRI/swrastAssignee: mesa-dev
Status: RESOLVED MOVED QA Contact:
Severity: normal    
Priority: medium    
Version: 7.6   
Hardware: x86 (IA32)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:

Description Karthik Hariharakrishnan 2010-03-24 04:36:42 UTC
The following shader returns incorrect output. It looks like the GLSL Compiler doesnt implement mod correctly.

varying vec var1;
void main (void)
{
	gl_FragColor = vec4(mod(4.0, 2.0), 0.0, 0.0, 1.0);
}

It should be the same as,

varying vec var1;
void main (void)
{
        float var = 4.0 - (2.0 * (floor(4.0/2.0)) ); //According to spec
	gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
Comment 1 Karthik Hariharakrishnan 2010-03-24 04:41:43 UTC
Changing the version of Mesa, Hardware and OS info in bug
Comment 2 Brian Paul 2010-03-24 07:53:33 UTC
Can you provide a stand-alone test program that demonstrates this?

I tried it myself and I got the expected result: mod(4.0, 2.0) returns 0.0

Mesa's mod() function is implemented just as the spec says:

float mod(const float a, const float b)
{
    float oneOverB;
    __asm float_rcp oneOverB, b;
    __retVal = a - b * floor(a * oneOverB);
}
Comment 3 Karthik Hariharakrishnan 2010-03-24 08:13:10 UTC
(In reply to comment #2)
> Can you provide a stand-alone test program that demonstrates this?
> 
> I tried it myself and I got the expected result: mod(4.0, 2.0) returns 0.0
> 
> Mesa's mod() function is implemented just as the spec says:
> 
> float mod(const float a, const float b)
> {
>     float oneOverB;
>     __asm float_rcp oneOverB, b;
>     __retVal = a - b * floor(a * oneOverB);
> }
> 

Hi Brian,

  Could you try running the program against the library in lib/gallium.
export LD_LIBRARY_PATH=<blah>/Mesa-7.7/lib/gallium

The test passes when the following is set
export LD_LIBRARY_PATH=<blah>/Mesa-7.7/lib/

Thanks
Comment 4 Brian Paul 2010-03-24 08:37:42 UTC
OK, looks like I wasn't running w/ X86/SSE codegen enabled.  Looks like a bug in that code.  I'll try to take a look in a while.
Comment 5 Brian Paul 2010-03-25 17:23:47 UTC
Off-hand, I _think_ this is an issue with the SSE rcp (reciprocol) instruction.  Per the comment in the code, I think we need to produce a more accurate result:

static void
emit_rcp (
   struct x86_function *func,
   unsigned xmm_dst,
   unsigned xmm_src )
{
   /* On Intel CPUs at least, this is only accurate to 12 bits -- not
    * good enough.  Need to either emit a proper divide or use the
    * iterative technique described below in emit_rsqrt().
    */
   sse2_rcpps(
      func,
      make_xmm( xmm_dst ),
      make_xmm( xmm_src ) );
}

Maybe someone handier with SSE can try to fix this.  The emit_rsqrt() function further down uses a Newton-Raphson step to improve the results.  That could help.
Comment 6 GitLab Migration User 2019-09-18 18:44:14 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/mesa/mesa/issues/294.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.