diff --git a/tools/hlsl_generator/gen.py b/tools/hlsl_generator/gen.py new file mode 100644 index 000000000..2584d023f --- /dev/null +++ b/tools/hlsl_generator/gen.py @@ -0,0 +1,389 @@ +import json +import io +import os +import re +from enum import Enum +from argparse import ArgumentParser +from typing import NamedTuple +from typing import Optional + +head = """// Copyright (C) 2023 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_SPIRV_INTRINSICS_CORE_INCLUDED_ +#define _NBL_BUILTIN_HLSL_SPIRV_INTRINSICS_CORE_INCLUDED_ + +#ifdef __HLSL_VERSION +#include "spirv/unified1/spirv.hpp" +#include "spirv/unified1/GLSL.std.450.h" +#endif + +#include "nbl/builtin/hlsl/type_traits.hlsl" + +namespace nbl +{ +namespace hlsl +{ +#ifdef __HLSL_VERSION +namespace spirv +{ + +//! General Decls +template +struct pointer +{ + using type = vk::SpirvOpaqueType >, T>; +}; +// partial spec for BDA +template +struct pointer +{ + using type = vk::SpirvType >, T>; +}; + +template +using pointer_t = typename pointer::type; + +template +NBL_CONSTEXPR_STATIC_INLINE bool is_pointer_v = is_same_v::type >; + +// The holy operation that makes addrof possible +template +[[vk::ext_instruction(spv::OpCopyObject)]] +pointer_t copyObject([[vk::ext_reference]] T value); + +// TODO: Generate extended instructions +//! Std 450 Extended set instructions +template +[[vk::ext_instruction(34 /* GLSLstd450MatrixInverse */, "GLSL.std.450")]] +SquareMatrix matrixInverse(NBL_CONST_REF_ARG(SquareMatrix) mat); + +//! Memory instructions +template +[[vk::ext_capability(spv::CapabilityPhysicalStorageBufferAddresses)]] +[[vk::ext_instruction(spv::OpLoad)]] +T load(pointer_t pointer, [[vk::ext_literal]] uint32_t __aligned = /*Aligned*/0x00000002, [[vk::ext_literal]] uint32_t __alignment = alignment); + +template +[[vk::ext_instruction(spv::OpLoad)]] +enable_if_t, T> load(P pointer); + +template +[[vk::ext_capability(spv::CapabilityPhysicalStorageBufferAddresses)]] +[[vk::ext_instruction(spv::OpStore)]] +void store(pointer_t pointer, T obj, [[vk::ext_literal]] uint32_t __aligned = /*Aligned*/0x00000002, [[vk::ext_literal]] uint32_t __alignment = alignment); + +template +[[vk::ext_instruction(spv::OpStore)]] +enable_if_t, void> store(P pointer, T obj); + +//! Bitcast Instructions +// Add specializations if you need to emit a `ext_capability` (this means that the instruction needs to forward through an `impl::` struct and so on) +template +[[vk::ext_capability(spv::CapabilityPhysicalStorageBufferAddresses)]] +[[vk::ext_instruction(spv::OpBitcast)]] +enable_if_t, T> bitcast(U); + +template +[[vk::ext_capability(spv::CapabilityPhysicalStorageBufferAddresses)]] +[[vk::ext_instruction(spv::OpBitcast)]] +uint64_t bitcast(pointer_t); + +template +[[vk::ext_capability(spv::CapabilityPhysicalStorageBufferAddresses)]] +[[vk::ext_instruction(spv::OpBitcast)]] +pointer_t bitcast(uint64_t); + +template +[[vk::ext_instruction(spv::OpBitcast)]] +enable_if_t || is_vector_v), T> bitcast(U); +""" + +foot = """} + +#endif +} +} + +#endif +""" + +def gen(core_grammer, glsl_grammer, output_path): + output = open(output_path, "w", buffering=1024**2) + + builtins = [x for x in core_grammer["operand_kinds"] if x["kind"] == "BuiltIn"][0]["enumerants"] + execution_modes = [x for x in core_grammer["operand_kinds"] if x["kind"] == "ExecutionMode"][0]["enumerants"] + group_operations = [x for x in core_grammer["operand_kinds"] if x["kind"] == "GroupOperation"][0]["enumerants"] + + with output as writer: + writer.write(head) + + writer.write("\n//! Builtins\nnamespace builtin\n{\n") + for b in builtins: + b_name = b["enumerant"] + b_type = None + b_cap = None + is_output = False + match b_name: + case "HelperInvocation": b_type = "bool" + case "VertexIndex": b_type = "uint32_t" + case "InstanceIndex": b_type = "uint32_t" + case "NumWorkgroups": b_type = "uint32_t3" + case "WorkgroupId": b_type = "uint32_t3" + case "LocalInvocationId": b_type = "uint32_t3" + case "GlobalInvocationId": b_type = "uint32_t3" + case "LocalInvocationIndex": b_type = "uint32_t" + case "SubgroupEqMask": + b_type = "uint32_t4" + b_cap = "GroupNonUniformBallot" + case "SubgroupGeMask": + b_type = "uint32_t4" + b_cap = "GroupNonUniformBallot" + case "SubgroupGtMask": + b_type = "uint32_t4" + b_cap = "GroupNonUniformBallot" + case "SubgroupLeMask": + b_type = "uint32_t4" + b_cap = "GroupNonUniformBallot" + case "SubgroupLtMask": + b_type = "uint32_t4" + b_cap = "GroupNonUniformBallot" + case "SubgroupSize": + b_type = "uint32_t" + b_cap = "GroupNonUniform" + case "NumSubgroups": + b_type = "uint32_t" + b_cap = "GroupNonUniform" + case "SubgroupId": + b_type = "uint32_t" + b_cap = "GroupNonUniform" + case "SubgroupLocalInvocationId": + b_type = "uint32_t" + b_cap = "GroupNonUniform" + case "Position": + b_type = "float32_t4" + is_output = True + case _: continue + if b_cap != None: + writer.write("[[vk::ext_capability(spv::Capability" + b_cap + ")]]\n") + if is_output: + writer.write("[[vk::ext_builtin_output(spv::BuiltIn" + b_name + ")]]\n") + writer.write("static " + b_type + " " + b_name + ";\n") + else: + writer.write("[[vk::ext_builtin_input(spv::BuiltIn" + b_name + ")]]\n") + writer.write("static const " + b_type + " " + b_name + ";\n\n") + writer.write("}\n") + + writer.write("\n//! Execution Modes\nnamespace execution_mode\n{") + for em in execution_modes: + name = em["enumerant"] + if name.endswith("INTEL"): continue + name_l = name[0].lower() + name[1:] + writer.write("\n\tvoid " + name_l + "()\n\t{\n\t\tvk::ext_execution_mode(spv::ExecutionMode" + name + ");\n\t}\n") + writer.write("}\n") + + writer.write("\n//! Group Operations\nnamespace group_operation\n{\n") + for go in group_operations: + name = go["enumerant"] + value = go["value"] + writer.write("\tstatic const uint32_t " + name + " = " + str(value) + ";\n") + writer.write("}\n") + + writer.write("\n//! Instructions\n") + for instruction in core_grammer["instructions"]: + if instruction["opname"].endswith("INTEL"): continue + + match instruction["class"]: + case "Atomic": + processInst(writer, instruction) + processInst(writer, instruction, Shape.PTR_TEMPLATE) + case "Barrier" | "Bit": + processInst(writer, instruction) + case "Reserved": + match instruction["opname"]: + case "OpBeginInvocationInterlockEXT" | "OpEndInvocationInterlockEXT": + processInst(writer, instruction) + case "Non-Uniform": + match instruction["opname"]: + case "OpGroupNonUniformElect" | "OpGroupNonUniformAll" | "OpGroupNonUniformAny" | "OpGroupNonUniformAllEqual": + processInst(writer, instruction, result_ty="bool") + case "OpGroupNonUniformBallot": + processInst(writer, instruction, result_ty="uint32_t4",prefered_op_ty="bool") + case "OpGroupNonUniformInverseBallot" | "OpGroupNonUniformBallotBitExtract": + processInst(writer, instruction, result_ty="bool",prefered_op_ty="uint32_t4") + case "OpGroupNonUniformBallotBitCount" | "OpGroupNonUniformBallotFindLSB" | "OpGroupNonUniformBallotFindMSB": + processInst(writer, instruction, result_ty="uint32_t",prefered_op_ty="uint32_t4") + case _: processInst(writer, instruction) + case _: continue # TODO + for instruction in glsl_grammer["instructions"]: + instruction["operands"] = [{"kind": "IdResultType"}] + instruction["operands"] + processInst(writer, instruction) + + writer.write(foot) + +class Shape(Enum): + DEFAULT = 0, + PTR_TEMPLATE = 1, # TODO: this is a DXC Workaround + +def processInst(writer: io.TextIOWrapper, + instruction, + shape: Shape = Shape.DEFAULT, + result_ty: Optional[str] = None, + prefered_op_ty: Optional[str] = None): + templates = [] + caps = [] + conds = [] + op_name = instruction["opname"] + fn_name = op_name[2].lower() + op_name[3:] + exts = instruction["extensions"] if "extensions" in instruction else [] + + if "capabilities" in instruction and len(instruction["capabilities"]) > 0: + for cap in instruction["capabilities"]: + if cap == "Kernel" and len(instruction["capabilities"]) == 1: return + if cap == "Shader": continue + caps.append(cap) + + if shape == Shape.PTR_TEMPLATE: + templates.append("typename P") + conds.append("is_spirv_type_v

") + + # split upper case words + matches = [(m.group(1), m.span(1)) for m in re.finditer(r'([A-Z])[A-Z][a-z]', fn_name)] + + for m in matches: + match m[0]: + case "I": + conds.append("(is_signed_v || is_unsigned_v)") + break + case "U": + conds.append("is_unsigned_v") + break + case "S": + conds.append("is_signed_v") + break + case "F": + conds.append("(is_same_v || is_same_v || is_same_v)") + break + else: + if "class" in instruction and instruction["class"] == "Bit": + conds.append("(is_signed_v || is_unsigned_v)") + + if "operands" in instruction and instruction["operands"][0]["kind"] == "IdResultType": + if result_ty == None: + result_ty = "T" + else: + result_ty = "void" + + match result_ty: + case "uint16_t" | "int16_t": caps.append("Int16") + case "uint64_t" | "int64_t": caps.append("Int64") + case "float16_t": caps.append("Float16") + case "float64_t": caps.append("Float64") + + for cap in caps or [None]: + final_fn_name = fn_name + "_" + cap if (len(caps) > 1) else fn_name + final_templates = templates.copy() + + if (not "typename T" in final_templates) and (result_ty == "T"): + final_templates = ["typename T"] + final_templates + + if len(caps) > 0: + if (("Float16" in cap and result_ty != "float16_t") or + ("Float32" in cap and result_ty != "float32_t") or + ("Float64" in cap and result_ty != "float64_t") or + ("Int16" in cap and result_ty != "int16_t" and result_ty != "uint16_t") or + ("Int64" in cap and result_ty != "int64_t" and result_ty != "uint64_t")): continue + + if "Vector" in cap: + result_ty = "vector<" + result_ty + ", N> " + final_templates.append("uint32_t N") + + op_ty = "T" + if prefered_op_ty != None: + op_ty = prefered_op_ty + elif result_ty != "void": + op_ty = result_ty + + args = [] + if "operands" in instruction: + for operand in instruction["operands"]: + operand_name = operand["name"].strip("'") if "name" in operand else None + operand_name = operand_name[0].lower() + operand_name[1:] if (operand_name != None) else "" + match operand["kind"]: + case "IdResult" | "IdResultType": continue + case "IdRef": + match operand["name"]: + case "'Pointer'": + if shape == Shape.PTR_TEMPLATE: + args.append("P " + operand_name) + else: + if (not "typename T" in final_templates) and (result_ty == "T" or op_ty == "T"): + final_templates = ["typename T"] + final_templates + args.append("[[vk::ext_reference]] " + op_ty + " " + operand_name) + case ("'a'" | "'b'" | "'c'" | "'x'" | "'y'" | "'z'" | "'i'" | "'v'" | + "'p'" | "'p0'" | "'p1'" | "'exp'" | "'minVal'" | "'maxVal'" | "'y_over_x'" | + "'edge'" | "'edge0'" | "'edge1'" | "'I'" | "'N'" | "'eta'" | "'sample'" | + "'degrees'" | "'radians'" | "'Nref'" | "'interpolant'" | "'offset'" | + "'Value'" | "'Object'" | "'Comparator'" | "'Base'" | "'Insert'"): + if (not "typename T" in final_templates) and (result_ty == "T" or op_ty == "T"): + final_templates = ["typename T"] + final_templates + args.append(op_ty + " " + operand_name) + case "'Offset'" | "'Count'" | "'Id'" | "'Index'" | "'Mask'" | "'Delta'": + args.append("uint32_t " + operand_name) + case "'Predicate'": args.append("bool " + operand_name) + case "'ClusterSize'": + if "quantifier" in operand and operand["quantifier"] == "?": continue # TODO: overload + else: return ignore(op_name) # TODO + case _: return ignore(op_name) # TODO + case "IdScope": args.append("uint32_t " + operand_name.lower() + "Scope") + case "IdMemorySemantics": args.append(" uint32_t " + operand_name) + case "GroupOperation": args.append("[[vk::ext_literal]] uint32_t " + operand_name) + case "MemoryAccess": + assert len(caps) <= 1 + writeInst(writer, final_templates, cap, exts, op_name, final_fn_name, conds, result_ty, args + ["[[vk::ext_literal]] uint32_t memoryAccess"]) + writeInst(writer, final_templates, cap, exts, op_name, final_fn_name, conds, result_ty, args + ["[[vk::ext_literal]] uint32_t memoryAccess, [[vk::ext_literal]] uint32_t memoryAccessParam"]) + case _: return ignore(op_name) # TODO + + writeInst(writer, final_templates, cap, exts, op_name, final_fn_name, conds, result_ty, args) + + +def writeInst(writer: io.TextIOWrapper, templates, cap, exts, op_name, fn_name, conds, result_type, args): + if len(templates) > 0: + writer.write("template<" + ", ".join(templates) + ">\n") + if cap != None: + writer.write("[[vk::ext_capability(spv::Capability" + cap + ")]]\n") + for ext in exts: + writer.write("[[vk::ext_extension(\"" + ext + "\")]]\n") + writer.write("[[vk::ext_instruction(spv::" + op_name + ")]]\n") + if len(conds) > 0: + writer.write("enable_if_t<" + " && ".join(conds) + ", " + result_type + ">") + else: + writer.write(result_type) + writer.write(" " + fn_name + "(" + ", ".join(args) + ");\n\n") + +def ignore(op_name): + print("\033[94mIGNORED\033[0m: " + op_name) + +if __name__ == "__main__": + script_dir_path = os.path.abspath(os.path.dirname(__file__)) + + parser = ArgumentParser(description="Generate HLSL from SPIR-V instructions") + parser.add_argument("output", type=str, help="HLSL output file") + parser.add_argument("--core-grammer", required=False, type=str, + help="SPIR-V Core grammer JSON file", + default=os.path.join(script_dir_path, "../../include/spirv/unified1/spirv.core.grammar.json")) + parser.add_argument("--glsl-grammer", required=False, type=str, + help="SPIR-V Extended GLSL.std.450 grammer JSON file", + default=os.path.join(script_dir_path, "../../include/spirv/unified1/extinst.glsl.std.450.grammar.json")) + args = parser.parse_args() + + grammer_raw = open(args.core_grammer, "r").read() + core_grammer = json.loads(grammer_raw) + del grammer_raw + + grammer_raw = open(args.glsl_grammer, "r").read() + glsl_grammer = json.loads(grammer_raw) + del grammer_raw + + gen(core_grammer, glsl_grammer, args.output) + diff --git a/tools/hlsl_generator/out.hlsl b/tools/hlsl_generator/out.hlsl new file mode 100644 index 000000000..729f04b20 --- /dev/null +++ b/tools/hlsl_generator/out.hlsl @@ -0,0 +1,1407 @@ +// Copyright (C) 2023 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h +#ifndef _NBL_BUILTIN_HLSL_SPIRV_INTRINSICS_CORE_INCLUDED_ +#define _NBL_BUILTIN_HLSL_SPIRV_INTRINSICS_CORE_INCLUDED_ + +#ifdef __HLSL_VERSION +#include "spirv/unified1/spirv.hpp" +#include "spirv/unified1/GLSL.std.450.h" +#endif + +#include "nbl/builtin/hlsl/type_traits.hlsl" + +namespace nbl +{ +namespace hlsl +{ +#ifdef __HLSL_VERSION +namespace spirv +{ + +//! General Decls +template +struct pointer +{ + using type = vk::SpirvOpaqueType >, T>; +}; +// partial spec for BDA +template +struct pointer +{ + using type = vk::SpirvType >, T>; +}; + +template +using pointer_t = typename pointer::type; + +template +NBL_CONSTEXPR_STATIC_INLINE bool is_pointer_v = is_same_v::type >; + +// The holy operation that makes addrof possible +template +[[vk::ext_instruction(spv::OpCopyObject)]] +pointer_t copyObject([[vk::ext_reference]] T value); + +// TODO: Generate extended instructions +//! Std 450 Extended set instructions +template +[[vk::ext_instruction(34 /* GLSLstd450MatrixInverse */, "GLSL.std.450")]] +SquareMatrix matrixInverse(NBL_CONST_REF_ARG(SquareMatrix) mat); + +//! Memory instructions +template +[[vk::ext_capability(spv::CapabilityPhysicalStorageBufferAddresses)]] +[[vk::ext_instruction(spv::OpLoad)]] +T load(pointer_t pointer, [[vk::ext_literal]] uint32_t __aligned = /*Aligned*/0x00000002, [[vk::ext_literal]] uint32_t __alignment = alignment); + +template +[[vk::ext_instruction(spv::OpLoad)]] +enable_if_t, T> load(P pointer); + +template +[[vk::ext_capability(spv::CapabilityPhysicalStorageBufferAddresses)]] +[[vk::ext_instruction(spv::OpStore)]] +void store(pointer_t pointer, T obj, [[vk::ext_literal]] uint32_t __aligned = /*Aligned*/0x00000002, [[vk::ext_literal]] uint32_t __alignment = alignment); + +template +[[vk::ext_instruction(spv::OpStore)]] +enable_if_t, void> store(P pointer, T obj); + +//! Bitcast Instructions +// Add specializations if you need to emit a `ext_capability` (this means that the instruction needs to forward through an `impl::` struct and so on) +template +[[vk::ext_capability(spv::CapabilityPhysicalStorageBufferAddresses)]] +[[vk::ext_instruction(spv::OpBitcast)]] +enable_if_t, T> bitcast(U); + +template +[[vk::ext_capability(spv::CapabilityPhysicalStorageBufferAddresses)]] +[[vk::ext_instruction(spv::OpBitcast)]] +uint64_t bitcast(pointer_t); + +template +[[vk::ext_capability(spv::CapabilityPhysicalStorageBufferAddresses)]] +[[vk::ext_instruction(spv::OpBitcast)]] +pointer_t bitcast(uint64_t); + +template +[[vk::ext_instruction(spv::OpBitcast)]] +enable_if_t || is_vector_v), T> bitcast(U); + +//! Builtins +namespace builtin +{ +[[vk::ext_builtin_output(spv::BuiltInPosition)]] +static float32_t4 Position; +[[vk::ext_builtin_input(spv::BuiltInHelperInvocation)]] +static const bool HelperInvocation; + +[[vk::ext_builtin_input(spv::BuiltInNumWorkgroups)]] +static const uint32_t3 NumWorkgroups; + +[[vk::ext_builtin_input(spv::BuiltInWorkgroupId)]] +static const uint32_t3 WorkgroupId; + +[[vk::ext_builtin_input(spv::BuiltInLocalInvocationId)]] +static const uint32_t3 LocalInvocationId; + +[[vk::ext_builtin_input(spv::BuiltInGlobalInvocationId)]] +static const uint32_t3 GlobalInvocationId; + +[[vk::ext_builtin_input(spv::BuiltInLocalInvocationIndex)]] +static const uint32_t LocalInvocationIndex; + +[[vk::ext_capability(spv::CapabilityGroupNonUniform)]] +[[vk::ext_builtin_input(spv::BuiltInSubgroupSize)]] +static const uint32_t SubgroupSize; + +[[vk::ext_capability(spv::CapabilityGroupNonUniform)]] +[[vk::ext_builtin_input(spv::BuiltInNumSubgroups)]] +static const uint32_t NumSubgroups; + +[[vk::ext_capability(spv::CapabilityGroupNonUniform)]] +[[vk::ext_builtin_input(spv::BuiltInSubgroupId)]] +static const uint32_t SubgroupId; + +[[vk::ext_capability(spv::CapabilityGroupNonUniform)]] +[[vk::ext_builtin_input(spv::BuiltInSubgroupLocalInvocationId)]] +static const uint32_t SubgroupLocalInvocationId; + +[[vk::ext_builtin_input(spv::BuiltInVertexIndex)]] +static const uint32_t VertexIndex; + +[[vk::ext_builtin_input(spv::BuiltInInstanceIndex)]] +static const uint32_t InstanceIndex; + +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_builtin_input(spv::BuiltInSubgroupEqMask)]] +static const uint32_t4 SubgroupEqMask; + +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_builtin_input(spv::BuiltInSubgroupGeMask)]] +static const uint32_t4 SubgroupGeMask; + +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_builtin_input(spv::BuiltInSubgroupGtMask)]] +static const uint32_t4 SubgroupGtMask; + +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_builtin_input(spv::BuiltInSubgroupLeMask)]] +static const uint32_t4 SubgroupLeMask; + +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_builtin_input(spv::BuiltInSubgroupLtMask)]] +static const uint32_t4 SubgroupLtMask; + +} + +//! Execution Modes +namespace execution_mode +{ + void invocations() + { + vk::ext_execution_mode(spv::ExecutionModeInvocations); + } + + void spacingEqual() + { + vk::ext_execution_mode(spv::ExecutionModeSpacingEqual); + } + + void spacingFractionalEven() + { + vk::ext_execution_mode(spv::ExecutionModeSpacingFractionalEven); + } + + void spacingFractionalOdd() + { + vk::ext_execution_mode(spv::ExecutionModeSpacingFractionalOdd); + } + + void vertexOrderCw() + { + vk::ext_execution_mode(spv::ExecutionModeVertexOrderCw); + } + + void vertexOrderCcw() + { + vk::ext_execution_mode(spv::ExecutionModeVertexOrderCcw); + } + + void pixelCenterInteger() + { + vk::ext_execution_mode(spv::ExecutionModePixelCenterInteger); + } + + void originUpperLeft() + { + vk::ext_execution_mode(spv::ExecutionModeOriginUpperLeft); + } + + void originLowerLeft() + { + vk::ext_execution_mode(spv::ExecutionModeOriginLowerLeft); + } + + void earlyFragmentTests() + { + vk::ext_execution_mode(spv::ExecutionModeEarlyFragmentTests); + } + + void pointMode() + { + vk::ext_execution_mode(spv::ExecutionModePointMode); + } + + void xfb() + { + vk::ext_execution_mode(spv::ExecutionModeXfb); + } + + void depthReplacing() + { + vk::ext_execution_mode(spv::ExecutionModeDepthReplacing); + } + + void depthGreater() + { + vk::ext_execution_mode(spv::ExecutionModeDepthGreater); + } + + void depthLess() + { + vk::ext_execution_mode(spv::ExecutionModeDepthLess); + } + + void depthUnchanged() + { + vk::ext_execution_mode(spv::ExecutionModeDepthUnchanged); + } + + void localSize() + { + vk::ext_execution_mode(spv::ExecutionModeLocalSize); + } + + void localSizeHint() + { + vk::ext_execution_mode(spv::ExecutionModeLocalSizeHint); + } + + void inputPoints() + { + vk::ext_execution_mode(spv::ExecutionModeInputPoints); + } + + void inputLines() + { + vk::ext_execution_mode(spv::ExecutionModeInputLines); + } + + void inputLinesAdjacency() + { + vk::ext_execution_mode(spv::ExecutionModeInputLinesAdjacency); + } + + void triangles() + { + vk::ext_execution_mode(spv::ExecutionModeTriangles); + } + + void inputTrianglesAdjacency() + { + vk::ext_execution_mode(spv::ExecutionModeInputTrianglesAdjacency); + } + + void quads() + { + vk::ext_execution_mode(spv::ExecutionModeQuads); + } + + void isolines() + { + vk::ext_execution_mode(spv::ExecutionModeIsolines); + } + + void outputVertices() + { + vk::ext_execution_mode(spv::ExecutionModeOutputVertices); + } + + void outputPoints() + { + vk::ext_execution_mode(spv::ExecutionModeOutputPoints); + } + + void outputLineStrip() + { + vk::ext_execution_mode(spv::ExecutionModeOutputLineStrip); + } + + void outputTriangleStrip() + { + vk::ext_execution_mode(spv::ExecutionModeOutputTriangleStrip); + } + + void vecTypeHint() + { + vk::ext_execution_mode(spv::ExecutionModeVecTypeHint); + } + + void contractionOff() + { + vk::ext_execution_mode(spv::ExecutionModeContractionOff); + } + + void initializer() + { + vk::ext_execution_mode(spv::ExecutionModeInitializer); + } + + void finalizer() + { + vk::ext_execution_mode(spv::ExecutionModeFinalizer); + } + + void subgroupSize() + { + vk::ext_execution_mode(spv::ExecutionModeSubgroupSize); + } + + void subgroupsPerWorkgroup() + { + vk::ext_execution_mode(spv::ExecutionModeSubgroupsPerWorkgroup); + } + + void subgroupsPerWorkgroupId() + { + vk::ext_execution_mode(spv::ExecutionModeSubgroupsPerWorkgroupId); + } + + void localSizeId() + { + vk::ext_execution_mode(spv::ExecutionModeLocalSizeId); + } + + void localSizeHintId() + { + vk::ext_execution_mode(spv::ExecutionModeLocalSizeHintId); + } + + void nonCoherentColorAttachmentReadEXT() + { + vk::ext_execution_mode(spv::ExecutionModeNonCoherentColorAttachmentReadEXT); + } + + void nonCoherentDepthAttachmentReadEXT() + { + vk::ext_execution_mode(spv::ExecutionModeNonCoherentDepthAttachmentReadEXT); + } + + void nonCoherentStencilAttachmentReadEXT() + { + vk::ext_execution_mode(spv::ExecutionModeNonCoherentStencilAttachmentReadEXT); + } + + void subgroupUniformControlFlowKHR() + { + vk::ext_execution_mode(spv::ExecutionModeSubgroupUniformControlFlowKHR); + } + + void postDepthCoverage() + { + vk::ext_execution_mode(spv::ExecutionModePostDepthCoverage); + } + + void denormPreserve() + { + vk::ext_execution_mode(spv::ExecutionModeDenormPreserve); + } + + void denormFlushToZero() + { + vk::ext_execution_mode(spv::ExecutionModeDenormFlushToZero); + } + + void signedZeroInfNanPreserve() + { + vk::ext_execution_mode(spv::ExecutionModeSignedZeroInfNanPreserve); + } + + void roundingModeRTE() + { + vk::ext_execution_mode(spv::ExecutionModeRoundingModeRTE); + } + + void roundingModeRTZ() + { + vk::ext_execution_mode(spv::ExecutionModeRoundingModeRTZ); + } + + void earlyAndLateFragmentTestsAMD() + { + vk::ext_execution_mode(spv::ExecutionModeEarlyAndLateFragmentTestsAMD); + } + + void stencilRefReplacingEXT() + { + vk::ext_execution_mode(spv::ExecutionModeStencilRefReplacingEXT); + } + + void coalescingAMDX() + { + vk::ext_execution_mode(spv::ExecutionModeCoalescingAMDX); + } + + void maxNodeRecursionAMDX() + { + vk::ext_execution_mode(spv::ExecutionModeMaxNodeRecursionAMDX); + } + + void staticNumWorkgroupsAMDX() + { + vk::ext_execution_mode(spv::ExecutionModeStaticNumWorkgroupsAMDX); + } + + void shaderIndexAMDX() + { + vk::ext_execution_mode(spv::ExecutionModeShaderIndexAMDX); + } + + void maxNumWorkgroupsAMDX() + { + vk::ext_execution_mode(spv::ExecutionModeMaxNumWorkgroupsAMDX); + } + + void stencilRefUnchangedFrontAMD() + { + vk::ext_execution_mode(spv::ExecutionModeStencilRefUnchangedFrontAMD); + } + + void stencilRefGreaterFrontAMD() + { + vk::ext_execution_mode(spv::ExecutionModeStencilRefGreaterFrontAMD); + } + + void stencilRefLessFrontAMD() + { + vk::ext_execution_mode(spv::ExecutionModeStencilRefLessFrontAMD); + } + + void stencilRefUnchangedBackAMD() + { + vk::ext_execution_mode(spv::ExecutionModeStencilRefUnchangedBackAMD); + } + + void stencilRefGreaterBackAMD() + { + vk::ext_execution_mode(spv::ExecutionModeStencilRefGreaterBackAMD); + } + + void stencilRefLessBackAMD() + { + vk::ext_execution_mode(spv::ExecutionModeStencilRefLessBackAMD); + } + + void quadDerivativesKHR() + { + vk::ext_execution_mode(spv::ExecutionModeQuadDerivativesKHR); + } + + void requireFullQuadsKHR() + { + vk::ext_execution_mode(spv::ExecutionModeRequireFullQuadsKHR); + } + + void outputLinesEXT() + { + vk::ext_execution_mode(spv::ExecutionModeOutputLinesEXT); + } + + void outputLinesNV() + { + vk::ext_execution_mode(spv::ExecutionModeOutputLinesNV); + } + + void outputPrimitivesEXT() + { + vk::ext_execution_mode(spv::ExecutionModeOutputPrimitivesEXT); + } + + void outputPrimitivesNV() + { + vk::ext_execution_mode(spv::ExecutionModeOutputPrimitivesNV); + } + + void derivativeGroupQuadsNV() + { + vk::ext_execution_mode(spv::ExecutionModeDerivativeGroupQuadsNV); + } + + void derivativeGroupLinearNV() + { + vk::ext_execution_mode(spv::ExecutionModeDerivativeGroupLinearNV); + } + + void outputTrianglesEXT() + { + vk::ext_execution_mode(spv::ExecutionModeOutputTrianglesEXT); + } + + void outputTrianglesNV() + { + vk::ext_execution_mode(spv::ExecutionModeOutputTrianglesNV); + } + + void pixelInterlockOrderedEXT() + { + vk::ext_execution_mode(spv::ExecutionModePixelInterlockOrderedEXT); + } + + void pixelInterlockUnorderedEXT() + { + vk::ext_execution_mode(spv::ExecutionModePixelInterlockUnorderedEXT); + } + + void sampleInterlockOrderedEXT() + { + vk::ext_execution_mode(spv::ExecutionModeSampleInterlockOrderedEXT); + } + + void sampleInterlockUnorderedEXT() + { + vk::ext_execution_mode(spv::ExecutionModeSampleInterlockUnorderedEXT); + } + + void shadingRateInterlockOrderedEXT() + { + vk::ext_execution_mode(spv::ExecutionModeShadingRateInterlockOrderedEXT); + } + + void shadingRateInterlockUnorderedEXT() + { + vk::ext_execution_mode(spv::ExecutionModeShadingRateInterlockUnorderedEXT); + } + + void maximallyReconvergesKHR() + { + vk::ext_execution_mode(spv::ExecutionModeMaximallyReconvergesKHR); + } + + void fPFastMathDefault() + { + vk::ext_execution_mode(spv::ExecutionModeFPFastMathDefault); + } +} + +//! Group Operations +namespace group_operation +{ + static const uint32_t Reduce = 0; + static const uint32_t InclusiveScan = 1; + static const uint32_t ExclusiveScan = 2; + static const uint32_t ClusteredReduce = 3; + static const uint32_t PartitionedReduceNV = 6; + static const uint32_t PartitionedInclusiveScanNV = 7; + static const uint32_t PartitionedExclusiveScanNV = 8; +} + +//! Instructions +template +[[vk::ext_capability(spv::CapabilityBitInstructions)]] +[[vk::ext_instruction(spv::OpBitFieldInsert)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> bitFieldInsert(T base, T insert, uint32_t offset, uint32_t count); + +template +[[vk::ext_capability(spv::CapabilityBitInstructions)]] +[[vk::ext_instruction(spv::OpBitFieldSExtract)]] +enable_if_t, T> bitFieldSExtract(T base, uint32_t offset, uint32_t count); + +template +[[vk::ext_capability(spv::CapabilityBitInstructions)]] +[[vk::ext_instruction(spv::OpBitFieldUExtract)]] +enable_if_t, T> bitFieldUExtract(T base, uint32_t offset, uint32_t count); + +template +[[vk::ext_capability(spv::CapabilityBitInstructions)]] +[[vk::ext_instruction(spv::OpBitReverse)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> bitReverse(T base); + +template +[[vk::ext_instruction(spv::OpBitCount)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> bitCount(T base); + +[[vk::ext_instruction(spv::OpControlBarrier)]] +void controlBarrier(uint32_t executionScope, uint32_t memoryScope, uint32_t semantics); + +[[vk::ext_instruction(spv::OpMemoryBarrier)]] +void memoryBarrier(uint32_t memoryScope, uint32_t semantics); + +template +[[vk::ext_instruction(spv::OpAtomicLoad)]] +T atomicLoad([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics); + +template +[[vk::ext_instruction(spv::OpAtomicLoad)]] +enable_if_t, T> atomicLoad(P pointer, uint32_t memoryScope, uint32_t semantics); + +template +[[vk::ext_instruction(spv::OpAtomicStore)]] +void atomicStore([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicStore)]] +enable_if_t, void> atomicStore(P pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicExchange)]] +T atomicExchange([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicExchange)]] +enable_if_t, T> atomicExchange(P pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicCompareExchange)]] +T atomicCompareExchange([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t equal, uint32_t unequal, T value, T comparator); + +template +[[vk::ext_instruction(spv::OpAtomicCompareExchange)]] +enable_if_t, T> atomicCompareExchange(P pointer, uint32_t memoryScope, uint32_t equal, uint32_t unequal, T value, T comparator); + +template +[[vk::ext_instruction(spv::OpAtomicIIncrement)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> atomicIIncrement([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics); + +template +[[vk::ext_instruction(spv::OpAtomicIIncrement)]] +enable_if_t && (is_signed_v || is_unsigned_v), T> atomicIIncrement(P pointer, uint32_t memoryScope, uint32_t semantics); + +template +[[vk::ext_instruction(spv::OpAtomicIDecrement)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> atomicIDecrement([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics); + +template +[[vk::ext_instruction(spv::OpAtomicIDecrement)]] +enable_if_t && (is_signed_v || is_unsigned_v), T> atomicIDecrement(P pointer, uint32_t memoryScope, uint32_t semantics); + +template +[[vk::ext_instruction(spv::OpAtomicIAdd)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> atomicIAdd([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicIAdd)]] +enable_if_t && (is_signed_v || is_unsigned_v), T> atomicIAdd(P pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicISub)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> atomicISub([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicISub)]] +enable_if_t && (is_signed_v || is_unsigned_v), T> atomicISub(P pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicSMin)]] +enable_if_t, T> atomicSMin([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicSMin)]] +enable_if_t && is_signed_v, T> atomicSMin(P pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicUMin)]] +enable_if_t, T> atomicUMin([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicUMin)]] +enable_if_t && is_unsigned_v, T> atomicUMin(P pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicSMax)]] +enable_if_t, T> atomicSMax([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicSMax)]] +enable_if_t && is_signed_v, T> atomicSMax(P pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicUMax)]] +enable_if_t, T> atomicUMax([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicUMax)]] +enable_if_t && is_unsigned_v, T> atomicUMax(P pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicAnd)]] +T atomicAnd([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicAnd)]] +enable_if_t, T> atomicAnd(P pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicOr)]] +T atomicOr([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicOr)]] +enable_if_t, T> atomicOr(P pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicXor)]] +T atomicXor([[vk::ext_reference]] T pointer, uint32_t memoryScope, uint32_t semantics, T value); + +template +[[vk::ext_instruction(spv::OpAtomicXor)]] +enable_if_t, T> atomicXor(P pointer, uint32_t memoryScope, uint32_t semantics, T value); + +[[vk::ext_capability(spv::CapabilityGroupNonUniform)]] +[[vk::ext_instruction(spv::OpGroupNonUniformElect)]] +bool groupNonUniformElect(uint32_t executionScope); + +[[vk::ext_capability(spv::CapabilityGroupNonUniformVote)]] +[[vk::ext_instruction(spv::OpGroupNonUniformAll)]] +bool groupNonUniformAll(uint32_t executionScope, bool predicate); + +[[vk::ext_capability(spv::CapabilityGroupNonUniformVote)]] +[[vk::ext_instruction(spv::OpGroupNonUniformAny)]] +bool groupNonUniformAny(uint32_t executionScope, bool predicate); + +[[vk::ext_capability(spv::CapabilityGroupNonUniformVote)]] +[[vk::ext_instruction(spv::OpGroupNonUniformAllEqual)]] +bool groupNonUniformAllEqual(uint32_t executionScope, bool value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBroadcast)]] +T groupNonUniformBroadcast(uint32_t executionScope, T value, uint32_t id); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBroadcastFirst)]] +T groupNonUniformBroadcastFirst(uint32_t executionScope, T value); + +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBallot)]] +uint32_t4 groupNonUniformBallot(uint32_t executionScope, bool predicate); + +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_instruction(spv::OpGroupNonUniformInverseBallot)]] +bool groupNonUniformInverseBallot(uint32_t executionScope, uint32_t4 value); + +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBallotBitExtract)]] +bool groupNonUniformBallotBitExtract(uint32_t executionScope, uint32_t4 value, uint32_t index); + +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBallotBitCount)]] +uint32_t groupNonUniformBallotBitCount(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, uint32_t4 value); + +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBallotFindLSB)]] +uint32_t groupNonUniformBallotFindLSB(uint32_t executionScope, uint32_t4 value); + +[[vk::ext_capability(spv::CapabilityGroupNonUniformBallot)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBallotFindMSB)]] +uint32_t groupNonUniformBallotFindMSB(uint32_t executionScope, uint32_t4 value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformShuffle)]] +[[vk::ext_instruction(spv::OpGroupNonUniformShuffle)]] +T groupNonUniformShuffle(uint32_t executionScope, T value, uint32_t id); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformShuffle)]] +[[vk::ext_instruction(spv::OpGroupNonUniformShuffleXor)]] +T groupNonUniformShuffleXor(uint32_t executionScope, T value, uint32_t mask); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformShuffleRelative)]] +[[vk::ext_instruction(spv::OpGroupNonUniformShuffleUp)]] +T groupNonUniformShuffleUp(uint32_t executionScope, T value, uint32_t delta); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformShuffleRelative)]] +[[vk::ext_instruction(spv::OpGroupNonUniformShuffleDown)]] +T groupNonUniformShuffleDown(uint32_t executionScope, T value, uint32_t delta); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformIAdd)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> groupNonUniformIAdd_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformIAdd)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> groupNonUniformIAdd_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformIAdd)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> groupNonUniformIAdd_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFAdd)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFAdd_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFAdd)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFAdd_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFAdd)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFAdd_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformIMul)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> groupNonUniformIMul_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformIMul)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> groupNonUniformIMul_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformIMul)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> groupNonUniformIMul_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFMul)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFMul_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFMul)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFMul_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFMul)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFMul_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformSMin)]] +enable_if_t, T> groupNonUniformSMin_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformSMin)]] +enable_if_t, T> groupNonUniformSMin_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformSMin)]] +enable_if_t, T> groupNonUniformSMin_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformUMin)]] +enable_if_t, T> groupNonUniformUMin_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformUMin)]] +enable_if_t, T> groupNonUniformUMin_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformUMin)]] +enable_if_t, T> groupNonUniformUMin_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFMin)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFMin_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFMin)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFMin_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFMin)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFMin_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformSMax)]] +enable_if_t, T> groupNonUniformSMax_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformSMax)]] +enable_if_t, T> groupNonUniformSMax_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformSMax)]] +enable_if_t, T> groupNonUniformSMax_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformUMax)]] +enable_if_t, T> groupNonUniformUMax_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformUMax)]] +enable_if_t, T> groupNonUniformUMax_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformUMax)]] +enable_if_t, T> groupNonUniformUMax_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFMax)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFMax_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFMax)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFMax_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformFMax)]] +enable_if_t<(is_same_v || is_same_v || is_same_v), T> groupNonUniformFMax_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBitwiseAnd)]] +T groupNonUniformBitwiseAnd_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBitwiseAnd)]] +T groupNonUniformBitwiseAnd_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBitwiseAnd)]] +T groupNonUniformBitwiseAnd_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBitwiseOr)]] +T groupNonUniformBitwiseOr_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBitwiseOr)]] +T groupNonUniformBitwiseOr_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBitwiseOr)]] +T groupNonUniformBitwiseOr_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBitwiseXor)]] +T groupNonUniformBitwiseXor_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBitwiseXor)]] +T groupNonUniformBitwiseXor_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformBitwiseXor)]] +T groupNonUniformBitwiseXor_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformLogicalAnd)]] +T groupNonUniformLogicalAnd_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformLogicalAnd)]] +T groupNonUniformLogicalAnd_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformLogicalAnd)]] +T groupNonUniformLogicalAnd_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformLogicalOr)]] +T groupNonUniformLogicalOr_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformLogicalOr)]] +T groupNonUniformLogicalOr_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformLogicalOr)]] +T groupNonUniformLogicalOr_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformArithmetic)]] +[[vk::ext_instruction(spv::OpGroupNonUniformLogicalXor)]] +T groupNonUniformLogicalXor_GroupNonUniformArithmetic(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformClustered)]] +[[vk::ext_instruction(spv::OpGroupNonUniformLogicalXor)]] +T groupNonUniformLogicalXor_GroupNonUniformClustered(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_instruction(spv::OpGroupNonUniformLogicalXor)]] +T groupNonUniformLogicalXor_GroupNonUniformPartitionedNV(uint32_t executionScope, [[vk::ext_literal]] uint32_t operation, T value); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformQuad)]] +[[vk::ext_instruction(spv::OpGroupNonUniformQuadBroadcast)]] +T groupNonUniformQuadBroadcast(uint32_t executionScope, T value, uint32_t index); + +template +[[vk::ext_capability(spv::CapabilityQuadControlKHR)]] +[[vk::ext_instruction(spv::OpGroupNonUniformQuadAllKHR)]] +T groupNonUniformQuadAllKHR(bool predicate); + +template +[[vk::ext_capability(spv::CapabilityQuadControlKHR)]] +[[vk::ext_instruction(spv::OpGroupNonUniformQuadAnyKHR)]] +T groupNonUniformQuadAnyKHR(bool predicate); + +template +[[vk::ext_capability(spv::CapabilityGroupNonUniformPartitionedNV)]] +[[vk::ext_extension("SPV_NV_shader_subgroup_partitioned")]] +[[vk::ext_instruction(spv::OpGroupNonUniformPartitionNV)]] +T groupNonUniformPartitionNV(T value); + +[[vk::ext_capability(spv::CapabilityFragmentShaderSampleInterlockEXT)]] +[[vk::ext_extension("SPV_EXT_fragment_shader_interlock")]] +[[vk::ext_instruction(spv::OpBeginInvocationInterlockEXT)]] +void beginInvocationInterlockEXT_FragmentShaderSampleInterlockEXT(); + +[[vk::ext_capability(spv::CapabilityFragmentShaderPixelInterlockEXT)]] +[[vk::ext_extension("SPV_EXT_fragment_shader_interlock")]] +[[vk::ext_instruction(spv::OpBeginInvocationInterlockEXT)]] +void beginInvocationInterlockEXT_FragmentShaderPixelInterlockEXT(); + +[[vk::ext_capability(spv::CapabilityFragmentShaderShadingRateInterlockEXT)]] +[[vk::ext_extension("SPV_EXT_fragment_shader_interlock")]] +[[vk::ext_instruction(spv::OpBeginInvocationInterlockEXT)]] +void beginInvocationInterlockEXT_FragmentShaderShadingRateInterlockEXT(); + +[[vk::ext_capability(spv::CapabilityFragmentShaderSampleInterlockEXT)]] +[[vk::ext_extension("SPV_EXT_fragment_shader_interlock")]] +[[vk::ext_instruction(spv::OpEndInvocationInterlockEXT)]] +void endInvocationInterlockEXT_FragmentShaderSampleInterlockEXT(); + +[[vk::ext_capability(spv::CapabilityFragmentShaderPixelInterlockEXT)]] +[[vk::ext_extension("SPV_EXT_fragment_shader_interlock")]] +[[vk::ext_instruction(spv::OpEndInvocationInterlockEXT)]] +void endInvocationInterlockEXT_FragmentShaderPixelInterlockEXT(); + +[[vk::ext_capability(spv::CapabilityFragmentShaderShadingRateInterlockEXT)]] +[[vk::ext_extension("SPV_EXT_fragment_shader_interlock")]] +[[vk::ext_instruction(spv::OpEndInvocationInterlockEXT)]] +void endInvocationInterlockEXT_FragmentShaderShadingRateInterlockEXT(); + +template +[[vk::ext_instruction(spv::Round)]] +T und(T x); + +template +[[vk::ext_instruction(spv::RoundEven)]] +T undEven(T x); + +template +[[vk::ext_instruction(spv::Trunc)]] +T unc(T x); + +template +[[vk::ext_instruction(spv::FAbs)]] +T bs(T x); + +template +[[vk::ext_instruction(spv::SAbs)]] +T bs(T x); + +template +[[vk::ext_instruction(spv::FSign)]] +T ign(T x); + +template +[[vk::ext_instruction(spv::SSign)]] +T ign(T x); + +template +[[vk::ext_instruction(spv::Floor)]] +T oor(T x); + +template +[[vk::ext_instruction(spv::Ceil)]] +T il(T x); + +template +[[vk::ext_instruction(spv::Fract)]] +T act(T x); + +template +[[vk::ext_instruction(spv::Radians)]] +T dians(T degrees); + +template +[[vk::ext_instruction(spv::Degrees)]] +T grees(T radians); + +template +[[vk::ext_instruction(spv::Sin)]] +T n(T x); + +template +[[vk::ext_instruction(spv::Cos)]] +T s(T x); + +template +[[vk::ext_instruction(spv::Tan)]] +T n(T x); + +template +[[vk::ext_instruction(spv::Asin)]] +T in(T x); + +template +[[vk::ext_instruction(spv::Acos)]] +T os(T x); + +template +[[vk::ext_instruction(spv::Atan)]] +T an(T y_over_x); + +template +[[vk::ext_instruction(spv::Sinh)]] +T nh(T x); + +template +[[vk::ext_instruction(spv::Cosh)]] +T sh(T x); + +template +[[vk::ext_instruction(spv::Tanh)]] +T nh(T x); + +template +[[vk::ext_instruction(spv::Asinh)]] +T inh(T x); + +template +[[vk::ext_instruction(spv::Acosh)]] +T osh(T x); + +template +[[vk::ext_instruction(spv::Atanh)]] +T anh(T x); + +template +[[vk::ext_instruction(spv::Atan2)]] +T an2(T y, T x); + +template +[[vk::ext_instruction(spv::Pow)]] +T w(T x, T y); + +template +[[vk::ext_instruction(spv::Exp)]] +T p(T x); + +template +[[vk::ext_instruction(spv::Log)]] +T g(T x); + +template +[[vk::ext_instruction(spv::Exp2)]] +T p2(T x); + +template +[[vk::ext_instruction(spv::Log2)]] +T g2(T x); + +template +[[vk::ext_instruction(spv::Sqrt)]] +T rt(T x); + +template +[[vk::ext_instruction(spv::InverseSqrt)]] +T verseSqrt(T x); + +template +[[vk::ext_instruction(spv::Determinant)]] +T terminant(T x); + +template +[[vk::ext_instruction(spv::MatrixInverse)]] +T trixInverse(T x); + +template +[[vk::ext_instruction(spv::Modf)]] +T df(T x, T i); + +template +[[vk::ext_instruction(spv::ModfStruct)]] +T dfStruct(T x); + +template +[[vk::ext_instruction(spv::FMin)]] +T in(T x, T y); + +template +[[vk::ext_instruction(spv::UMin)]] +T in(T x, T y); + +template +[[vk::ext_instruction(spv::SMin)]] +T in(T x, T y); + +template +[[vk::ext_instruction(spv::FMax)]] +T ax(T x, T y); + +template +[[vk::ext_instruction(spv::UMax)]] +T ax(T x, T y); + +template +[[vk::ext_instruction(spv::SMax)]] +T ax(T x, T y); + +template +[[vk::ext_instruction(spv::FClamp)]] +T lamp(T x, T minVal, T maxVal); + +template +[[vk::ext_instruction(spv::UClamp)]] +T lamp(T x, T minVal, T maxVal); + +template +[[vk::ext_instruction(spv::SClamp)]] +T lamp(T x, T minVal, T maxVal); + +template +[[vk::ext_instruction(spv::FMix)]] +T ix(T x, T y, T a); + +template +[[vk::ext_instruction(spv::IMix)]] +T ix(T x, T y, T a); + +template +[[vk::ext_instruction(spv::Step)]] +T ep(T edge, T x); + +template +[[vk::ext_instruction(spv::SmoothStep)]] +T oothStep(T edge0, T edge1, T x); + +template +[[vk::ext_instruction(spv::Fma)]] +T a(T a, T b, T c); + +template +[[vk::ext_instruction(spv::Frexp)]] +T exp(T x, T exp); + +template +[[vk::ext_instruction(spv::FrexpStruct)]] +T expStruct(T x); + +template +[[vk::ext_instruction(spv::Ldexp)]] +T exp(T x, T exp); + +template +[[vk::ext_instruction(spv::PackSnorm4x8)]] +T ckSnorm4x8(T v); + +template +[[vk::ext_instruction(spv::PackUnorm4x8)]] +T ckUnorm4x8(T v); + +template +[[vk::ext_instruction(spv::PackSnorm2x16)]] +T ckSnorm2x16(T v); + +template +[[vk::ext_instruction(spv::PackUnorm2x16)]] +T ckUnorm2x16(T v); + +template +[[vk::ext_instruction(spv::PackHalf2x16)]] +T ckHalf2x16(T v); + +template +[[vk::ext_instruction(spv::UnpackSnorm2x16)]] +T packSnorm2x16(T p); + +template +[[vk::ext_instruction(spv::UnpackUnorm2x16)]] +T packUnorm2x16(T p); + +template +[[vk::ext_instruction(spv::UnpackHalf2x16)]] +T packHalf2x16(T v); + +template +[[vk::ext_instruction(spv::UnpackSnorm4x8)]] +T packSnorm4x8(T p); + +template +[[vk::ext_instruction(spv::UnpackUnorm4x8)]] +T packUnorm4x8(T p); + +template +[[vk::ext_instruction(spv::Length)]] +T ngth(T x); + +template +[[vk::ext_instruction(spv::Distance)]] +T stance(T p0, T p1); + +template +[[vk::ext_instruction(spv::Cross)]] +T oss(T x, T y); + +template +[[vk::ext_instruction(spv::Normalize)]] +T rmalize(T x); + +template +[[vk::ext_instruction(spv::FaceForward)]] +T ceForward(T n, T i, T nref); + +template +[[vk::ext_instruction(spv::Reflect)]] +T flect(T i, T n); + +template +[[vk::ext_instruction(spv::Refract)]] +T fract(T i, T n, T eta); + +template +[[vk::ext_instruction(spv::FindILsb)]] +enable_if_t<(is_signed_v || is_unsigned_v), T> ndILsb(T value); + +template +[[vk::ext_instruction(spv::FindSMsb)]] +enable_if_t, T> ndSMsb(T value); + +template +[[vk::ext_instruction(spv::FindUMsb)]] +enable_if_t, T> ndUMsb(T value); + +template +[[vk::ext_capability(spv::CapabilityInterpolationFunction)]] +[[vk::ext_instruction(spv::InterpolateAtCentroid)]] +T terpolateAtCentroid(T interpolant); + +template +[[vk::ext_capability(spv::CapabilityInterpolationFunction)]] +[[vk::ext_instruction(spv::InterpolateAtSample)]] +T terpolateAtSample(T interpolant, T sample); + +template +[[vk::ext_capability(spv::CapabilityInterpolationFunction)]] +[[vk::ext_instruction(spv::InterpolateAtOffset)]] +T terpolateAtOffset(T interpolant, T offset); + +template +[[vk::ext_instruction(spv::NMin)]] +T in(T x, T y); + +template +[[vk::ext_instruction(spv::NMax)]] +T ax(T x, T y); + +template +[[vk::ext_instruction(spv::NClamp)]] +T lamp(T x, T minVal, T maxVal); + +} + +#endif +} +} + +#endif