diff --git a/crates/spirv-std/macros/src/lib.rs b/crates/spirv-std/macros/src/lib.rs
index 9ecc7aef8b..202454a85b 100644
--- a/crates/spirv-std/macros/src/lib.rs
+++ b/crates/spirv-std/macros/src/lib.rs
@@ -76,7 +76,7 @@ mod image;
 use proc_macro::TokenStream;
 use proc_macro2::{Delimiter, Group, Ident, Span, TokenTree};
 
-use syn::{punctuated::Punctuated, spanned::Spanned, visit_mut::VisitMut, ItemFn, Token};
+use syn::{punctuated::Punctuated, spanned::Spanned, visit_mut::VisitMut, ItemFn, Token, Visibility};
 
 use quote::{quote, ToTokens};
 use std::fmt::Write;
@@ -149,6 +149,14 @@ pub fn spirv(attr: TokenStream, item: TokenStream) -> TokenStream {
     let attr: proc_macro2::TokenStream = attr.into();
     tokens.extend(quote! { #[cfg_attr(target_arch="spirv", rust_gpu::spirv(#attr))] });
 
+    if attr.to_string().trim() == "fragment" {
+        let item_clone = item.clone();
+        let input = syn::parse_macro_input!(item_clone as ItemFn);
+        if !matches!(input.vis, Visibility::Public(_)) {
+            panic!("The `spirv` macro can only be applied to public functions.");
+        }
+    }
+
     let item: proc_macro2::TokenStream = item.into();
     for tt in item {
         match tt {