Bug 10783

Summary: Missing ArcSine and ArcCosine capability in GLSL
Product: Mesa Reporter: James Burns <James.Burns>
Component: Mesa coreAssignee: mesa-dev
Status: RESOLVED FIXED QA Contact:
Severity: critical    
Priority: high    
Version: 6.5   
Hardware: All   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:

Description James Burns 2007-04-27 13:26:09 UTC
This bug report is based on mesa_6_5_3_rc4.  Shaders containing calls to asin or acos cause a crash of Mesa.  (At least when using OSMesa.)  The following test is dumped by MESA on this event.

Loading shader: /home/burnsje/MmwSupport/csg141/shaders/ir_water.frag
rm: cannot remove `movie/*.jpeg': No such file or directory
Mesa 6.5.3 implementation error: undefined __asm function float_arcsine

Please report at bugzilla.freedesktop.org
csfbatch: shader/slang/slang_codegen.c:1273: _slang_gen_asm: Assertion `info' failed.
Aborted
Comment 1 Brian Paul 2007-04-27 13:56:10 UTC
Hmmm, I don't think I have time to implement acos/asin() today, but I can at least fix the crash.
I'll mark it as a known issue and fix it properly for Mesa 7.0.  How's that?
Comment 2 Ian Romanick 2007-04-30 16:05:09 UTC
I did a bit of research on the net, and I think asin, acos, and atan can be approcimated pretty easilly.  This should make the GLSL to GL_ARB_{fragment,vertex}_program conversion pretty simple:

asin(x) = pi/2 - sqrt(1 - x)(a0 + a1*x + a2*x^2 + a3*x^3)
acos(x) =        sqrt(1 - x)(a0 + a1*x + a2*x^2 + a3*x^3)

where

   a0 = 1.5707288
   a1 = -0.2121144
   a2 = 0.0742610
   a3 = -0.0187293

atan(y, x) = s * ( pi/4 - (pi / 4) * ((x - |y|) / (x + |y|)))    for x >= 0
             s * (3pi/4 - (pi / 4) * ((x + |y|) / (|y| - x)))    for x < 0

where
   s = -1  for y < 0
   s =  1  otherwise

References:

http://mathforum.org/library/drmath/view/54137.html
http://dspguru.com/comp.dsp/tricks/alg/fxdatan2.htm
http://en.wikipedia.org/wiki/Arcsin#Recommended_method_of_calculation
Comment 3 James Burns 2007-04-30 19:11:45 UTC
(In reply to comment #1)
> Hmmm, I don't think I have time to implement acos/asin() today, but I can at
> least fix the crash.
> I'll mark it as a known issue and fix it properly for Mesa 7.0.  How's that?
> 
I've fixed this in my own version of Mesa, so I will be fine waiting for Mesa 7.0 on this.  I surely would like to see this fixed in the next release.  
Comment 4 James Burns 2007-04-30 19:16:26 UTC
(In reply to comment #2)
> I did a bit of research on the net, and I think asin, acos, and atan can be
> approcimated pretty easilly.  This should make the GLSL to
> GL_ARB_{fragment,vertex}_program conversion pretty simple:
> 
> asin(x) = pi/2 - sqrt(1 - x)(a0 + a1*x + a2*x^2 + a3*x^3)
> acos(x) =        sqrt(1 - x)(a0 + a1*x + a2*x^2 + a3*x^3)
> 
> where
> 
>    a0 = 1.5707288
>    a1 = -0.2121144
>    a2 = 0.0742610
>    a3 = -0.0187293
> 
> atan(y, x) = s * ( pi/4 - (pi / 4) * ((x - |y|) / (x + |y|)))    for x >= 0
>              s * (3pi/4 - (pi / 4) * ((x + |y|) / (|y| - x)))    for x < 0
> 
> where
>    s = -1  for y < 0
>    s =  1  otherwise
> 
> References:
> 
> http://mathforum.org/library/drmath/view/54137.html
> http://dspguru.com/comp.dsp/tricks/alg/fxdatan2.htm
> http://en.wikipedia.org/wiki/Arcsin#Recommended_method_of_calculation
> 


In this case, I would defer to whatever the community wants to do here.  (Assuming the math here is correct, and I have not checked it.)  It would appear that this solution is faster than a typical asin/acos implemented by most compilers.   We do similiar sorts of approximations here for our realtime applications, but we often use 6th order expressions.  

It does seem that this approach is out of sync with the remainder of the MESA GLSL approach, using the _mesa_XXX functions which call the standard C math functions.  In the patch I am using here, I stuck with the current approach for the sake of consistency.
Comment 5 Brian Paul 2007-05-01 06:54:05 UTC
If I were to follow the pattern of the other trigonometry functions in Mesa's GLSL, I'd add OPCODE_ACOS/ASIN instructions and simply call acos/asin() in the program interpreter.

I doubt, however, that any target GPUs will have native ACOS/ASIN instructions so those Mesa instructions would have to be expanded into code to compute an approximation.  That'll probably be needed for sin/cos as-is.

I believe Ian's code is meant to go into the GLSL acos/asin functions so that it gets compiled into Mesa GPU instructions.  I'll give that a try.
Comment 6 James Burns 2007-05-01 07:02:09 UTC
(In reply to comment #5)
> If I were to follow the pattern of the other trigonometry functions in Mesa's
> GLSL, I'd add OPCODE_ACOS/ASIN instructions and simply call acos/asin() in the
> program interpreter.
> 
> I doubt, however, that any target GPUs will have native ACOS/ASIN instructions
> so those Mesa instructions would have to be expanded into code to compute an
> approximation.  That'll probably be needed for sin/cos as-is.
> 
> I believe Ian's code is meant to go into the GLSL acos/asin functions so that
> it gets compiled into Mesa GPU instructions.  I'll give that a try.
> 

That's probably a good point.  I'm a rare bird living in the land of OSMesa.
Comment 7 Brian Paul 2007-05-01 13:05:52 UTC
Ian, is a0 supposed to be PI/2?  1.5707288 is pretty close, but not quite.

In any case, I've commited asin() based on your series.  acos() and atan() are in terms of acos().

Comment 8 James Burns 2007-05-01 15:29:17 UTC
(In reply to comment #7)
> Ian, is a0 supposed to be PI/2?  1.5707288 is pretty close, but not quite.
> 
> In any case, I've commited asin() based on your series.  acos() and atan() are
> in terms of acos().
> 

Fix checked out ok in my test cases and main application.

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.