Skip to content

spvDescriptorHeapEXT fetching nested data incorrectly #11483

@calkwong

Description

@calkwong

Issue Description

When accessing a uniform buffer from descriptor heap using spvDescriptorHeapEXT (no descriptor sets and bindings), computed addresses are potentially incorrect for nested variables.

public struct UniformBuffer
{
    public float4x4 view;
	public float4x4 proj;
	public float4x4 view_proj;
	public float4x4 inverse_view_proj;
	public float4x4 prev_view_proj;
	public float4x4 light_rot;
	public float4x4 shadow_transforms[4]; // PROBLEM HERE
	public float4 cascade_splits;
	public float4 camera_pos;
	public float4 sunlight_color;
	public float4 sunlight_dir;
	public uint skybox_id;
	public uint irradiance_id;
	public uint prefiltered_id;
	public uint brdf_id;
}

Every other fetched variable is fine, but data for shadow_transforms is always wrong.

Reproducer Code

getDescriptorFromHandle(ConstantBuffer<UniformBuffer>.Handle(uint2(index,0))).shadow_transforms[i]

Above is how I fetch the data.

Expected Behavior

This incorrect behavior only surfaced after I switched from using descriptor sets and bindings (also descriptor heap) to untyped pointers (spvDescriptorHeapEXT). Apart from changing how descriptors are fetched across the board, no shader logic was touched.
Before this change, I accessed the uniform buffer this way:

[[vk::binding(0, 0)]] public ConstantBuffer<UniformBuffer> uniforms;
uniforms.shadow_transforms[i];

In spirv, as far as I can tell the way data is laid out in the uniform buffer is exactly the same in both cases. The only difference is the source of the base pointer.
For the problematic case:

%135 = OpUntypedAccessChainKHR %_ptr_UniformConstant %_runtimearr_133 %slang_resourceHeap %uint_0
%142 = OpBufferPointerEXT %_ptr_Uniform_UniformBuffer_natural %135

Working case:

%uniforms = OpVariable %_ptr_Uniform_UniformBuffer_natural Uniform

Workarounds

With spvDescriptorHeapEXT, If I flatten the array of matrices into individual float4x4 variables, they are fetched correctly again. Alternatively, passing the buffer's address directly through push constants and fetching manually also works correctly.

Environment

  • Slang v2016.10.2
  • Vulkan 1.4.350
  • Linux 7.0.11-1-cachyos
  • NVIDIA 3070ti / Driver 610.43.02
  • slangc compiler options: -capability spvDescriptorHeapEXT -spirv-resource-heap-stride 32 -matrix-layout-column-major -fvk-use-scalar-layout

Metadata

Metadata

Assignees

Type

No fields configured for Bug.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions