GLSL Spinlock


I have longstanding problems with texture mutexes.

I have rewritten some of my old code in a new framework, and am still getting the same problems.

Here is a string literal containing the body of a fragment shader that, when run on an NVIDIA GeForce GTX 580M, with driver 340.52, deadlocks the driver. The texture mutex (of type UINT32 R) is in img2D_0, and is initialized each frame to VALUE_UNLOCKED:

"	ivec2 coord = ivec2(gl_FragCoord.xy);\n"

"	float depth_added = /*some easy calculation*/;\n"

"	bool have_written = false;\n"
"	while (!have_written) {\n"
"		bool can_write = imageAtomicExchange(img2D_0,coord," STRINGIFY_VALUE(VALUE_LOCKED) ")==" STRINGIFY_VALUE(VALUE_UNLOCKED) ";\n"
"		memoryBarrier();\n"

"		if (can_write) {\n"
			//critical section:
"			imageAtomicExchange(img2D_0,coord," STRINGIFY_VALUE(VALUE_UNLOCKED) ");\n"
"			have_written = true;\n"
"		}\n"
"		memoryBarrier();\n"

		//Just some extra method.  Deleting these two lines doesn't affect the failure.
"		if (!have_written) continue;\n"
"		break;\n"
"	}\n"

"	discard;\n"

I can replace the while loop with a for loop that puts a hard limit on the number of loops, but then some fragments’ critical sections aren’t run (a bit of extra imageStore-ing to other images confirms that).

What is going on here, and how can I fix it?