Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spirv: miscellaneous stuff #22889

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open

Conversation

alichraghi
Copy link
Contributor

lib/std/Target.zig Outdated Show resolved Hide resolved
SPV_AMD_shader_fragment_mask,
SPV_AMD_gpu_shader_int16,
v1_6,
SPV_AMDX_shader_enqueue,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's totally fine if you don't feel like doing this, but bonus points for making the script fix these names, i.e. amdx_shader_enqueue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah i was actually going to ask is it okay to add helper functions like featureToExtension to Target/spirv.zig

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate? What would that function do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returns the actual extension name of a feature. currently we basically do @tagName(feature) but that would no longer work if we turn features name to snake_case

Copy link
Contributor Author

@alichraghi alichraghi Feb 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never mind. im removing all those unknown features. if someone wants to emit a random capability/extension they can do it through inline assembly. all cpu features must be recognizable by the compiler

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear, I'm not actually opposed to having all these features if there's at least a conceivable world where some compiler-adjacent tooling might be interested in representing/querying them - even if that's not the Zig compiler specifically. For example, I consider it a design goal of std.Target to be usable for tools like dis/assemblers, decompilers, emulators, compilers for other languages, etc...

Good point re: mapping Ziggified names to SPIR-V names; I hadn't thought about that aspect. Ordinarily, we don't add helper functions of this nature in std.Target.<arch>, but that's mostly an artifact of the feature bits not necessarily corresponding to some official set of features. Since the data is readily available when generating the feature list, I don't see any harm in adding a method along the lines of extensionName(feature: Feature) [:0]const u8 for SPIR-V. Obviously only relevant if we decide to go back to that approach rather than the new one you proposed here.

Definitely interested in @Snektron's perspective on all this.

@alichraghi alichraghi force-pushed the ali_spv branch 2 times, most recently from a3f7b49 to b7782ce Compare February 14, 2025 20:39
`OpCapability` and `OpExtension` now can also be emitted from inline assembly
Copy link
Collaborator

@Snektron Snektron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good imo. I'm not completely convinced yet about the target features, but I guess this is better than what it was.

Comment on lines +91 to 96
pub fn binding(comptime ptr: anytype, comptime descriptor_set: u32, comptime bind: u32) void {
asm volatile ("OpDecorate %ptr DescriptorSet " ++ &[_]u8{'0' + descriptor_set} ++
"OpDecorate %ptr Binding " ++ &[_]u8{'0' + bind}
:
: [ptr] "" (ptr),
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this should work

Suggested change
pub fn binding(comptime ptr: anytype, comptime descriptor_set: u32, comptime bind: u32) void {
asm volatile ("OpDecorate %ptr DescriptorSet " ++ &[_]u8{'0' + descriptor_set} ++
"OpDecorate %ptr Binding " ++ &[_]u8{'0' + bind}
:
: [ptr] "" (ptr),
);
pub fn binding(comptime ptr: anytype, comptime descriptor_set: u32, comptime bind: u32) void {
asm volatile (
\\OpDecorate %ptr DescriptorSet $set
\\OpDecorate %ptr Binding $bind
:
: [ptr] "" (ptr),
[set] "c" (set),
[bind] "c" (bind),
);

this $constant syntax was added a while ago I think

Comment on lines +6 to +23
ShaderStereoViewNV,
PerViewAttributesNV,
FragmentFullyCoveredEXT,
MeshShadingNV,
ImageFootprintNV,
FragmentBarycentricNV,
ComputeDerivativeGroupQuadsNV,
FragmentDensityEXT,
ShadingRateNV,
GroupNonUniformPartitionedNV,
ShaderNonUniform,
ShaderNonUniformEXT,
RuntimeDescriptorArray,
RuntimeDescriptorArrayEXT,
InputAttachmentArrayDynamicIndexing,
InputAttachmentArrayDynamicIndexingEXT,
UniformTexelBufferArrayDynamicIndexing,
UniformTexelBufferArrayDynamicIndexingEXT,
StorageTexelBufferArrayDynamicIndexing,
StorageTexelBufferArrayDynamicIndexingEXT,
UniformBufferArrayNonUniformIndexing,
UniformBufferArrayNonUniformIndexingEXT,
SampledImageArrayNonUniformIndexing,
SampledImageArrayNonUniformIndexingEXT,
StorageBufferArrayNonUniformIndexing,
StorageBufferArrayNonUniformIndexingEXT,
StorageImageArrayNonUniformIndexing,
StorageImageArrayNonUniformIndexingEXT,
InputAttachmentArrayNonUniformIndexing,
InputAttachmentArrayNonUniformIndexingEXT,
UniformTexelBufferArrayNonUniformIndexing,
UniformTexelBufferArrayNonUniformIndexingEXT,
StorageTexelBufferArrayNonUniformIndexing,
StorageTexelBufferArrayNonUniformIndexingEXT,
RayTracingNV,
VulkanMemoryModel,
VulkanMemoryModelKHR,
VulkanMemoryModelDeviceScope,
VulkanMemoryModelDeviceScopeKHR,
PhysicalStorageBufferAddresses,
PhysicalStorageBufferAddressesEXT,
ComputeDerivativeGroupLinearNV,
RayTracingProvisionalKHR,
CooperativeMatrixNV,
FragmentShaderSampleInterlockEXT,
FragmentShaderShadingRateInterlockEXT,
ShaderSMBuiltinsNV,
FragmentShaderPixelInterlockEXT,
DemoteToHelperInvocationEXT,
SubgroupShuffleINTEL,
SubgroupBufferBlockIOINTEL,
SubgroupImageBlockIOINTEL,
SubgroupImageMediaBlockIOINTEL,
RoundToInfinityINTEL,
FloatingPointModeINTEL,
IntegerFunctions2INTEL,
FunctionPointersINTEL,
IndirectReferencesINTEL,
AsmINTEL,
AtomicFloat32MinMaxEXT,
AtomicFloat64MinMaxEXT,
AtomicFloat16MinMaxEXT,
VectorComputeINTEL,
VectorAnyINTEL,
ExpectAssumeKHR,
SubgroupAvcMotionEstimationINTEL,
SubgroupAvcMotionEstimationIntraINTEL,
SubgroupAvcMotionEstimationChromaINTEL,
VariableLengthArrayINTEL,
FunctionFloatControlINTEL,
FPGAMemoryAttributesINTEL,
FPFastMathModeINTEL,
ArbitraryPrecisionIntegersINTEL,
UnstructuredLoopControlsINTEL,
FPGALoopControlsINTEL,
KernelAttributesINTEL,
FPGAKernelAttributesINTEL,
FPGAMemoryAccessesINTEL,
FPGAClusterAttributesINTEL,
LoopFuseINTEL,
FPGABufferLocationINTEL,
USMStorageClassesINTEL,
IOPipesINTEL,
BlockingPipesINTEL,
FPGARegINTEL,
AtomicFloat32AddEXT,
AtomicFloat64AddEXT,
LongConstantCompositeINTEL,
v1_6,
int8,
int16,
int64,
float16,
float64,
addresses,
matrix,
kernel,
generic_pointer,
vector16,
shader,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these the same features as LLVM?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines -1016 to -1021
// TODO: merge tools/update_spirv_features.zig into this script
//.{
// .zig_name = "spirv",
// .llvm_name = "SPIRV",
// .td_name = "SPIRV.td",
//},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we need something equivalent to this again with LLVM 20? Since SPIR-V is enabled by default in LLVM 20?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually want to enable using LLVM's SPIR-V backend with Zig? I'd brought that up a while back (I think around the time of the LLVM 19 upgrade?) and there seemed to be some resistance to the idea.

Right now, we explicitly prevent it:

zig/src/codegen/llvm.zig

Lines 13019 to 13023 in 8a3aeba

// We don't currently support using these backends.
.spirv,
.spirv32,
.spirv64,
=> {},

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't do that yet because they define no features

Comment on lines +222 to +223
if (std.Target.spirv.featureSetHas(target.cpu.features, .v1_0)) break :blk 0;
// TODO: always assume a version set?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can always assume to have SPIR-V 1.0

Comment on lines -1379 to 1228
const key = .{ child_ty.toIntern(), storage_class, child_repr };
const entry = try self.ptr_types.getOrPut(self.gpa, key);
if (entry.found_existing) {
const fwd_id = entry.value_ptr.ty_id;
if (!entry.value_ptr.fwd_emitted) {
try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypeForwardPointer, .{
.pointer_type = fwd_id,
.storage_class = storage_class,
});
entry.value_ptr.fwd_emitted = true;
}
return fwd_id;
}

const result_id = self.spv.allocId();
entry.value_ptr.* = .{
.ty_id = result_id,
.fwd_emitted = false,
};

fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef {
const child_ty_id = try self.resolveType(child_ty, child_repr);

try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{
.id_result = result_id,
.storage_class = storage_class,
.type = child_ty_id,
});

const result_id = try self.spv.ptrType(child_ty_id, storage_class);
if (storage_class == .Uniform or storage_class == .PushConstant) try self.spv.decorate(child_ty_id, .Block);
try self.spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = @intCast(child_ty.abiSize(self.pt.zcu)) } });
return result_id;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the right way to handle things because it doesn't correctly handle recursive pointers. The call to self.resolveType() would enter an infinite loop, thats why the ptr_types map is handled especially. For example, this kernel fails:

const Node = struct { node: *Node };

export fn oef() callconv(.spirv_kernel) void {
    var a: Node = undefined;
    _ = &a;
}
~/programming/zig/build/spirv-zig/bin/zig build-obj ./test.zig  -fno-compiler-rt -target spirv64-ope
ncl-gnu -mcpu generic+int64+int16+int8+float64+float16+generic_pointer+v1_6+kernel -fno-llvm -freference-trace
fish: Job 1, '~/programming/zig/build/spirv-z…' terminated by signal SIGSEGV (Address boundary error)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future we might be able to remove this ugly piece of code by relying on SPV_KHR_untyped_pointers. Some projects are already adding support for this, so hopefully we will be able to use this in the not too far away future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants