Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Copmute Shader fmod with doubles

Discussion in 'Shaders' started by okanskose, Jan 30, 2015.

  1. okanskose

    okanskose

    Joined:
    Jan 30, 2015
    Posts:
    3
    Hi Unity community,

    I have to make some calculations with double precision values in a compute shader. But I am stuck at the point that when I try to use functions like fmod(x, y) or abs(x) and so on, where the parameters are double precision values, i get an error-massage that tells me: "[..] conversion from larger type to smaller, possible loss of data [..]".

    I really need this precision though and a loss of data is not good.
    Is there any way to use functions with double precision like fmod(double x, double y) instead of fmod(float x, flaot y)? (As I know, this is supported in glsl.)

    EDIT: I am running the Unity 3D version 4.6.0 in DirectX 11.

    Thanks in advance
    Greetings, okko
     
    Last edited: Jan 30, 2015
  2. TechnoCraft

    TechnoCraft

    Joined:
    Apr 6, 2012
    Posts:
    28
    As far as Unity Free Edition goes: The big showstopper with shaders and single or double precision is performance cost in decoding the values inside a shader. I guess you could use it within vertex shader. If you do not need realtime dynamic shader (on every Update) then you could use shaders even in double precision. See this topic.
     
  3. okanskose

    okanskose

    Joined:
    Jan 30, 2015
    Posts:
    3
    Thanks for reply. I am familiar with performance lost while using double precision on GPU.
    I have to use double precision in computeshader which runs Screen.width * Screen.height threads (or fragment shader, but compute shader provides more possibilities for my use case). So there is no way run my code in a vertex shader.
    Is there no way to use the functions with double precision values as parameter and return value?

    Thanks in advance and greetings, okko
     
  4. TechnoCraft

    TechnoCraft

    Joined:
    Apr 6, 2012
    Posts:
    28
    Compute shaders run on different part of GPU because they do computation - not rendering. If you need double precision you need at least DX11 GPU. Compute Shader Overview

    You can transfer double precision values to a Compute Shader via SetBuffer, GetBuffer. As far as threads go, the limitation is 1024 in Unity Free. See what Aras had to say (a while back) regarding this topic.

    Shader Properites
    Use a script to transfer floating point data via texture to a HLSL Shader. You can only use this option to get (double precision) to vertex or fragment function for rendering. You need to write HLSL color2double decoder. You must use at least two pixels for one value. Each pixel represents 32bits. Enough for 64bit double precision format. You can use my project I referenced above to get you started. See Color2Float (single precision float) in shCustomBumpedSpecular.shader.

    Decoding could be accelerated if you used more pixels. Say 16 pixels for one value. Each pixel representing 4 bits.
     
  5. okanskose

    okanskose

    Joined:
    Jan 30, 2015
    Posts:
    3
    Hi TechnoCraft,

    I already stumbled over those methods, but I can't see a solution for my problem by using such an approach.
    I'm using compute shader and running Screen.width * Screen.height threads, also in DirectX11.

    My problem appears if I try to do something like this (of course not in C#, but in a compute shader. Just an example..):
    Code (CSharp):
    1. double DoSomeFancyCalcsWithDoubles(double a, double b)
    2. {
    3.     double c = a + b;
    4.     return sin(a) * abs(c) + modf(a, b);
    5. }
    The addition in line 3 is no problem, but I get an issue if I am trying to use functions like in line 4, because all the built in functions (so far I figured out) are using single precision values and this is where data loss occurs.

    Currently I can't see a solution by using two floats for a double precision representation while working with functions like sin, cos, modf... Did I misunderstand something or do you have any idea or reference to solve this problem?

    Thanks for reply and in advance,
    greetings, okko
     
  6. TechnoCraft

    TechnoCraft

    Joined:
    Apr 6, 2012
    Posts:
    28
    What GPU (graphic card) are you using?

    Since compute shader is executed on the GPU, the precision of operations is based on GPU compute capabilities (hardware capabilites).

    Direct3D 10.x Hardware
    No double-precision values are available.

    Direct3D 11.x Hardware
    Double-precision support might be available. For information about how to determine whether double-precision is available, see D3D11_FEATURE_DOUBLES.

    To determine your NVidia GPU compute capability see a list of Cuda cards. You need at least 1.3 compute capability to do double-precision. See "Version features and specifications" at Wiki.

    If you own AMD (ATI) GPU see OpenCL cards and their compute capability version.While OpenCL 1.0 includes double-precision by default. Not all cards do double-precision (search for "Double precision" in supplied link). For DirectCompute at least AMD Radeon HD 5000 or newer is required.

    Please read a more detailed explanation in referenced links below.

    References
    Microsoft DirectCompute (Compute Shader)
    GPU Computing Wiki
    AMD System requirements