why can't you check each element in g(float4 ) just like you are doing for the non-vectorized version?
You can use ternary/select operators instead of if-else. They don't cause a conditional clause switch.
I don't want to check each element, it request 4 operations !
I already use the ternary operator in the last line of 'fresnel_dielectric4'.
But I can't for 'g' ... because :
a) what give sqrt(X) if x < 0 ?
b) I also want to compute 'fresnel' in a SIMD way (Mainly for CPU)
OpenCL's sqrt should behave as c99's sqrt which says:
The sqrt functions compute the nonnegative square root of x. A domain error occurs if the argument is less than zero.
So if you cannot guarantee positive number in sqrt, i guess checking them individually is a must.
It is why I afraid of this :-P
Because it require to extract SIMD data into a float, then check it for x,y,z,w...
Finally using SIMD can be more expensive than not using it !
as of your code, maybe you could create two new variables float4 g_m_c = g-c; and float4 g_p_c = g+c; and set A = g_m_c/g_p_c; and B = mad(c,g_p_c,-1)/mad(c,g_m_c,1); (you forgot a '=' before 0.5f when declaring fresnel). I don't know if it would increase performance.
why you test the 'x' components 4 times? Shouldn't you test 'x', 'y', 'z' and 'w' components of g?
about cosi, do you really need a clamp?
about eta, what range of values should it take?
You're after the relational operators (see opencl spec 9.6.5), and the select operator. See below.
They work just like the trinary operator except that all paths are evaluated explicitly and you can use any width of input.
It shouldn't matter that any result is NaN along the way since it is just discarded. SIMD processors have to be used in this way for parallelism, so they should behave as you'd expec. i.e. the processor isn't going to crack a sad just because you gave it invalid data in one path.
The compiler might already be doing the select conversion for you, fwiw (well, if your code was correct, you only ever test for g.x and only ever use use freshnel.x in your result).
int4 cmp = isgreater(g, (float4)0); g = sqrt(g); float4 A = (g-c) / ( g + c); etc. float4 fresnel = 0.5f * A * A ...; and finally return select((float4)1, fresnel, cmp);
It is exactly what I was searching for !