Jump to content
  • Advertisement
Sign in to follow this  
StanLee

OpenGL Atomic Add for Float Type

This topic is 783 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

 

I was searching the specifications for a possibility to do atomic addition for buffer variables of type float. But unfortunately I have found only atomic operations on integer types: https://www.opengl.org/wiki/Atomic_Variable_Operations

 

This is a big problem for me now. My fragment shader looks like this:

struct ItemType{
	float R, G, B, A;
};

layout (std430, binding = 0) buffer BufferObject {
	ItemType items[];
};

uniform int ID;

//... Other uniforms and variables

void main(void){
	// ... computations. Result: vec4 CompResult
	
	atomicAdd(items[ID].R, CompResult.r); //not working
	atomicAdd(items[ID].G, CompResult.g); //not working
	atomicAdd(items[ID].B, CompResult.b); //not working
}

This fragment shader is executed n-times with the same ID for one rendering call. (n is the number of rendered fragments) Obviously I have to perform the addition atomically but somehow there is no function which can do this for float types.

 

Has anyone else dealt with this problem before? Is there a possibility to circumvent the problem? I already had the idea to built my own per-pixel mutex just as it has been done in the Red Book, but I fear that this will destroy my performance completely.

 

Best Regards,

Stan 

Edited by StanLee

Share this post


Link to post
Share on other sites
Advertisement

Hmmm, so only NV has atomics on floats. Maybe I'll stick to only NV support for now.

 

By using integeres, do you mean converting them to integer values before saving them in the buffer? 

Share this post


Link to post
Share on other sites

Assuming you know that your added numbers sum will never get higher than 100:

 

int fromFloat = int (floatColor * (float(0x7fffffff) / 100.0f));

float backFromInt = float(fromFloat) * (100.0f / float(0x7fffffff));

 

I may have introduced a bug, but you get the point: Make a large integer from a small floating point number to get as much precission as possible.

Share this post


Link to post
Share on other sites

I understand. =) I will stick to the NV extension for now, but try this out later. Thanks! =)

Share this post


Link to post
Share on other sites
It's always possible to access any data in an atomic manner using a compareswap in a loop.


Something like
Do {floatval = old value + ... } while(compareswap(oldvalue, floatvalue));

It will loop as long as the atomic data is different from old value. If the atomic is equal to old value it will atomically swap it with floatvalue and exit the loop.

I'm not sure this pattern is efficient. On the other hand from my experience amd atomic are way faster than Nvidia's one and that's maybe why they provide float atomic to make you avoid resorting to slower pattern.

Share this post


Link to post
Share on other sites

Often it's best to avoid atomics, e.g. to sum up all numbers from an array, a prefix scan method should be much faster.

OpenCL sample:

 

accSum[lID] = lacc; // lID = thread index, each thread puts its value to the array, but we want to compute the sum of all values

    barrier (CLK_LOCAL_MEM_FENCE);

    uint step = 0;
    while (true)
    {
        uint add = (1<<step);
        uint index = lID + add; // neighbour array index
        if ((lID & ((~1)<<step)) == lID) accSum[lID] += accSum[index]; // add neighbour value to own value
        barrier (CLK_LOCAL_MEM_FENCE);
        if (add == (wgS>>1)) break; // wgS = total number of threads btw. array entries
        step++;
    }
 
// accSum[0] contains sum now

 

how this works illustrated is:

 

11111111
2 2 2 2
4   4
8

 

So for an array of 256 entries you need only 8 loop iterations without any atomic conflicts.

 

To make this fast you need compute, where all threads have acces to the array stored in LDS memory.

 

If that's new to you look it up! ;)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!