# Changing global variables in HLSL?

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

## Recommended Posts

Hi! I have one simple question: Is it possible to change a global variable by a pixelshader in HLSL/Cg? I mean something like this (of course r++ is stupid to define a color with it, only to demonstrate what I mean):
float r;

{
r++;
return float4(r, 0, 0, 1);
}


r seems to remain zero for all pixels. [Edited by - uggibuggi on June 22, 2007 11:21:05 AM]

##### Share on other sites
All constants are reset for each iteration of a VS/PS. You can't actually change them. That's one of the basic concepts of Shaders, one run cannot affect another's (well, it's more complicated than that, but that's the basics).

What's actually happening is that the HLSL compiler is making a local variable and changing it's value, and using it instead of the global. That way it gets reset each frame.

##### Share on other sites
Some shader languages such as CUDA allow you to access shared and global memory in the kernel, however this memory isn't synchronized or reliable so what you want to do isn't effectively possible.

##### Share on other sites
Ok... Thanks.

So there is absolutely no way to share data between all the pixels being processed?

What I want to do is to calculate the brightest area on the screen. To do that on the cpu, I would calculate the brightness in the area around each pixel and then save the brightness together with the coordinates if it is brighter than the previous saved value.

Because this is an very expensive Task I thought it's be something that could be done by the gpu.

EDIT:
@Zipster: That could help, thanks... I don't need it to be synchronized - the value will only be changed when the value to save is greater than the saved value, so what counts is that in the end I have the biggest value.

##### Share on other sites
Quote:
 Original post by uggibuggiOk... Thanks.So there is absolutely no way to share data between all the pixels being processed?What I want to do is to calculate the brightest area on the screen. To do that on the cpu, I would calculate the brightness in the area around each pixel and then save the brightness together with the coordinates if it is brighter than the previous saved value.Because this is an very expensive Task I thought it's be something that could be done by the gpu.

You can definitely do this on the GPU. What you would do is run a down-sampling filter over the texture in multiple passes until you get a 1x1 result, where the down-sampling filter just choses the brightest pixel in the kernel and outputs the brightness, along with its texture coordinates (like in a 32-bit per-channel floating-point render target). When everything is finished, you have the result in that final texture.

Quote:
 EDIT:@Zipster: That could help, thanks... I don't need it to be synchronized - the value will only be changed when the value to save is greater than the saved value, so what counts is that in the end I have the biggest value.

Unfortunately, I don't know if this is possible in HLSL or Cg.

##### Share on other sites
Quote:
 What you would do is run a down-sampling filter over the texture in multiple passes until you get a 1x1 result

I've already thought about that, but I had the problem that I also need the coordinates of the pixel - but with storing them as color information, it could work.

I've tried the "static" keyword for local variables, for wich Microsoft's HLSL Reference notes this:
Quote:
 For a local variable (declared inside of a function), the static keyword indicates that the value of the variable persists between funtion invocations.

But that doesn't seem to work - for this code, r seems to remain 0.1:
//The Pixelshaderfloat4 PS_Textured( QuadVertexOutput IN): COLOR{	static float r=0;	r+=0.1;	return float4(0, r, 0, 1);}

##### Share on other sites
The static thing is for function invocations in the same shader invocation. It won't share across threads, nothing currently does in DirectX. The only communication you have is in the pixel shader, and only with your pixel neighbors for calculating derivatives (for texture filtering). This is on purpose.

That said, the DirectX team knows that this is a very interesting problem, and that solving it on the GPU makes sense, and that certain GPUs already have some more advanced forms of sharing between threads. So in a future version we may have the ability to do read-modify-write operations such as this, or to have shared memory between threads in a new shader model.

But for now, you'll have to stick with the iterative approach (which is fast, but not the simplest thing to set up).

##### Share on other sites
Quote:

Does that mean that with an assembly-written-shader it would be possible to write to the shared memory?

##### Share on other sites
Quote:
Original post by uggibuggi
Quote:

Does that mean that with an assembly-written-shader it would be possible to write to the shared memory?
No, not using Direct3D. I suspect the same is true of OpenGL.

GPGPU is picking up pace now, Nvidia's Tesla project is just unbelievably crazy - \$12k for a quad G80 (iirc) capable of 2 teraflops of computing power. API's/languages like CUDA are the way to access this.

Anyway, assembly is dead with D3D. You don't really want to use it for SM3 in D3D9 and it's completely blocked under D3D10.

Go with down-sampling, it's a little bit unintuitive at first but it's really not that bad...

hth
Jack

##### Share on other sites
Ok, thanks. I'll try it that way.