{"id":2482,"date":"2022-09-20T01:10:05","date_gmt":"2022-09-20T01:10:05","guid":{"rendered":"https:\/\/cml-a.com\/content\/?p=2482"},"modified":"2022-09-20T01:10:05","modified_gmt":"2022-09-20T01:10:05","slug":"register-spaces","status":"publish","type":"post","link":"https:\/\/cml-a.com\/content\/2022\/09\/20\/register-spaces\/","title":{"rendered":"Register Spaces"},"content":{"rendered":"\n<p>Recently someone asked me '<strong>what are HLSL register spaces'?<\/strong> in the context of D3D12. I'm crossposting the answer here in case you also want to know.<\/p>\n\n\n\n<p>A good comparison is C++ namespaces. Obviously, in C++, you can put everything in the default (global) namespace if you want, but having a namespace gives you a different dimension in naming things. You can have two symbols with the same name, and there's some extra syntax you use to help the compiler dis-ambiguate.<\/p>\n\n\n\n<p>HLSL register spaces are like that. Ordinarily, defining two variables to the same register like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cbuffer MyVar : register(b0)\n{\n\tmatrix projection;\n};\n\ncbuffer MyVar2 : register(b0)\n{\n\tmatrix projection2;\n};<\/code><\/pre>\n\n\n\n<p>will produce a compiler error, like<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>1>FXC : error : resource MyVar at register 0 overlaps with resource MyVar2 at register 0, space 0<\/code><\/pre>\n\n\n\n<p>But if you put them in different register spaces, like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cbuffer MyVar : register(b0, space0)\n{\n\tmatrix projection;\n};\n\ncbuffer MyVar2 : register(b0, space1)\n{\n\tmatrix projection2;\n};<\/code><\/pre>\n\n\n\n<p>then it\u2019s fine, it's not a conflict anymore. <\/p>\n\n\n\n<p>When you create a binding that goes with the shader register, that\u2019s when you can dis-ambiguate which one you mean:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>              CD3DX12_DESCRIPTOR_RANGE range;\n              CD3DX12_ROOT_PARAMETER parameter;\n\n              UINT myRegisterSpace = 1;\n              range.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0, myRegisterSpace);\n              parameter.InitAsDescriptorTable(1, &amp;range, D3D12_SHADER_VISIBILITY_VERTEX);\n<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p> <strong>Q: In the above example, what if I defined both MyVar and MyVar2 as b0, then assigned bindings to both of them (e.g., with SetGraphicsRootDescriptorTable)? <\/strong><\/p><p> A: That's fine. Just make sure the root parameter is set up to use the register space you intended on.<\/p><\/blockquote>\n\n\n\n<p>Small, simple test applications all written by one person usually don\u2019t have a problem with overlapping shader registers. <\/p>\n\n\n\n<p>But things get more complicated when you have different software modules working together. You might have some other component you don\u2019t own, which has its own shaders, and those shaders want to bind variables which occupy shader registers t0-t3. And then there\u2019s a different component you don\u2019t own, which also want t0-t3. Ordinarily, that\u2019d be a conflict you can\u2019t resolve. With register spaces, each component can use a different register space (still a change to their shader code, but a way simpler one) and then there\u2019s no conflict. When you go to create bindings for those shader variables, you just specify which register space you mean.<\/p>\n\n\n\n<p>Another case where register spaces can come in handy is if your application is taking advantage of <em>bindless <\/em>shader semantics. One way of doing that is: in your HLSL you declare a gigantic resource array. It could be unbounded, or have a very large size. Then at execution time, you populate and use bindings at various indices in the array. Ordinarily, two giant resource arrays would likely overlap each other and create a collision. With register spaces, there's no collision.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Going forward, you might be less inclined to need register spaces with bindless semantics. Why? Because with Shader Model 6.6 dynamic resource indexing, <em>bindless<\/em> semantics is a lot more convenient- you don't have to declare a giant array. Read more about dynamic resource indexing here: <a href=\"https:\/\/microsoft.github.io\/DirectX-Specs\/d3d\/HLSL_SM_6_6_DynamicResources.html\">https:\/\/microsoft.github.io\/DirectX-Specs\/d3d\/HLSL_SM_6_6_DynamicResources.html<\/a><\/p><\/blockquote>\n\n\n\n<p>Finally, register spaces can make it easier to port code using previous versions of the Direct3D programming API (e.g., Direct3D 11). In previous versions, applications could use the same shader register to mean different things for different pipeline stages, for example, VS versus PS. In Direct3D 12, a root signature unifies all graphics pipeline bindings and is common to all stages. When porting shader code, therefore, you  might choose to use one register space per shader stage, to keep everything correct and non-ambiguous.<\/p>\n\n\n\n<p>If you want some more reference material on register spaces, here's the section of the public spec:<br><a href=\"https:\/\/microsoft.github.io\/DirectX-Specs\/d3d\/ResourceBinding.html#note-about-register-space\">https:\/\/microsoft.github.io\/DirectX-Specs\/d3d\/ResourceBinding.html#note-about-register-space <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently someone asked me &#8216;what are HLSL register spaces&#8217;? in the context of D3D12. I&#8217;m crossposting the answer here in case you also want to know. A good comparison is C++ namespaces. Obviously, in C++, you can put everything in the default (global) namespace if you want, but having a namespace gives you a different [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[44,51,75,224],"class_list":["post-2482","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-d3d12","tag-directx","tag-graphics","tag-windows"],"_links":{"self":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/posts\/2482","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/comments?post=2482"}],"version-history":[{"count":0,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/posts\/2482\/revisions"}],"wp:attachment":[{"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/media?parent=2482"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/categories?post=2482"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cml-a.com\/content\/wp-json\/wp\/v2\/tags?post=2482"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}