shader-slang / slang

Making it easier to work with shaders
MIT License
2.02k stars 172 forks source link

Support resources in structured buffer types? #922

Closed tangent-vector closed 9 months ago

tangent-vector commented 5 years ago

Slang current supports having a ConstantBuffer<X> where X contains resources. This continues support that has already existed in fxc for a long time. If the user writes:

struct X { float4 u; Texture2D t; SamplerState s; }
ConstantBuffer<X> cb;

the Slang compiler generates output along the lines of:

struct X { float4 u; }
ConstantBuffer<X> cb : register(b0);
Texture2D cb_t : register(t0);
SamplerState cb_s : register(s0);

This is similar in spirit to what you would get with a ParameterBlock<X> except that the output doesn't automatically use a full space or set (the latter is quite important on Vulkan, where there are tight constraints on how many sets you can use).

The user can use this same pattern with arrays, where there ends up being a difference between something like ConstantBuffer<X[10]> vs. ConstantBuffer<X>[10] (the same basic pattern could be extended to unbounded-size arrays). In the first case the output will be something like:

struct X { float4 u; }
ConstantBuffer<X[10]> cb;
Texture2D cb_t[10];
SamplerState cb_s[10];

while in the latter case you would get:

struct X { float4 u; }
ConstantBuffer<X> cb[10]; // note how the `[10]` moved
Texture2D cb_t[10];
SamplerState cb_s[10];

There's a clear difference here between whether you have one constant buffer with an array in it, or an array of constant buffers. In many cases a developer will prefer the single-buffer case because it means fewer descriptors need to be set up in application code.

Constant buffers have some API-imposed restrictions on their overall size, such that using them as backing storage for large arrays isn't always desirable. In cases where a Slang user might be inclined to reach for ConstantBuffer<X[LARGE_NUMBER]> but LARGE_NUMBER is either unbounded or too big for constant buffer size limits, they might instead prefer to use a StructuredBuffer<X>.

Slang currently only supports StructuredBuffer<X> when the type X contains only ordinary/uniform data (any other cases will fail in the "type legalization" pass). An alternative would be to take code like this:

struct X { float4 u; Texture2D t; SamplerState s; }
StructuredBuffer<X> sb;

and transform it into code like this:

struct X { float4 u; }
StructuredBuffer<X> sb;
Texture2D sb_t[];
SamplerState sb_s[];

That is, the uniform/ordinary data stays in the structured buffer while all the resource-type fields get surfaced as unbounded-size arrays alongside it.

This could be a useful feature for renderers that want to support unbounded-size arrays of high-level types but aren't yet ready to dive in to "full bindless" approaches. It may be, however, that the payoff for supporting this kind of idiom is small compared to just making "full bindless" idioms easier.

natduca commented 9 months ago

Cloisng due to inactivity. Lets reopen if we get a customer use case.