Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 7 of 7

Thread: atomicCompSwap

  1. #1
    Junior Member Newbie
    Join Date
    Jan 2013
    Posts
    4

    atomicCompSwap

    Hi there,

    These days I played with OpenGL Compute Shaders and atomic operations. Unfortunately, the GLSL compiler keeps complaining about my use of the function atomicCompSwap.
    It claims "0(63) : error C1115: unable to find compatible overloaded function "atomicCompSwap(uint, uint, uint)"".

    Code :
    bool getMutex(inout uint mutex) {
    	if (atomicCompSwap(mutex, uint(0), threadId) == threadId) {
    		return true;
    	} else {
    		return false;
    	}
    }

    According to the specs, the argument list is perfectly valid. I also tried the signed version with the same results. May this be a driver bug?

    My system specs are:
    Windows 7 64bit
    Geforce GT 555M
    Driver version: 310.90

  2. #2
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    `atomicCompSwap` can only be used with uint variables declared as either `shared` or `buffer`. An `inout` function parameter is neither of those things; it's merely a function parameter.

    You must call it directly with a `shared` or `buffer` variable. Or an array entry indexed from one of those. You can't pass one through an intermediate function like that.

  3. #3
    Junior Member Newbie
    Join Date
    Jan 2013
    Posts
    4
    Quote Originally Posted by Alfonse Reinheart View Post
    `atomicCompSwap` can only be used with uint variables declared as either `shared` or `buffer`. An `inout` function parameter is neither of those things; it's merely a function parameter.

    You must call it directly with a `shared` or `buffer` variable. Or an array entry indexed from one of those. You can't pass one through an intermediate function like that.

    Ahhh thanks for the clarification!
    You were right, of course. Now I am using a macro instead of a function and everything works as expected. Tank you!

  4. #4
    Junior Member Newbie
    Join Date
    Jan 2013
    Posts
    4
    Hm I thought I did understand how atomicCompSwap works, but I was wrong.

    There are two points that I dont' get:

    1) The documentation says that the return value of atomicCompSwap is the new value if the comparison yields true and the old value if it yields false. But it seems that the return value is always the old value and the comparison just triggers if the memory is changed or not.

    2) Why do I need a barrier() call after an atomicCompSwap in order to see the new values in the same thread?

    The following code snipped demonstrates what I mean:

    Code :
    void main() {	
    	subDivisionQueueCounter = 17;
     
    	// Write to debug output
    	Debug.Data[0] = subDivisionQueueCounter;	
     
    	uint newVal = subDivisionQueueCounter + 2;		
    	uint veryNewVal = atomicCompSwap(subDivisionQueueCounter, 17, newVal);
    	//barrier();       // Weird I need to uncomment this!
     
    	// Write to debug output	
    	Debug.Data[1] = subDivisionQueueCounter;
    }

    In this example Debug is just a ShaderStorageBuffer that I use to get debug information out of a shader invocation and subDivisionQueueCounter is a shared uint variable. I start exactly one thread, i.e. the workgroup size is (1,1,1) and I start the kernel with glDispatchCompute(1, 1, 1) so there should be no concurrency issues.

    If I comment the call to barrier(), the contents of the debug buffer are [17, 17] while they are [17, 19] if I uncomment it. In my mind, it should always be [17, 19] regardless of barrier.

  5. #5
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    The documentation says that the return value of atomicCompSwap is the new value if the comparison yields true and the old value if it yields false.
    No. The atomic memory functions always return the old value. The idea being that if you need the old value, you just got it. And if you need the new value, you can compute it.

    If you do an atomicCompSwap, you have to do the conditional logic with the old value and your test value to see if it was swapped or not. Most of the time, you don't have to care.

    Why do I need a barrier() call after an atomicCompSwap in order to see the new values in the same thread?
    I don't claim to have a full and complete understanding of how the memory model works in the case of shared variables, but my reading of the spec suggests that visibility issues regarding them are about other threads. So this sounds like a driver bug.

    That being said, since every local invocation is writing to the same shared variable (regardless of the fact that there's only one invocation), you're probably confusing the compiler.

  6. #6
    Junior Member Newbie
    Join Date
    Jan 2013
    Posts
    4
    Thanks again for the quick reply! This forum is really helpful

    It sounds logical for the atomic functions to always return the old value, I agree on that. Probably the following quote is just a typo or some other sort of mistake: "If the content of mem is equal to compare, then the content of data is written into mem and is returned from the function" (http://www.opengl.org/sdk/docs/manglsl/).

  7. #7
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    As stated on the page you linked to, "If you find any inaccuracies or typos in the reference pages, don't hesitate to inform us via the feedback form or using the Khronos Bugzilla (you must first create a Bugzilla account, however)." So you should do that. The OpenGL specification clearly states it correctly, as does the Wiki page.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •