Skip to content

SPIR-V: .storage_buffer address space incorrectly blocks pointer indexing #25638

@jonascloud

Description

@jonascloud

Zig Version

Zig 0.15+

Steps to Reproduce and Observed Behavior

 extern var buffer: [*]addrspace(.storage_buffer) f32;

  export fn test_fn() void {
      _ = buffer[0]; // Error: illegal operation on logical pointer
  }

Build:
zig build-lib -target spirv64-vulkan -mcpu vulkan_v1_2+variable_pointers test.zig

Edit summary:
I was using [*]f32 addrspace(.storage_buffer) which is wrong => needs to be [*]addrspace(.storage_buffer) f32. The old error was leading me to believe the address space was being lost, but in reality it was not set correctly. Fixing this leads to the New Error. Fix 2 should solve this. Will post a pr soon.
Edit summary end.

Old Error:
test.zig:16:11: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan

New Error:
test.zig:16:11: note: cannot perform arithmetic on pointers with address space 'storage_buffer' on target spirv-vulkan

Fix 2

src/target.zig:569 unconditionally marks .storage_buffer as logical - which is true.
src/Sema.zig:23166 checks via arePointersLogical if indexing operations are allowed:

 if (target_util.arePointersLogical(target, as)) {
            return sema.failWithOwnedErrorMsg(block, msg: {
                const msg = try sema.errMsg(src, "illegal operation on logical pointer of type '{f}'", .{ty.fmt(pt)});

Which is wrong because .storage_buffer can support indexing via OpPtrAccessChain if variable_pointers_storage_buffer is enabled.
A quick fix would be to change src/target.zig:569 to:

.storage_buffer => !target.cpu.features.isEnabled(@intFromEnum(std.Target.spirv.Feature.variable_pointers)),

I would suggest a name change though, because arePointersLogical is not asking if indexing operations are allowed. .storage_buffer pointers are still logical. But they can also support Indexing.
Maybe something like:

 /// Returns whether new pointer values can be derived from existing pointers in the given
 /// address space. In SPIR-V, this corresponds to whether OpPtrAccessChain and similar
 /// pointer derivation operations are supported, which depends on capabilities like
 /// Addresses, VariablePointers, VariablePointersStorageBuffer, PhysicalStorageBufferAddresses
 pub fn canDerivePointers(target: *const std.Target, as: AddressSpace) bool {

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions