11/*
2- * Copyright 2016-2022 Aaron Barany
2+ * Copyright 2016-2025 Aaron Barany
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
1818#include < MSL/Compile/Output.h>
1919#include " ExecuteCommand.h"
2020#include " MetalOutput.h"
21+ #include < spirv/unified1/spirv.hpp>
2122#include < cassert>
2223#include < fstream>
2324#include < sstream>
@@ -42,8 +43,8 @@ namespace msl
4243
4344using namespace compile ;
4445
45- static void setBinding (std::vector< uint32_t >& spirv, std:: uint32_t id, std:: uint32_t set,
46- std::uint32_t binding)
46+ static void setBinding (
47+ std::vector< uint32_t >& spirv, std:: uint32_t id, std:: uint32_t set, std:: uint32_t binding)
4748{
4849 const unsigned int firstInstruction = 5 ;
4950 const std::uint32_t opCodeMask = 0xFFFF ;
@@ -131,8 +132,8 @@ static std::vector<std::uint32_t> setBindingIndices(const std::vector<std::uint3
131132 return adjustedSpirv;
132133}
133134
134- static std::string setFragmentGroup (const std::string& metal, const std::string& entryPoint,
135- std::uint32_t fragmentGroup)
135+ static std::string setFragmentGroup (
136+ const std::string& metal, const std::string& entryPoint, std::uint32_t fragmentGroup)
136137{
137138 std::string structDecl = " struct " + entryPoint + " _out" ;
138139 std::size_t outStructStart = metal.find (structDecl);
@@ -164,8 +165,8 @@ static std::string setFragmentGroup(const std::string& metal, const std::string&
164165 return result;
165166}
166167
167- static std::string patchEntryPointInputGroup (const std::string& metal,
168- const FragmentInputGroup& inputGroup)
168+ static std::string patchEntryPointInputGroup (
169+ const std::string& metal, const FragmentInputGroup& inputGroup)
169170{
170171 // Expect one primary declaration in the entry point.
171172 std::string declStart = " constant " + inputGroup.type + " & " + inputGroup.name + " [[buffer(" ;
@@ -279,14 +280,23 @@ std::vector<std::pair<std::string, std::string>> TargetMetal::getExtraDefines()
279280 return defines;
280281}
281282
283+ std::uint32_t TargetMetal::getSpirVVersion () const
284+ {
285+ // SPV_EXT_demote_to_helper_invocation is core with SPIRV 1.6, and breaks discard operations
286+ // when targeting Metal < 2.3.
287+ if (m_version < 203 )
288+ return 0x10500 ;
289+ return spv::Version;
290+ }
291+
282292void TargetMetal::willCompile ()
283293{
284294 // Need dummy bindings for internal usage.
285295 setDummyBindings (true );
286296}
287297
288- bool TargetMetal::compileMetal (std::vector<std:: uint8_t >& data, Output& output,
289- const std::string& metal)
298+ bool TargetMetal::compileMetal (
299+ std::vector<std:: uint8_t >& data, Output& output, const std::string& metal)
290300{
291301 // Compile this entry point.
292302 std::stringstream versionStr;
0 commit comments