🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Direct3D 11 Programming Tip #6

Published August 27, 2009
Advertisement

Direct3D 11 Programming Tip #6: Compute Shader Addressing

This tip will be the final compute shader 'background' type post. We will be looking at how the compute shader utilizes the new system values to slice up a programming task, and at the same time give the developer a very rich and powerful system to implement complex algorithms. These system values represent the heart of any algorithm on the compute shader, and give it the flexibility to do general purpose computation in addition to the graphics algorithms that are sure to come out in the next month or so (I mean the demos when W7 launches...).

New System Values for Compute Shader

There is a new set of system values that have been introduced that are specific to the compute shader in shader model 5.0. These values are generated by D3D and passed into your compute shader as input arguments. In the past couple tip posts, I mentioned two major concepts in the compute shader: thread groups, and the dispatch call. A thread group is composed of a 3 dimensional number of threads, which is declared in your shader code. Then, the number of thread groups that are invoked is specified by the 'Dispatch' call, which takes another 3 dimensional number of thread groups as input. These concepts are the key to understanding the new system values, which we will list and describe here:

SV_GroupID :: This system value provides the compute shader function with a 3 dimensional 'group ID'. The group ID identifies which thread group each invocation of the compute shader belongs to. So if you call Dispatch(4,1,1) from your application, you will get 4 thread groups and this system value will vary from 0-3 in the x coordinate depending on which group a given thread belongs to.

SV_GroupThreadID :: This system value provides the compute shader function with a 3 dimensional 'group thread ID'. This identifies which thread is currently being run within the current thread group. So if you declared [numthreads( 32, 32, 1 )] in your compute shader HLSL code, then you would get 32x32 thread invocations and this system value would vary from 0-31 in both the x and the y coordinates depending on the current thread.

SV_GroupIndex :: This system value provides a similar identifier as the SV_GroupThreadID, but it is a 1 dimensional value instead. This is done in the same manner that you would index a multi-dimensional array as a single dimensional array - if given an group thread ID of (12,6,1) with the same thread declaration shown above, then the index would calculated be as follows: 11 + 5*32 + 0*32*32 = 171

SV_DispatchThreadID :: This system value provides a similar identifier as the group thread ID, but the range of the thread ID's is spread out over an entire dispatch call. For example, if you have the same thread declaration as above and called Dispatch(3,3,1) then the dispatch thread IDs would vary from 0*32 to 2*32 in both the x and y directions.

Given these descriptions, lets take a step back and consider what is going on when the compute shader is operating. When you think about what your compute shader is going to do when it is executed, it really just boils down to the fact that your shader function will be executed many times on the resources that you bind to it. The only differences between invocations is that the system values are varied in a systematic way. It is up to the developer to choose an appropriate configuration of threads per thread group, and thread groups per dispatch call to make the system values cover the range of your resources to be operated on.

Example Algorithm

With this in mind, it would be best to consider an example of how this could be used. The prototypical example for the compute shader is image processing, so let's start out there. We'll start out slow, and say that we want to make a compute shader that will invert the color of a texture bound to the computer shader. The image to be inverted will be 640x480, and will consist of 3 color channels.

Just for the sake of the example, we'll say that the number of threads per thread group is going to be 20x20x1. This means that we will be processing the image in chunks that are 20x20. To cover the entire image, the Dispatch call will need to consist of 32x24x1 thread groups. Our compute shader code would look like the following:

//// InvertColorCS.hlsl//// Copyright (C) 2009  Jason Zink Texture2D		InputMap : register( t0 );           RWTexture2D	OutputMap : register( u0 );// Group size#define size_x 20#define size_y 20// Declare one thread for each texel of the input texture.[numthreads(size_x, size_y, 1)]void CSMAIN( uint3 GroupID : SV_GroupID, uint3 DispatchThreadID : SV_DispatchThreadID, uint3 GroupThreadID : SV_GroupThreadID, uint GroupIndex : SV_GroupIndex ){	int3 texturelocation = int3( 0, 0, 0 );	texturelocation.x = GroupID.x * size_x + GroupThreadID.x;	texturelocation.y = GroupID.y * size_y + GroupThreadID.y;	float3 Color = InputMap.Load(texturelocation);	OutputMap[texturelocation.xy] = float3( 1.0f, 1.0f, 1.0f ) - Color;}

Here you can see how the texturelocation variable utilizes the group ID and the size of the thread group in addition to the group thread ID to calculate the proper place in the input texture to load. In addition, the same address is used to write to the output texture.

This was a pretty simple example, but gives you a quick taste of how the compute shader addressing is used. From here on out, we are going to take off the training wheels and start looking at something more complex for the compute shader. I have a few other tips in the queue that may come before the next example, but it is coming...

I also wanted to mention that if anyone has a particular portion of the D3D11 API that they want to know more about, feel free to post it in a comment. I can't guarantee that I know all about it, but I can guarantee that I will find out all about and then write about it too! [grin]
Previous Entry Hardware Updates
Next Entry Untitled
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement