7
votes

I'm a bit confused right now and just want to ask you all to help me get a few ideas clarfied.

In a HLSL shader (compute shader for example) I can declare a StructuredBuffer sb, right? Do I HAVE to bind it to a register, such as : register(t0)?

From the application side, I can call CSSetShaderResources(...). The first argument (the StartSlot), does it have anything to do with the little number behind the "t" in the register declaration?

If I set the StartSlot as 0 (for example), and I set the second argument as 2. Am I telling the API that I'll binding two Shader Resource Views, one in register(t0) and another in register(t1)?

If I declare Texture2D tex[10] : register(t0) I can set it by calling CSSetShaderResources(0, 10, ...). Does this mean that registers(t0~t9) are all used up?

Sorry for such a "rapid fire" of questions, but I'm just really confused and some of my tests seem to give confliting results...

Any help would be appreciated.

2

2 Answers

4
votes

So let's reply in order:

Yes you can of course declare a StructuredBuffer in a compute shader (actually you can declare it for any type of shader).

If you don't use effect framework (techniques), you need to declare a register, so the shader will know where to read from your data (using effect framework it just does it under the hood, but you still can explicitely declare).

CSSetShaderResources tells to bind N resources from a start slot, so your description of using 0,2 is correct.

For array of textures, I had to run PIX to check it out, but it's indeed the way you said.

Texture2D tex[10] : register(t0); 

Will mean that each texture index will be allocated a slot starting from the register you specified, so you need to call CSSetShaderResources(0,10,srvarray) to set them.

2
votes

Very cool explanation! I also got confused, and after your questions and explanations it's clear for me!

But I found a good example for this post, which I want to share. It seems it starts the counter of the slot for every SetShaderResources Type. All shaders (VS, HS, DS, PS) seems to have theirs own counter. Here the code from a NVidia example:

The Shaderclass code:

pd3dDeviceContext->HSSetShaderResources( 0, 2, Resources ); 
pd3dDeviceContext->HSSetShaderResources( 8, 1, &m_pRegularWatertightTexSRV );
pd3dDeviceContext->HSSetShaderResources( 9, 1, &m_pQuadWatertightTexSRV );
pd3dDeviceContext->HSSetShaderResources( 2, 1, &pHeightMapTextureSRV );
pd3dDeviceContext->DSSetShaderResources( 2, 1, &pHeightMapTextureSRV );
pd3dDeviceContext->PSSetShaderResources( 2, 1, &pHeightMapTextureSRV );
pd3dDeviceContext->PSSetShaderResources( 10, 1, &pNormalMapTextureSRV );
pd3dDeviceContext->PSSetShaderResources( 3, 1, &pTexRenderRV11 );

The first is holding two resources, so the next slot (line 4) has to add 2 for the starting slot (0+2=2). Every SetShaderResources has to start with 0, but you can do that on different places in your code, therefore there is no 0 slot for DS and PS here. Some times if you remove a line it still works but the data is postponed. Now you see the first four in HLSL at line t0, t1, t8, and t9 the other register were bound somewhere else.

The HLSL code:

Texture2D<float> GregoryStencil               : register( t0 ); 
Texture2D<uint>  Index                        : register( t1 );    
Texture2D<float>  g_txHeight                  : register( t2 );       
Texture2D<float> g_depth                      : register( t3 ); 
Texture2D g_FloorTexture                      : register( t4 );  
Texture2D<float3>  regularPatchControlPoints  : register( t5 ); 
Texture2D<float3>  gregoryPatchControlPoints  : register( t6 ); 
Texture2D<float4>  g_floorHeight              : register( t7 );   
Texture2D<float2>  RegularWatertightUVs       : register( t8 );  
Texture2D<float2>  QuadWatertightUVs          : register( t9 );  
Texture2D<float3>  g_txNormal                 : register( t10 );