#include "bgfx_p.h"
#include "shader_spirv.h"
namespace bgfx
{
#define SPV_OPERAND_1(_a0) SpvOperand::_a0
#define SPV_OPERAND_2(_a0, _a1) SPV_OPERAND_1(_a0), SPV_OPERAND_1(_a1)
#define SPV_OPERAND_3(_a0, _a1, _a2) SPV_OPERAND_1(_a0), SPV_OPERAND_2(_a1, _a2)
#define SPV_OPERAND_4(_a0, _a1, _a2, _a3) SPV_OPERAND_1(_a0), SPV_OPERAND_3(_a1, _a2, _a3)
#define SPV_OPERAND_5(_a0, _a1, _a2, _a3, _a4) SPV_OPERAND_1(_a0), SPV_OPERAND_4(_a1, _a2, _a3, _a4)
#define SPV_OPERAND_6(_a0, _a1, _a2, _a3, _a4, _a5) SPV_OPERAND_1(_a0), SPV_OPERAND_5(_a1, _a2, _a3, _a4, _a5)
#define SPV_OPERAND_7(_a0, _a1, _a2, _a3, _a4, _a5, _a6) SPV_OPERAND_1(_a0), SPV_OPERAND_6(_a1, _a2, _a3, _a4, _a5, _a6)
#define SPV_OPERAND_8(_a0, _a1, _a2, _a3, _a4, _a5, _a6, _a7) SPV_OPERAND_1(_a0), SPV_OPERAND_7(_a1, _a2, _a3, _a4, _a5, _a6, _a7)
#define SPV_OPERAND_9(_a0, _a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8) SPV_OPERAND_1(_a0), SPV_OPERAND_8(_a1, _a2, _a3, _a4, _a5, _a6, _a7, _a8)
#if BX_COMPILER_MSVC
# define SPV_OPERAND(...) { BX_MACRO_DISPATCHER(SPV_OPERAND_, __VA_ARGS__) BX_VA_ARGS_PASS(__VA_ARGS__) }
#else
# define SPV_OPERAND(...) { BX_MACRO_DISPATCHER(SPV_OPERAND_, __VA_ARGS__)(__VA_ARGS__) }
#endif #define _ Count
bool isDebug(SpvOpcode::Enum _opcode)
{
return (SpvOpcode::SourceContinued <= _opcode && SpvOpcode::Line >= _opcode)
|| SpvOpcode::NoLine == _opcode
;
}
struct SpvOpcodeInfo
{
bool hasType;
bool hasResult;
SpvOperand::Enum operands[8];
};
static const SpvOpcodeInfo s_spvOpcodeInfo[] =
{
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(SourceLanguage, LiteralNumber, Id, LiteralString) },
{ false, false, SPV_OPERAND(LiteralString) },
{ false, true, SPV_OPERAND(LiteralString) },
{ false, true, SPV_OPERAND(LiteralNumber, LiteralString) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(LiteralString) },
{ false, true, SPV_OPERAND(LiteralString) },
{ true, true, SPV_OPERAND(LiteralNumber) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(AddressingModel, MemoryModel) },
{ false, false, SPV_OPERAND(ExecutionModel, Id, LiteralString) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(Capability ) },
{ false, false, SPV_OPERAND(_) },
{ false, true, SPV_OPERAND(LiteralNumber) },
{ false, true, SPV_OPERAND(LiteralNumber) },
{ false, true, SPV_OPERAND(LiteralNumber) },
{ false, true, SPV_OPERAND(LiteralNumber) },
{ false, true, SPV_OPERAND(ComponentType, LiteralNumber) },
{ false, true, SPV_OPERAND(LiteralNumber) },
{ false, true, SPV_OPERAND(SampledType, Dim, LiteralNumber, LiteralNumber, LiteralNumber, LiteralNumber, ImageFormat, AccessQualifier) },
{ false, true, SPV_OPERAND(LiteralNumber) },
{ false, true, SPV_OPERAND(LiteralNumber) },
{ false, true, SPV_OPERAND(ElementType, LiteralNumber) },
{ false, true, SPV_OPERAND(ElementType) },
{ false, true, SPV_OPERAND(IdRep) },
{ false, true, SPV_OPERAND(LiteralString) },
{ false, true, SPV_OPERAND(StorageClass, Id) },
{ false, true, SPV_OPERAND(Id, Id, Id, Id, Id) },
{ false, true, SPV_OPERAND(_) },
{ false, true, SPV_OPERAND(_) },
{ false, true, SPV_OPERAND(_) },
{ false, true, SPV_OPERAND(_) },
{ false, true, SPV_OPERAND(_) },
{ false, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(LiteralRep) },
{ true, true, SPV_OPERAND(LiteralRep) },
{ true, true, SPV_OPERAND(SamplerAddressingMode, LiteralNumber, SamplerFilterMode) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(FunctionControl, Id) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(Function, IdRep) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(StorageClass, Id) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(Pointer, MemoryAccess) },
{ false, false, SPV_OPERAND(Pointer, Object, MemoryAccess) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(Base, IdRep) },
{ true, true, SPV_OPERAND(Base, IdRep) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(Id, Decoration, LiteralRep) },
{ false, false, SPV_OPERAND(StructureType, LiteralNumber, Decoration, LiteralRep) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(Id, Id, LiteralRep) },
{ true, true, SPV_OPERAND(IdRep) },
{ true, true, SPV_OPERAND(Composite, LiteralRep) },
{ true, true, SPV_OPERAND(Id, Composite, LiteralRep) },
{ true, true, SPV_OPERAND(Id) },
{ true, true, SPV_OPERAND(Matrix) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(SampledImage, Coordinate, ImageOperands, IdRep) },
{ true, true, SPV_OPERAND(SampledImage, Coordinate, ImageOperands, Id, IdRep) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(SampledImage, Coordinate, Component, ImageOperands, IdRep) },
{ true, true, SPV_OPERAND(SampledImage, Coordinate, Dref, ImageOperands, IdRep) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(Id) },
{ true, true, SPV_OPERAND(Id) },
{ true, true, SPV_OPERAND(Id) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(Id) },
{ true, true, SPV_OPERAND(Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Vector, Scalar) },
{ true, true, SPV_OPERAND(Matrix, Scalar) },
{ true, true, SPV_OPERAND(Vector, Matrix) },
{ true, true, SPV_OPERAND(Matrix, Vector) },
{ true, true, SPV_OPERAND(Matrix, Matrix) },
{ true, true, SPV_OPERAND(Vector, Vector) },
{ true, true, SPV_OPERAND(Vector, Vector) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(Vector) },
{ true, true, SPV_OPERAND(Vector) },
{ true, true, SPV_OPERAND(Id) },
{ true, true, SPV_OPERAND(Id) },
{ true, true, SPV_OPERAND(Id) },
{ true, true, SPV_OPERAND(Id) },
{ true, true, SPV_OPERAND(Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(Id, Id) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(Condition, Id, Id) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(Id) },
{ false, false, SPV_OPERAND(Condition, Id, Id, LiteralRep) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(Id) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
{ false, false, SPV_OPERAND(_) },
{ true, true, SPV_OPERAND(_) },
};
BX_STATIC_ASSERT(BX_COUNTOF(s_spvOpcodeInfo) == SpvOpcode::Count);
const char* s_spvOpcode[] =
{
"Nop",
"Undef",
"SourceContinued",
"Source",
"SourceExtension",
"Name",
"MemberName",
"String",
"Line",
"Invalid9",
"Extension",
"ExtInstImport",
"ExtInst",
"Invalid13",
"MemoryModel",
"EntryPoint",
"ExecutionMode",
"Capability",
"Invalid18",
"TypeVoid",
"TypeBool",
"TypeInt",
"TypeFloat",
"TypeVector",
"TypeMatrix",
"TypeImage",
"TypeSampler",
"TypeSampledImage",
"TypeArray",
"TypeRuntimeArray",
"TypeStruct",
"TypeOpaque",
"TypePointer",
"TypeFunction",
"TypeEvent",
"TypeDeviceEvent",
"TypeReserveId",
"TypeQueue",
"TypePipe",
"TypeForwardPointer",
"Invalid40",
"ConstantTrue",
"ConstantFalse",
"Constant",
"ConstantComposite",
"ConstantSampler",
"ConstantNull",
"Invalid47",
"SpecConstantTrue",
"SpecConstantFalse",
"SpecConstant",
"SpecConstantComposite",
"SpecConstantOp",
"Invalid53",
"Function",
"FunctionParameter",
"FunctionEnd",
"FunctionCall",
"Invalid58",
"Variable",
"ImageTexelPointer",
"Load",
"Store",
"CopyMemory",
"CopyMemorySized",
"AccessChain",
"InBoundsAccessChain",
"PtrAccessChain",
"ArrayLength",
"GenericPtrMemSemantics",
"InBoundsPtrAccessChain",
"Decorate",
"MemberDecorate",
"DecorationGroup",
"GroupDecorate",
"GroupMemberDecorate",
"Invalid76",
"VectorExtractDynamic",
"VectorInsertDynamic",
"VectorShuffle",
"CompositeConstruct",
"CompositeExtract",
"CompositeInsert",
"CopyObject",
"Transpose",
"Invalid85",
"SampledImage",
"ImageSampleImplicitLod",
"ImageSampleExplicitLod",
"ImageSampleDrefImplicitLod",
"ImageSampleDrefExplicitLod",
"ImageSampleProjImplicitLod",
"ImageSampleProjExplicitLod",
"ImageSampleProjDrefImplicitLod",
"ImageSampleProjDrefExplicitLod",
"ImageFetch",
"ImageGather",
"ImageDrefGather",
"ImageRead",
"ImageWrite",
"Image",
"ImageQueryFormat",
"ImageQueryOrder",
"ImageQuerySizeLod",
"ImageQuerySize",
"ImageQueryLod",
"ImageQueryLevels",
"ImageQuerySamples",
"Invalid108",
"ConvertFToU",
"ConvertFToS",
"ConvertSToF",
"ConvertUToF",
"UConvert",
"SConvert",
"FConvert",
"QuantizeToF16",
"ConvertPtrToU",
"SatConvertSToU",
"SatConvertUToS",
"ConvertUToPtr",
"PtrCastToGeneric",
"GenericCastToPtr",
"GenericCastToPtrExplicit",
"Bitcast",
"Invalid125",
"SNegate",
"FNegate",
"IAdd",
"FAdd",
"ISub",
"FSub",
"IMul",
"FMul",
"UDiv",
"SDiv",
"FDiv",
"UMod",
"SRem",
"SMod",
"FRem",
"FMod",
"VectorTimesScalar",
"MatrixTimesScalar",
"VectorTimesMatrix",
"MatrixTimesVector",
"MatrixTimesMatrix",
"OuterProduct",
"Dot",
"IAddCarry",
"ISubBorrow",
"UMulExtended",
"SMulExtended",
"Invalid153",
"Any",
"All",
"IsNan",
"IsInf",
"IsFinite",
"IsNormal",
"SignBitSet",
"LessOrGreater",
"Ordered",
"Unordered",
"LogicalEqual",
"LogicalNotEqual",
"LogicalOr",
"LogicalAnd",
"LogicalNot",
"Select",
"IEqual",
"INotEqual",
"UGreaterThan",
"SGreaterThan",
"UGreaterThanEqual",
"SGreaterThanEqual",
"ULessThan",
"SLessThan",
"ULessThanEqual",
"SLessThanEqual",
"FOrdEqual",
"FUnordEqual",
"FOrdNotEqual",
"FUnordNotEqual",
"FOrdLessThan",
"FUnordLessThan",
"FOrdGreaterThan",
"FUnordGreaterThan",
"FOrdLessThanEqual",
"FUnordLessThanEqual",
"FOrdGreaterThanEqual",
"FUnordGreaterThanEqual",
"Invalid192",
"Invalid193",
"ShiftRightLogical",
"ShiftRightArithmetic",
"ShiftLeftLogical",
"BitwiseOr",
"BitwiseXor",
"BitwiseAnd",
"Not",
"BitFieldInsert",
"BitFieldSExtract",
"BitFieldUExtract",
"BitReverse",
"BitCount",
"Invalid206",
"DPdx",
"DPdy",
"Fwidth",
"DPdxFine",
"DPdyFine",
"FwidthFine",
"DPdxCoarse",
"DPdyCoarse",
"FwidthCoarse",
"Invalid216",
"Invalid217",
"EmitVertex",
"EndPrimitive",
"EmitStreamVertex",
"Invalid222",
"Invalid223",
"EndStreamPrimitive",
"ControlBarrier",
"MemoryBarrier",
"Invalid226",
"AtomicLoad",
"AtomicStore",
"AtomicExchange",
"AtomicCompareExchange",
"AtomicCompareExchangeWeak",
"AtomicIIncrement",
"AtomicIDecrement",
"AtomicIAdd",
"AtomicISub",
"AtomicSMin",
"AtomicUMin",
"AtomicSMax",
"AtomicUMax",
"AtomicAnd",
"AtomicOr",
"AtomicXor",
"Invalid243",
"Invalid244",
"Phi",
"LoopMerge",
"SelectionMerge",
"Label",
"Branch",
"BranchConditional",
"Switch",
"Kill",
"Return",
"ReturnValue",
"Unreachable",
"LifetimeStart",
"LifetimeStop",
"Invalid258",
"GroupAsyncCopy",
"GroupWaitEvents",
"GroupAll",
"GroupAny",
"GroupBroadcast",
"GroupIAdd",
"GroupFAdd",
"GroupFMin",
"GroupUMin",
"GroupSMin",
"GroupFMax",
"GroupUMax",
"GroupSMax",
"Invalid272",
"Invalid273",
"ReadPipe",
"WritePipe",
"ReservedReadPipe",
"ReservedWritePipe",
"ReserveReadPipePackets",
"ReserveWritePipePackets",
"CommitReadPipe",
"CommitWritePipe",
"IsValidReserveId",
"GetNumPipePackets",
"GetMaxPipePackets",
"GroupReserveReadPipePackets",
"GroupReserveWritePipePackets",
"GroupCommitReadPipe",
"GroupCommitWritePipe",
"Invalid289",
"Invalid290",
"EnqueueMarker",
"EnqueueKernel",
"GetKernelNDrangeSubGroupCount",
"GetKernelNDrangeMaxSubGroupSize",
"GetKernelWorkGroupSize",
"GetKernelPreferredWorkGroupSizeMultiple",
"RetainEvent",
"ReleaseEvent",
"CreateUserEvent",
"IsValidEvent",
"SetUserEventStatus",
"CaptureEventProfilingInfo",
"GetDefaultQueue",
"BuildNDRange",
"ImageSparseSampleImplicitLod",
"ImageSparseSampleExplicitLod",
"ImageSparseSampleDrefImplicitLod",
"ImageSparseSampleDrefExplicitLod",
"ImageSparseSampleProjImplicitLod",
"ImageSparseSampleProjExplicitLod",
"ImageSparseSampleProjDrefImplicitLod",
"ImageSparseSampleProjDrefExplicitLod",
"ImageSparseFetch",
"ImageSparseGather",
"ImageSparseDrefGather",
"ImageSparseTexelsResident",
"NoLine",
"AtomicFlagTestAndSet",
"AtomicFlagClear",
"ImageSparseRead",
"",
};
BX_STATIC_ASSERT(BX_COUNTOF(s_spvOpcode)-1 == SpvOpcode::Count);
const char* getName(SpvOpcode::Enum _opcode)
{
BX_WARN(_opcode <= SpvOpcode::Count, "Unknown opcode id %d.", _opcode);
return _opcode <= SpvOpcode::Count
? s_spvOpcode[_opcode]
: "?SpvOpcode?"
;
}
struct SpvDecorationInfo
{
SpvOperand::Enum operands[2];
};
static const SpvDecorationInfo s_spvDecorationInfo[] =
{
{ SPV_OPERAND(_) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(LiteralString, LinkageType) },
{ SPV_OPERAND(_) },
{ SPV_OPERAND(LiteralNumber) },
{ SPV_OPERAND(LiteralNumber) },
};
static const char* s_spvDecoration[] =
{
"RelaxedPrecision",
"SpecId",
"Block",
"BufferBlock",
"RowMajor",
"ColMajor",
"ArrayStride",
"MatrixStride",
"GLSLShared",
"GLSLPacked",
"CPacked",
"BuiltIn",
"Unknown12",
"NoPerspective",
"Flat",
"Patch",
"Centroid",
"Sample",
"Invariant",
"Restrict",
"Aliased",
"Volatile",
"Constant",
"Coherent",
"NonWritable",
"NonReadable",
"Uniform",
"Unknown27",
"SaturatedConversion",
"Stream",
"Location",
"Component",
"Index",
"Binding",
"DescriptorSet",
"Offset",
"XfbBuffer",
"XfbStride",
"FuncParamAttr",
"FPRoundingMode",
"FPFastMathMode",
"LinkageAttributes",
"NoContraction",
"InputAttachmentIndex",
"Alignment",
""
};
BX_STATIC_ASSERT(BX_COUNTOF(s_spvDecoration)-1 == SpvDecoration::Count);
const char* getName(SpvDecoration::Enum _enum)
{
BX_UNUSED(s_spvDecorationInfo);
BX_ASSERT(_enum <= SpvDecoration::Count, "Unknown decoration id %d.", _enum);
return _enum <= SpvDecoration::Count
? s_spvDecoration[_enum]
: "?SpvDecoration?"
;
}
#undef _
#undef SPV_OPERAND
static const char* s_spvStorageClass[] =
{
"UniformConstant",
"Input",
"Uniform",
"Output",
"Workgroup",
"CrossWorkgroup",
"Private",
"Function",
"Generic",
"PushConstant",
"AtomicCounter",
"Image",
""
};
BX_STATIC_ASSERT(BX_COUNTOF(s_spvStorageClass)-1 == SpvStorageClass::Count);
const char* getName(SpvStorageClass::Enum _enum)
{
BX_ASSERT(_enum <= SpvStorageClass::Count, "Unknown storage class id %d.", _enum);
return _enum <= SpvStorageClass::Count
? s_spvStorageClass[_enum]
: "?SpvStorageClass?"
;
}
static const char* s_spvBuiltin[] =
{
"Position",
"PointSize",
"ClipDistance",
"CullDistance",
"VertexId",
"InstanceId",
"PrimitiveId",
"InvocationId",
"Layer",
"ViewportIndex",
"TessLevelOuter",
"TessLevelInner",
"TessCoord",
"PatchVertices",
"FragCoord",
"PointCoord",
"FrontFacing",
"SampleId",
"SamplePosition",
"SampleMask",
"FragDepth",
"HelperInvocation",
"NumWorkgroups",
"WorkgroupSize",
"WorkgroupId",
"LocalInvocationId",
"GlobalInvocationId",
"LocalInvocationIndex",
"WorkDim",
"GlobalSize",
"EnqueuedWorkgroupSize",
"GlobalOffset",
"GlobalLinearId",
"SubgroupSize",
"SubgroupMaxSize",
"NumSubgroups",
"NumEnqueuedSubgroups",
"SubgroupId",
"SubgroupLocalInvocationId",
"VertexIndex",
"InstanceIndex",
"",
};
BX_STATIC_ASSERT(BX_COUNTOF(s_spvBuiltin)-1 == SpvBuiltin::Count);
const char* getName(SpvBuiltin::Enum _enum)
{
BX_ASSERT(_enum <= SpvBuiltin::Count, "Unknown builtin id %d.", _enum);
return _enum <= SpvBuiltin::Count
? s_spvBuiltin[_enum]
: "?SpvBuiltin?"
;
}
int32_t read(bx::ReaderI* _reader, SpvOperand& _operand, bx::Error* _err)
{
int32_t size = 0;
uint32_t token;
_operand.literalString = "";
switch (_operand.type)
{
case SpvOperand::LiteralString:
do
{
size += bx::read(_reader, token, _err);
_operand.literalString.append( (char*)&token, (char*)&token + sizeof(token) );
}
while (0 != (token & 0xff000000) && _err->isOk() );
break;
default:
size += bx::read(_reader, _operand.data, _err);
break;
}
return size;
}
int32_t read(bx::ReaderI* _reader, SpvInstruction& _instruction, bx::Error* _err)
{
int32_t size = 0;
uint32_t token;
size += bx::read(_reader, token, _err);
_instruction.opcode = SpvOpcode::Enum( (token & UINT32_C(0x0000ffff) ) );
_instruction.length = uint16_t( (token & UINT32_C(0xffff0000) ) >> 16);
if (_instruction.opcode >= SpvOpcode::Count)
{
BX_ERROR_SET(_err, BGFX_SHADER_SPIRV_INVALID_INSTRUCTION, "SPIR-V: Invalid instruction.");
return size;
}
if (0 == _instruction.length)
{
return size;
}
const SpvOpcodeInfo& info = s_spvOpcodeInfo[_instruction.opcode];
_instruction.hasType = info.hasType;
_instruction.hasResult = info.hasResult;
if (info.hasType)
{
size += read(_reader, _instruction.type, _err);
}
else
{
_instruction.type = UINT32_MAX;
}
if (info.hasResult)
{
size += read(_reader, _instruction.result, _err);
}
else
{
_instruction.result = UINT32_MAX;
}
uint16_t currOp = 0;
switch (_instruction.opcode)
{
case SpvOpcode::EntryPoint:
_instruction.operand[currOp].type = info.operands[currOp];
size += read(_reader, _instruction.operand[currOp++], _err);
_instruction.operand[currOp].type = info.operands[currOp];
size += read(_reader, _instruction.operand[currOp++], _err);
_instruction.operand[currOp].type = info.operands[currOp];
size += read(_reader, _instruction.operand[currOp++], _err);
_instruction.operand[currOp].type = SpvOperand::Id;
for (uint32_t ii = 0, num = _instruction.length - size/4; ii < num; ++ii)
{
size += read(_reader, _instruction.operand[currOp], _err);
}
break;
default:
for (
; size/4 != _instruction.length
&& _err->isOk()
&& currOp < BX_COUNTOF(_instruction.operand)
; ++currOp)
{
_instruction.operand[currOp].type = info.operands[currOp];
size += read(_reader, _instruction.operand[currOp], _err);
}
break;
}
_instruction.numOperands = currOp;
return size;
}
int32_t write(bx::WriterI* _writer, const SpvInstruction& _instruction, bx::Error* _err)
{
int32_t size = 0;
BX_UNUSED(_writer, _instruction, _err);
return size;
}
int32_t toString(char* _out, int32_t _size, const SpvInstruction& _instruction)
{
int32_t size = 0;
if (_instruction.hasResult)
{
if (_instruction.hasType)
{
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, " r%d.t%d = "
, _instruction.result
, _instruction.type
);
}
else
{
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, " r%d = "
, _instruction.result
);
}
}
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, "%s"
, getName(_instruction.opcode)
);
for (uint32_t ii = 0, num = _instruction.numOperands; ii < num; ++ii)
{
const SpvOperand& operand = _instruction.operand[ii];
switch (operand.type)
{
case SpvOperand::AddressingModel:
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, "%sAddressingModel(%d)"
, 0 == ii ? " " : ", "
, operand.data
);
break;
case SpvOperand::Decoration:
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, "%s%s"
, 0 == ii ? " " : ", "
, getName(SpvDecoration::Enum(operand.data) )
);
break;
case SpvOperand::FunctionControl:
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, "%s0x%08x"
, 0 == ii ? " " : ", "
, operand.data
);
break;
case SpvOperand::LiteralNumber:
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, "%s%d"
, 0 == ii ? " " : ", "
, operand.data
);
break;
case SpvOperand::LiteralString:
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, "%s%s"
, 0 == ii ? " " : ", "
, operand.literalString.c_str()
);
break;
case SpvOperand::MemoryModel:
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, "%sMemoryModel(%d)"
, 0 == ii ? " " : ", "
, operand.data
);
break;
case SpvOperand::StorageClass:
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, "%s%s"
, 0 == ii ? " " : ", "
, getName(SpvStorageClass::Enum(operand.data) )
);
break;
case SpvOperand::Count:
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, "%s__%d__"
, 0 == ii ? " " : ", "
, operand.data
);
break;
default:
size += bx::snprintf(&_out[size], bx::uint32_imax(0, _size-size)
, "%sr%d"
, 0 == ii ? " " : ", "
, operand.data
);
break;
}
}
return size;
}
int32_t read(bx::ReaderSeekerI* _reader, SpvShader& _shader, bx::Error* _err)
{
int32_t size = 0;
uint32_t numBytes = uint32_t(bx::getSize(_reader) - bx::seek(_reader) );
_shader.byteCode.resize(numBytes);
size += bx::read(_reader, _shader.byteCode.data(), numBytes, _err);
return size;
}
int32_t write(bx::WriterI* _writer, const SpvShader& _shader, bx::Error* _err)
{
int32_t size = 0;
BX_UNUSED(_writer, _shader, _err);
return size;
}
#define SPIRV_MAGIC 0x07230203
int32_t read(bx::ReaderSeekerI* _reader, SpirV& _spirv, bx::Error* _err)
{
BX_ERROR_SCOPE(_err);
int32_t size = 0;
size += bx::read(_reader, _spirv.header, _err);
if (!_err->isOk()
|| size != sizeof(SpirV::Header)
|| _spirv.header.magic != SPIRV_MAGIC
)
{
BX_ERROR_SET(_err, BGFX_SHADER_SPIRV_INVALID_HEADER, "SPIR-V: Invalid header.");
return size;
}
size += read(_reader, _spirv.shader, _err);
return size;
}
int32_t write(bx::WriterSeekerI* _writer, const SpirV& _spirv, bx::Error* _err)
{
int32_t size = 0;
BX_UNUSED(_writer, _spirv, _err);
return size;
}
void parse(const SpvShader& _src, SpvParseFn _fn, void* _userData, bx::Error* _err)
{
BX_ERROR_SCOPE(_err);
uint32_t numBytes = uint32_t(_src.byteCode.size() );
bx::MemoryReader reader(_src.byteCode.data(), numBytes);
for (uint32_t token = 0, numTokens = uint32_t(_src.byteCode.size() / sizeof(uint32_t) ); token < numTokens;)
{
SpvInstruction instruction;
uint32_t size = read(&reader, instruction, _err);
if (!_err->isOk() )
{
return;
}
if (size/4 != instruction.length)
{
BX_TRACE("read %d, expected %d, %s"
, size/4
, instruction.length
, getName(instruction.opcode)
);
BX_ERROR_SET(_err, BGFX_SHADER_SPIRV_INVALID_INSTRUCTION, "SPIR-V: Invalid instruction.");
return;
}
bool cont = _fn(token * sizeof(uint32_t), instruction, _userData);
if (!cont)
{
return;
}
token += instruction.length;
}
}
}