request HLSL support for sqrt() for integers

Started by
29 comments, last by Matias Goldberg 8 years, 2 months ago

For two different machines to produce the same output (GPU speaking), they must follow these rules:

Therein lies the difference between the two arguments we're making.

Is floating point arithmetic deterministic? Yes.

Can I run the same code across multiple vendors' hardware and expect identical results? No, that's not what I said or claimed.

The fact that the same code can produce different results on different hardware doesn't make "float operations non-deterministic". Saying things like "non-deterministic across machines" is a not really a very good use of terms. The results are deterministic on machine A and deterministic on machine B, but the fact that you can't predict the output on Machine C doesn't mean "float operations are non-deterministic".

If floating point operations were non-deterministic they'd be great source of random numbers!

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

Advertisement
Your function is going to give incorrect results every time the the length of the vector isn't a whole integer, so why not do it in floating point where you'll get a far closer to correct result?

float operations have a margin of error too, when using uints you just have to change your definition of what 0 to 1 means, for example 0 to 1 in my world physics engine is 0 to 2^9 uint.

Your function is going to give incorrect results every time the the length of the vector isn't a whole integer, so why not do it in floating point where you'll get a far closer to correct result?

The same thing happens with float operations, when using uints you just have to change your definition of what 0 to 1 means, for example 0 to 1 in my world physics engine is 0 to 2^9 uint.

If large errors are less important to you than predictable results across different hardware then by all means implement your length functions however you want, but don't expect that they'll get added to HLSL.

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

Can I ran the same code across multiple vendors' hardware and expect identical results? No, that's not what I said or claimed.

It's what the topic is about though...

The fact that the same code can produce different results on different hardware doesn't make "float operations non-deterministic".

It's pretty common to call game code that produces different results on different machines "non-deterministic". It's also common for games requiring determinism to jump through a lot of hoops when it comes to floating point precision and machine implementation differences, such as using fixed-point and implementing all your math (including sqrt/length calculations) using integer instructions...

If large errors are less important to you than predictable results across different hardware

wait what?

uint operations are more accurate than float operations, as I said you can change the definition of 0 to 1 at your own taste, so I can make (0 to 1) = (0 to 2^25) and this will make it 2 times more accurate than (0 to 1) float

If large errors are less important to you than predictable results across different hardware

wait what?

uint operations are more accurate than float operations, as I said you can change the definition of 0 to 1 at your own taste, so I can make (0 to 1) = (0 to 2^25) and this will make it 2 times more accurate than (0 to 1) float

Let me try and understand your system then:

You said you mapped "0-1" in your world to 0 - 2^9 uint.

So if you want the length of the floating point vector float2(1 / 512, 1 / 512) you would instead call your integer length2D function with uint2(1,1)?

The truly accurate length of float2(1 / 512, 1 / 512) is 0.002762136.

Your length 2D function when called with uint2(1,1) will return 1. 1 in your "0 - 2^9" = "0 - 1" system is equivalent to 0.001953125.

Your function's answer error is 30%. What am I missing?

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

wait what?

uint operations are more accurate than float operations, as I said you can change the definition of 0 to 1 at your own taste, so I can make (0 to 1) = (0 to 2^25) and this will make it 2 times more accurate than (0 to 1) float

As I already pointed out, since you're calculating (x *x) + (y * y) you can't guarantee avoiding overflow unless you ensure X and Y don't exceed 2^15.

(2^25 * 2^25) + (2^25 + 2^25) = 2 ^ 51.

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

For two different machines to produce the same output (GPU speaking), they must follow these rules:

Therein lies the difference between the two arguments we're making.

Is floating point arithmetic deterministic? Yes.

Can I run the same code across multiple vendors' hardware and expect identical results? No, that's not what I said or claimed.

The fact that the same code can produce different results on different hardware doesn't make "float operations non-deterministic". Saying things like "non-deterministic across machines" is a not really a very good use of terms. The results are deterministic on machine A and deterministic on machine B, but the fact that you can't predict the output on Machine C doesn't mean "float operations are non-deterministic".

If floating point operations were non-deterministic they'd be great source of random numbers!

You are, strictly speaking, correct. But considering that something as simple as a driver update or a DirectX runtime update can cause your shaders to return a different output, makes this kind of determinism useless to almost all practical use cases.

You are, strictly speaking, correct. But considering that something as simple as a driver update or a DirectX runtime update can cause your shaders to return a different output, makes this kind of determinism useless to almost all practical use cases.

Being able to normalize/transform/manipulate vectors and have the result be the same from one frame to the next is critically important to 3D graphics unless you're content for the entire screen to jitter and wobble uncontrollably.

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

eozTV5R.png

As I already pointed out, since you're calculating (x *x) + (y * y) you can't guarantee avoiding overflow unless you ensure X and Y don't exceed 2^15.

HLSL trigonometric functions have some magic going on behind it, that's why I want them to do a length() for uints, they could make something that will let the function calculate all vectors that have a length less than 2^32

This topic is closed to new replies.

Advertisement