• Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

# HLSL shaders with XNA - convert float to double

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

8 replies to this topic

### #1nagromo  Members   -  Reputation: 676

Like
0Likes
Like

Posted 11 August 2012 - 08:36 AM

I'm writing a fractal explorer using XNA and HLSL (w/ Pixel Shader 3.0).

It's working great using 32-bit floats, but I'm running into resolution issues, so I want to move to 64-bit doubles.

My card (Radeon 4850) does support 64-bit doubles, and I can define doubles that are initialized to a constant value and do math using them. The problem comes when I want to mix floats with doubles.

The inputs to my shader are the texture coordinates in float2 and some float and float2 constants from the application. These inputs are combined to produce the coordinate in fractal space; I need to do this calculation in double precision.

Here's the original version (single-precision) that's part of the working shader:
[source lang="plain"]float2 c = (texCoord - 0.5) * Zoom * float2(1, Aspect) - pan;[/source]
texCoord and pan are float2, and Zoom and Aspect are float.

I'm having trouble converting this over to use double-precision; even these basic tests to draw the fractal region from (0,0) to (1,1) don't work:

[source lang="plain"]double2 c = texCoord;double2 c = (double2)texCoord;double2 c = double2((double)texCoord.x,(double)texCoord.y);[/source]
All three of these lines give the same error: "internal error: 64-bit arg ??? component 1 not aligned" where ??? is any number from 138 to 922.

Any advice on how to resolve this? Alternatively, if the vertex shader inputs could be double and the values from the application could also be double, that would remove the need for conversion, but I don't know of any way to force the input to my vertex shader to be passed as a double. (If I re-define texCoord to double, I get the same error with different numbers.)

### #2AmzBee  Members   -  Reputation: 416

Like
0Likes
Like

Posted 11 August 2012 - 09:29 AM

[source lang="cpp"]float2 a = float2(0.1f, 0.1f);double2 b = double2(a);[/source]

also have a look at what MSDN says about double type's: http://msdn.microsoft.com/en-us/library/windows/desktop/bb509646(v=vs.85).aspx

Aimee
Aimee Bailey

http://xpod-games.com
@XpodGames

### #3Nik02  Members   -  Reputation: 1992

Like
2Likes
Like

Posted 11 August 2012 - 10:37 AM

Doubles are only supported in shader model 5 and up. In lower shader profiles, they are handled as floats.

Edited by Nik02, 11 August 2012 - 10:41 AM.

Niko Suni
Software developer

### #4nagromo  Members   -  Reputation: 676

Like
0Likes
Like

Posted 11 August 2012 - 08:57 PM

AmzBee, that worked fine too When I added this code:
[source lang="java"]float2 a = float2(0.1f, 0.1f);double2 b = double2(a);c = c + float2(b);[/source]
I could see that my coordinates were off by (0.1f, 0.1f). However, if I instead do double2 b = double2(texCoord), I get the same error.

It seems that even though the doubles appear to work, it is probably converting to float under the hood, and as Nik02 says, doubles are not supported by shader model 3.0.

It looks like XNA is built on DX9, so to get a higher shader model (and double precision), I'd need to move away from XNA.

### #5Nik02  Members   -  Reputation: 1992

Like
1Likes
Like

Posted 11 August 2012 - 09:11 PM

Even in SM5, doubles have some limitations that are mainly due to the fact that the common hardware doesn't actually have double-size registers.

-On GPUs that do support doubles (which is optional - but common - in D3D11 class hardware), you have to pack and unpack doubles in two memory slots manually in order to move them in and out of the shaders, because neither the input assembler nor the rasterizer supports doubles natively.
-Doubles are at least twice as slow as floats, because the hardware has to jump extra hoops to both load+store doubles and to actually compute something with them.
-While the basic math instructions are implemented in full double precision, I believe that there are some instructions such as rsq (and other transcendent math) that aren't. This may have changed since I last checked, though.
Niko Suni
Software developer

### #6nagromo  Members   -  Reputation: 676

Like
0Likes
Like

Posted 11 August 2012 - 09:34 PM

Thanks. I'd already run across most of these issues as I've researched this (without realizing that it was SM5 specific).

The math operations aren't an issue; I don't even need double-precision division, just scalar and vector multiplication, addition, and subtraction.

Is SM5 capable of casting from float to double? I.E. if I re-wrote my application code using SlimDX (not that there is much app code), would I have trouble with my pixel shader taking in single-precision texture coordinates and casting to a double (or mutiplying the float texture coordinates by a double scalar value and getting double results)?

This is just a side project I'm doing for fun; most of my coding these days is embedded C on various microcontrollers, so I'm quite out of the loop on modern graphics.

### #7nagromo  Members   -  Reputation: 676

Like
0Likes
Like

Posted 11 August 2012 - 09:49 PM

Also, it looks like in order to save partial results to a texture for smooth performance, I'd have to have a texture as R32G32_UInt and pack/unpack every pixel as it's saved/loaded by the shader. Is there a good way to find out what texture formats are supported by a card without writing all the code and testing it?

### #8Nik02  Members   -  Reputation: 1992

Like
2Likes
Like

Posted 11 August 2012 - 10:47 PM

Double division is an example of a transcendental instruction that is not supported in SM5. I believe it is planned to be supported in later shader models (not sure about 5.1 profiles).

It is valid to cast doubles to floats and vice versa in the shaders. The shader compiler will emit single ftod or dtof intermediate instructions when casting.

You can't directly write doubles to render targets or writable buffers - you need to pack the doubles to two ints before you output them, if you want to maintain full precision in the stored results. The precision is automatically maintained inside the shaders, though.

...

SM5-level hardware has a large fixed set of texture formats and a smaller list of optional ones. The format you mention is mandatory, so you can assume that the hardware supports it if it supports SM5.
Niko Suni
Software developer

### #9MJP  Moderators   -  Reputation: 5444

Like
0Likes
Like

Posted 11 August 2012 - 11:08 PM

If you have an SM5.0 GPU that supports feature level 11, then you can use this guide to see which DXGI formats are available for various usages.

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS