Partager via


Modifications du bytecode dans SM5.1

SM5.1 modifie la façon dont les registres de ressources sont déclarés et référencés dans les instructions.

SM5.1 s’oriente vers la déclaration d’un registre « variable », de la même façon que pour les registres de mémoire partagée de groupe, illustré par l’exemple suivant :

Texture2D<float4> tex0          : register(t5,  space0);
Texture2D<float4> tex1[][5][3]  : register(t10, space0);
Texture2D<float4> tex2[8]       : register(t0,  space1);
SamplerState samp0              : register(s5, space0);

float4 main(float4 coord : COORD) : SV_TARGET
{
    float4 r = coord;
    r += tex0.Sample(samp0, r.xy);
    r += tex2[r.x].Sample(samp0, r.xy);
    r += tex1[r.x][r.y][r.z].Sample(samp0, r.xy);
    return r;
}

Le désassemblement de cet exemple est le suivant :

// Resource Bindings:
//
// Name                                 Type  Format         Dim Space Slot  Elements
// ------------------------------ ---------- ------- ----------- ----- ---- ---------
// samp0                             sampler      NA          NA     0    5         1
// tex0                              texture  float4          2d     0    5         1
// tex1[0][5][3]                     texture  float4          2d     0   10 unbounded
// tex2[8]                           texture  float4          2d     1    0         8
//
//
//
// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// COORD                    0   xyzw        0     NONE   float   xyzw
//
//
// Output signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_TARGET                0   xyzw        0   TARGET   float   xyzw
//
ps_5_1
dcl_globalFlags refactoringAllowed
dcl_sampler s0[5:5], mode_default, space=0
dcl_resource_texture2d (float,float,float,float) t0[5:5], space=0
dcl_resource_texture2d (float,float,float,float) t1[10:*], space=0
dcl_resource_texture2d (float,float,float,float) t2[0:7], space=1
dcl_input_ps linear v0.xyzw
dcl_output o0.xyzw
dcl_temps 2
sample r0.xyzw, v0.xyxx, t0[0].xyzw, s0[5]
add r0.xyzw, r0.xyzw, v0.xyzw
ftou r1.x, r0.x
sample r1.xyzw, r0.xyxx, t2[r1.x + 0].xyzw, s0[5]
add r0.xyzw, r0.xyzw, r1.xyzw
ftou r1.xyz, r0.zyxz
imul null, r1.yz, r1.zzyz, l(0, 15, 3, 0)
iadd r1.y, r1.z, r1.y
iadd r1.x, r1.x, r1.y
sample r1.xyzw, r0.xyxx, t1[r1.x + 10].xyzw, s0[5]
add o0.xyzw, r0.xyzw, r1.xyzw
ret
// Approximately 12 instruction slots used

Chaque plage de ressources de nuanceur a désormais un ID (un nom) dans le bytecode du nuanceur. Par exemple, le tableau de textures tex1 devient « t1 » dans le code d’octet du nuanceur. L’attribution d’ID uniques à chaque plage de ressources permet deux choses :

  • Identifiez sans ambiguïté la plage de ressources (voir dcl_resource_texture2d) qui est indexée dans une instruction (voir exemple d’instruction).
  • Attachez un ensemble d’attributs à la déclaration, par exemple, le type d’élément, la taille de la foulée, le mode d’opération raster, etc..

Notez que l’ID de la plage n’est pas lié à la déclaration de limite inférieure HLSL.

L’ordre des liaisons de ressources de réflexion et des instructions de déclaration du nuanceur est le même pour aider à identifier la correspondance entre les variables HLSL et les ID de bytecode.

Chaque instruction de déclaration dans SM5.1 utilise un opérande 3D pour définir : ID de plage, limites inférieure et supérieure. Un jeton supplémentaire est émis pour spécifier l’espace d’inscription. D’autres jetons peuvent également être émis pour transmettre des propriétés supplémentaires de la plage, par exemple, cbuffer ou l’instruction de déclaration de mémoire tampon structurée émet la taille du cbuffer ou de la structure. Les détails exacts de l’encodage se trouvent dans d3d12TokenizedProgramFormat.h et D3D10ShaderBinary::CShaderCodeParser.

Les instructions SM5.1 n’émettent pas d’informations supplémentaires sur l’opérande des ressources dans le cadre de l’instruction (comme dans SM5.0). Ces informations sont maintenant déplacées vers les instructions de déclaration. Dans SM5.0, les instructions d’indexation des ressources exigeaient que les attributs de ressource soient décrits dans des jetons opcode étendus, car l’indexation obfuscatait l’association à la déclaration. Dans SM5.1, chaque ID (tel que « t1 ») est associé sans ambiguïté à une déclaration unique qui décrit les informations de ressource requises. Par conséquent, les jetons opcode étendus utilisés dans les instructions pour décrire les informations de ressource ne sont plus émis.

Dans les instructions de non-déclaration, un opérande de ressources pour les échantillonneurs, les SVS et les UAV est un opérande 2D. Le premier index est une constante littérale qui spécifie l’ID de plage. Le deuxième index représente la valeur linéarisée de l’index. La valeur est calculée par rapport au début de l’espace de registre correspondant (et non par rapport au début de la plage logique) afin de mieux corréler avec la signature racine et de réduire la charge du compilateur de pilotes liée à l’ajustement de l’index.

Un opérande de ressources pour les cbV est un opérande 3D : ID littéral de la plage, index du cbuffer, décalage dans le instance particulier de cbuffer.

Fonctionnalités du nuanceur HLSL Modèle 5.1 pour Direct3D 12

Modèle de nuanceur 5.1