Sign in to follow this  
jplynch

Assigning specific shader resource slots to textures in DX10

Recommended Posts

Any help here would be greatly appreciated as I am at a loss. Essentially, I have some HLSL shader code that needs to run in both DX9 and DX10 with as few changes as possible. Fortunately, the DX10 shader compiler has a backwards compatibility mode that allows Shader Model 3.0 code to be compiled for Shader Model 4.0. So far so good. Unfortunately, while the compiler honors the registers to which I assign samplers, it does NOT do likewise for textures. In fact, no matter what I do, the compiler seems to assign slots to the textures in order of first use in the shader file. This is highly unintuitive and makes it really hard to match samplers with textures. It is not feasible for me to rewrite all of the shaders to use code specifically for Shader Model 4.0. Furthermore, the engine in which these shaders must run uses the sampler index to assign textures; it requires that they be identical. While this could be changed, if necessary, I would really, really, really like to avoid that option. In any case, does anyone know of a way to force the DX10 shader compiler to bind textures to a specific register/sampler while compiling in backwards compatibility mode? It is amazing to me that this would not be possible. Here is an example of what I'm talking about. This code: float4 vs_main( float4 pos : POSITION ) : POSITION { return pos; } texture2D diffuse_tex0 : register( t0 ); texture2D diffuse_tex1 : register( t1 ); sampler2D diffuse_samp0 : register( s0 ) = sampler_state { Texture = <diffuse_tex0>; }; sampler2D diffuse_samp1 : register( s1 ) = sampler_state { Texture = <diffuse_tex1>; }; float4 ps_main() : COLOR0 { return tex2D( diffuse_samp1, float2( 0.5f, 0.5f ) ) * tex2D( diffuse_samp0, float2( 0.5f, 0.5f ) ); } Produces this output: // // Generated by Microsoft (R) HLSL Shader Compiler 9.23.949.2378 // // // fxc /Tps_4_0 /Eps_main /Gec sampler_org.hlsl // // // Resource Bindings: // // Name Type Format Dim Slot Elements // ---------------- ---------- ------- ----------- ---- -------- // diffuse_samp0 sampler NA NA 0 1 // diffuse_samp1 sampler NA NA 1 1 // diffuse_samp1 texture float 2d 2 1 // diffuse_samp0 texture float 2d 3 1 // // // // Input signature: // // Name Index Mask Register SysValue Format Used // ---------------- ----- ------ -------- -------- ------ ------ // no Input // // Output signature: // // Name Index Mask Register SysValue Format Used // ---------------- ----- ------ -------- -------- ------ ------ // SV_Target 0 xyzw 0 TARGET float xyzw // ps_4_0 dcl_output o0.xyzw dcl_sampler s0, mode_default dcl_sampler s1, mode_default dcl_resource_texture2d ( float , float , float , float ) t2 dcl_resource_texture2d ( float , float , float , float ) t3 dcl_temps 2 sample r0.xyzw, l(0.500000, 0.500000, 0.000000, 0.000000), t2.xyzw, s1 sample r1.xyzw, l(0.500000, 0.500000, 0.000000, 0.000000), t3.xyzw, s0 mul o0.xyzw, r0.xyzw, r1.xyzw ret // Approximately 4 instruction slots used Note that sampler zero is sampling from shader resource three and that sampler one is sampling from shader resource two, despite my specification. Any help greatly appreciated. ** EDIT ** Fixed typo in code that did not affect output.

Share this post


Link to post
Share on other sites
Try this:

float4 vs_main( float4 pos : POSITION ) : POSITION
{
return pos;
}


texture2D diffuse_tex0 : register( t0 );
texture2D diffuse_tex1 : register( t1 );

sampler diffuse_samp0 : register( s0 ) =
sampler_state
{
Texture = <diffuse_tex0>;
};

sampler diffuse_samp1 : register( s1 ) =
sampler_state
{
Texture = <diffuse_tex1>;
};


float4 ps_main() : SV_Target0
{
return diffuse_tex1.Sample( diffuse_samp1, float2( 0.5f, 0.5f ) ) * diffuse_tex0.Sample( diffuse_samp0, float2( 0.5f, 0.5f ) );
}

------------------

You're not referencing the textures at all, so it shouldn't be surprising that your register selections aren't doing anything. Instead you're hitting the compiler's DX9 compatibility path (where you can still specify resource registers, but you have to put the t binding on the sampler).

Share this post


Link to post
Share on other sites
Thanks for the reply!

That solution does indeed work, and I was surprised to find that it also compiles for Shader Model 3.0 targets. Unfortunately, it's also not a good solution for me because the system that I have to use to generate and compile the shaders makes it easy to change the declaration of the samplers/textures (and their semantics/registers) but much harder to change the code where the samplers/texture are used. It would also require changing the way the DX9 shaders are compiled, as they currently use an older compiler.

I do quibble with the assertion that the texture was not previously being referenced. I had hoped that the fact that it is assigned to the sampler_state would be sufficient for the compiler.

Now the good news: I did indeed find a solution to the problem that requires only changing the declaration. You can assign both a sampler register AND a texture register to a sampler at the same time:

float4 vs_main( float4 pos : POSITION ) : POSITION
{
return pos;
}

sampler2D diffuse_samp0 : register( s0 ) : register( t0 ) =
sampler_state
{
Texture = <diffuse_tex0>;
};

sampler2D diffuse_samp1 : register( s1 ) : register( t1 ) =
sampler_state
{
Texture = <diffuse_tex1>;
};


float4 ps_main() : COLOR0
{
return tex2D( diffuse_samp1, float2( 0.5f, 0.5f ) ) * tex2D( diffuse_samp0, float2( 0.5f, 0.5f ) );
}

The above code does indeed produce the correct output! I only wish that this functionality had been documented somewhere (or, if it has been, that it would have been in an easier to find location).

The sampler_state blocks are probably superfluous now. In any case, problem solved. Thanks so much for your assistance, even though I'm going a different route. I hope this proves useful to someone else in the future.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this