对缓冲区资源使用无绑定描述符有意义吗?
Does it make sense to use bindless descriptors for buffer resources?
我正在我的 directx12 项目中尝试使用 bindless hlsl 资源绑定,我明白了为什么 bindless 对于绑定纹理很有用,因为您可以执行以下操作:
DescriptorTable(
SRV(t0, space=0, numDescriptors=unbounded, offset=0),
SRV(t0, space=1, numDescriptors=unbounded, offset=),
SRV(t0, space=2, numDescriptors=unbounded, offset=0)
visibility=SHADER_VISIBLITY_ALL)
Texture2D textures2d[8192] : register(t0, space0);
Texture3D textures3d[8192] : register(t0, space1);
TextureCube texturesCube[8192] : register(t0, space2);
但是绑定缓冲资源,比如StructuredBuffer
s呢?由于它们需要关联一个类型,例如 StructuredBuffer<some_struct>
,您将如何在 HLSL 中声明它们?例如,假设您有许多不同类型的 StructuredBuffer
,您是否必须将它们分别绑定到一个单独的 space?
struct point_light
{
float3 position_ws;
float falloff_start;
float3 color;
float falloff_end;
float3 strenght;
uint id;
};
RWStructuredBuffer<point_light> sb_point_lights : register(u0, space0);
struct spot_light
{
float3 position_ws;
float falloff_start;
float3 color;
float falloff_end;
float3 strenght;
float spot_power;
float3 direction;
uint id;
};
StructuredBuffer<spot_light> sb_spot_lights : register(u0, space1);
或者有没有办法做类似的事情(这不起作用):
struct point_light
{
float3 position_ws;
float falloff_start;
float3 color;
float falloff_end;
float3 strenght;
uint id;
};
RWStructuredBuffer<point_light> sb_point_lights : register(u0, space0);
struct spot_light
{
float3 position_ws;
float falloff_start;
float3 color;
float falloff_end;
float3 strenght;
float spot_power;
float3 direction;
uint id;
};
StructuredBuffer<spot_light> sb_spot_lights : register(u0 + offset_to_spotlights, space0);
如果你需要在相同类型的缓冲区之间切换,动态索引确实有用,但是正如你所说的你需要声明相同类型的资源(也就是说,它与纹理相同,我有共同的例如,Texture2d< uint > 之类的用例,因此它不限于 StructuredBuffer)。
是的,您必须为每个类型化缓冲区声明一个不同的数组,这不是很方便。
如果您想完全动态访问资源(无论类型),Shader Model 6.6 引入了对堆的直接访问(代号:ultimate bindless ;)
所以你有一个名为ResourceDescriptorHeap的全局变量(代表当前绑定的资源Heap)
和 SamplerDescriptorHeap(相同但用于采样器)。
现在你可以这样做(例如):
int textureLocationInHeap =5;
int bufferLocationInHeap = 6;
Texture2D myTexture = ResourceDescriptorHeap[textureLocationInHeap];
StructuredBuffer<float> myBuffer = ResourceDescriptorHeap[bufferLocationInHeap ];
然后您可以使用根常量或常量缓冲区(根据您的喜好)传递 textureLocationInHeap 和 bufferLocationInHeap。
您不再需要传递描述符 tables(当然您仍然可以混合使用 table/“直接访问”
当然请注意,如果您索引的资源类型不正确(或者您有一个空的堆槽),您将面临未定义的结果或驱动程序崩溃(第二种可能性更大)。
更多关于动态资源绑定的信息:
https://devblogs.microsoft.com/directx/in-the-works-hlsl-shader-model-6-6/
我正在我的 directx12 项目中尝试使用 bindless hlsl 资源绑定,我明白了为什么 bindless 对于绑定纹理很有用,因为您可以执行以下操作:
DescriptorTable(
SRV(t0, space=0, numDescriptors=unbounded, offset=0),
SRV(t0, space=1, numDescriptors=unbounded, offset=),
SRV(t0, space=2, numDescriptors=unbounded, offset=0)
visibility=SHADER_VISIBLITY_ALL)
Texture2D textures2d[8192] : register(t0, space0);
Texture3D textures3d[8192] : register(t0, space1);
TextureCube texturesCube[8192] : register(t0, space2);
但是绑定缓冲资源,比如StructuredBuffer
s呢?由于它们需要关联一个类型,例如 StructuredBuffer<some_struct>
,您将如何在 HLSL 中声明它们?例如,假设您有许多不同类型的 StructuredBuffer
,您是否必须将它们分别绑定到一个单独的 space?
struct point_light
{
float3 position_ws;
float falloff_start;
float3 color;
float falloff_end;
float3 strenght;
uint id;
};
RWStructuredBuffer<point_light> sb_point_lights : register(u0, space0);
struct spot_light
{
float3 position_ws;
float falloff_start;
float3 color;
float falloff_end;
float3 strenght;
float spot_power;
float3 direction;
uint id;
};
StructuredBuffer<spot_light> sb_spot_lights : register(u0, space1);
或者有没有办法做类似的事情(这不起作用):
struct point_light
{
float3 position_ws;
float falloff_start;
float3 color;
float falloff_end;
float3 strenght;
uint id;
};
RWStructuredBuffer<point_light> sb_point_lights : register(u0, space0);
struct spot_light
{
float3 position_ws;
float falloff_start;
float3 color;
float falloff_end;
float3 strenght;
float spot_power;
float3 direction;
uint id;
};
StructuredBuffer<spot_light> sb_spot_lights : register(u0 + offset_to_spotlights, space0);
如果你需要在相同类型的缓冲区之间切换,动态索引确实有用,但是正如你所说的你需要声明相同类型的资源(也就是说,它与纹理相同,我有共同的例如,Texture2d< uint > 之类的用例,因此它不限于 StructuredBuffer)。
是的,您必须为每个类型化缓冲区声明一个不同的数组,这不是很方便。
如果您想完全动态访问资源(无论类型),Shader Model 6.6 引入了对堆的直接访问(代号:ultimate bindless ;)
所以你有一个名为ResourceDescriptorHeap的全局变量(代表当前绑定的资源Heap)
和 SamplerDescriptorHeap(相同但用于采样器)。
现在你可以这样做(例如):
int textureLocationInHeap =5;
int bufferLocationInHeap = 6;
Texture2D myTexture = ResourceDescriptorHeap[textureLocationInHeap];
StructuredBuffer<float> myBuffer = ResourceDescriptorHeap[bufferLocationInHeap ];
然后您可以使用根常量或常量缓冲区(根据您的喜好)传递 textureLocationInHeap 和 bufferLocationInHeap。
您不再需要传递描述符 tables(当然您仍然可以混合使用 table/“直接访问”
当然请注意,如果您索引的资源类型不正确(或者您有一个空的堆槽),您将面临未定义的结果或驱动程序崩溃(第二种可能性更大)。
更多关于动态资源绑定的信息:
https://devblogs.microsoft.com/directx/in-the-works-hlsl-shader-model-6-6/