X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fglsl%2Fspirv.cpp;h=91182a65725f3cae26a509ed588492ba08cfb881;hp=7d6edf656a4097607e70b1a68208f3c523e9d212;hb=e8369afbde298a3011a341cd2d4dfed76ecd8d3b;hpb=e484dab089e86e889f007ad362f72337542015a0 diff --git a/source/glsl/spirv.cpp b/source/glsl/spirv.cpp index 7d6edf65..91182a65 100644 --- a/source/glsl/spirv.cpp +++ b/source/glsl/spirv.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "reflect.h" @@ -11,149 +12,138 @@ namespace SL { const SpirVGenerator::BuiltinFunctionInfo SpirVGenerator::builtin_functions[] = { - { "radians", "f", "GLSL.std.450", GLSL450_RADIANS, { 1 }, 0 }, - { "degrees", "f", "GLSL.std.450", GLSL450_DEGREES, { 1 }, 0 }, - { "sin", "f", "GLSL.std.450", GLSL450_SIN, { 1 }, 0 }, - { "cos", "f", "GLSL.std.450", GLSL450_COS, { 1 }, 0 }, - { "tan", "f", "GLSL.std.450", GLSL450_TAN, { 1 }, 0 }, - { "asin", "f", "GLSL.std.450", GLSL450_ASIN, { 1 }, 0 }, - { "acos", "f", "GLSL.std.450", GLSL450_ACOS, { 1 }, 0 }, - { "atan", "f", "GLSL.std.450", GLSL450_ATAN, { 1 }, 0 }, - { "atan", "ff", "GLSL.std.450", GLSL450_ATAN2, { 1, 2 }, 0 }, - { "sinh", "f", "GLSL.std.450", GLSL450_SINH, { 1 }, 0 }, - { "cosh", "f", "GLSL.std.450", GLSL450_COSH, { 1 }, 0 }, - { "tanh", "f", "GLSL.std.450", GLSL450_TANH, { 1 }, 0 }, - { "asinh", "f", "GLSL.std.450", GLSL450_ASINH, { 1 }, 0 }, - { "acosh", "f", "GLSL.std.450", GLSL450_ACOSH, { 1 }, 0 }, - { "atanh", "f", "GLSL.std.450", GLSL450_ATANH, { 1 }, 0 }, - { "pow", "ff", "GLSL.std.450", GLSL450_POW, { 1, 2 }, 0 }, - { "exp", "f", "GLSL.std.450", GLSL450_EXP, { 1 }, 0 }, - { "log", "f", "GLSL.std.450", GLSL450_LOG, { 1 }, 0 }, - { "exp2", "f", "GLSL.std.450", GLSL450_EXP2, { 1 }, 0 }, - { "log2", "f", "GLSL.std.450", GLSL450_LOG2, { 1 }, 0 }, - { "sqrt", "f", "GLSL.std.450", GLSL450_SQRT, { 1 }, 0 }, - { "inversesqrt", "f", "GLSL.std.450", GLSL450_INVERSE_SQRT, { 1 }, 0 }, - { "abs", "f", "GLSL.std.450", GLSL450_F_ABS, { 1 }, 0 }, - { "abs", "i", "GLSL.std.450", GLSL450_S_ABS, { 1 }, 0 }, - { "sign", "f", "GLSL.std.450", GLSL450_F_SIGN, { 1 }, 0 }, - { "sign", "i", "GLSL.std.450", GLSL450_S_SIGN, { 1 }, 0 }, - { "floor", "f", "GLSL.std.450", GLSL450_FLOOR, { 1 }, 0 }, - { "trunc", "f", "GLSL.std.450", GLSL450_TRUNC, { 1 }, 0 }, - { "round", "f", "GLSL.std.450", GLSL450_ROUND, { 1 }, 0 }, - { "roundEven", "f", "GLSL.std.450", GLSL450_ROUND_EVEN, { 1 }, 0 }, - { "ceil", "f", "GLSL.std.450", GLSL450_CEIL, { 1 }, 0 }, - { "fract", "f", "GLSL.std.450", GLSL450_FRACT, { 1 }, 0 }, - { "mod", "f", "", OP_F_MOD, { 1, 2 }, 0 }, - { "min", "ff", "GLSL.std.450", GLSL450_F_MIN, { 1, 2 }, 0 }, - { "min", "ii", "GLSL.std.450", GLSL450_S_MIN, { 1, 2 }, 0 }, - { "min", "uu", "GLSL.std.450", GLSL450_U_MIN, { 1, 2 }, 0 }, - { "max", "ff", "GLSL.std.450", GLSL450_F_MAX, { 1, 2 }, 0 }, - { "max", "ii", "GLSL.std.450", GLSL450_S_MAX, { 1, 2 }, 0 }, - { "max", "uu", "GLSL.std.450", GLSL450_U_MAX, { 1, 2 }, 0 }, - { "clamp", "fff", "GLSL.std.450", GLSL450_F_CLAMP, { 1, 2, 3 }, 0 }, - { "clamp", "iii", "GLSL.std.450", GLSL450_S_CLAMP, { 1, 2, 3 }, 0 }, - { "clamp", "uuu", "GLSL.std.450", GLSL450_U_CLAMP, { 1, 2, 3 }, 0 }, - { "mix", "fff", "GLSL.std.450", GLSL450_F_MIX, { 1, 2, 3 }, 0 }, - { "mix", "ffb", "", OP_SELECT, { 3, 2, 1 }, 0 }, - { "mix", "iib", "", OP_SELECT, { 3, 2, 1 }, 0 }, - { "mix", "uub", "", OP_SELECT, { 3, 2, 1 }, 0 }, - { "step", "ff", "GLSL.std.450", GLSL450_F_STEP, { 1, 2 }, 0 }, - { "smoothstep", "fff", "GLSL.std.450", GLSL450_F_SMOOTH_STEP, { 1, 2, 3 }, 0 }, - { "isnan", "f", "", OP_IS_NAN, { 1 }, 0 }, - { "isinf", "f", "", OP_IS_INF, { 1 }, 0 }, - { "fma", "fff", "GLSL.std.450", GLSL450_F_FMA, { 1, 2, 3 }, 0 }, - { "length", "f", "GLSL.std.450", GLSL450_LENGTH, { 1 }, 0 }, - { "distance", "ff", "GLSL.std.450", GLSL450_DISTANCE, { 1, 2 }, 0 }, - { "dot", "ff", "", OP_DOT, { 1, 2 }, 0 }, - { "cross", "ff", "GLSL.std.450", GLSL450_CROSS, { 1, 2 }, 0 }, - { "normalize", "f", "GLSL.std.450", GLSL450_NORMALIZE, { 1 }, 0 }, - { "faceforward", "fff", "GLSL.std.450", GLSL450_FACE_FORWARD, { 1, 2, 3 }, 0 }, - { "reflect", "ff", "GLSL.std.450", GLSL450_REFLECT, { 1, 2 }, 0 }, - { "refract", "fff", "GLSL.std.450", GLSL450_REFRACT, { 1, 2, 3 }, 0 }, - { "matrixCompMult", "ff", "", 0, { 0 }, &SpirVGenerator::visit_builtin_matrix_comp_mult }, - { "outerProduct", "ff", "", OP_OUTER_PRODUCT, { 1, 2 }, 0 }, - { "transpose", "f", "", OP_TRANSPOSE, { 1 }, 0 }, - { "determinant", "f", "GLSL.std.450", GLSL450_DETERMINANT, { 1 }, 0 }, - { "inverse", "f", "GLSL.std.450", GLSL450_MATRIX_INVERSE, { 1 }, 0 }, - { "lessThan", "ff", "", OP_F_ORD_LESS_THAN, { 1, 2 }, 0 }, - { "lessThan", "ii", "", OP_S_LESS_THAN, { 1, 2 }, 0 }, - { "lessThan", "uu", "", OP_U_LESS_THAN, { 1, 2 }, 0 }, - { "lessThanEqual", "ff", "", OP_F_ORD_LESS_THAN_EQUAL, { 1, 2 }, 0 }, - { "lessThanEqual", "ii", "", OP_S_LESS_THAN_EQUAL, { 1, 2 }, 0 }, - { "lessThanEqual", "uu", "", OP_U_LESS_THAN_EQUAL, { 1, 2 }, 0 }, - { "greaterThan", "ff", "", OP_F_ORD_GREATER_THAN, { 1, 2 }, 0 }, - { "greaterThan", "ii", "", OP_S_GREATER_THAN, { 1, 2 }, 0 }, - { "greaterThan", "uu", "", OP_U_GREATER_THAN, { 1, 2 }, 0 }, - { "greaterThanEqual", "ff", "", OP_F_ORD_GREATER_THAN_EQUAL, { 1, 2 }, 0 }, - { "greaterThanEqual", "ii", "", OP_S_GREATER_THAN_EQUAL, { 1, 2 }, 0 }, - { "greaterThanEqual", "uu", "", OP_U_GREATER_THAN_EQUAL, { 1, 2 }, 0 }, - { "equal", "ff", "", OP_F_ORD_EQUAL, { 1, 2 }, 0 }, - { "equal", "ii", "", OP_I_EQUAL, { 1, 2 }, 0 }, - { "equal", "uu", "", OP_I_EQUAL, { 1, 2 }, 0 }, - { "notEqual", "ff", "", OP_F_ORD_NOT_EQUAL, { 1, 2 }, 0 }, - { "notEqual", "ii", "", OP_I_NOT_EQUAL, { 1, 2 }, 0 }, - { "notEqual", "uu", "", OP_I_NOT_EQUAL, { 1, 2 }, 0 }, - { "any", "b", "", OP_ANY, { 1 }, 0 }, - { "all", "b", "", OP_ALL, { 1 }, 0 }, - { "not", "b", "", OP_LOGICAL_NOT, { 1 }, 0 }, - { "bitfieldExtract", "iii", "", OP_BIT_FIELD_S_EXTRACT, { 1, 2, 3 }, 0 }, - { "bitfieldExtract", "uii", "", OP_BIT_FIELD_U_EXTRACT, { 1, 2, 3 }, 0 }, - { "bitfieldInsert", "iiii", "", OP_BIT_FIELD_INSERT, { 1, 2, 3, 4 }, 0 }, - { "bitfieldInsert", "uuii", "", OP_BIT_FIELD_INSERT, { 1, 2, 3, 4 }, 0 }, - { "bitfieldReverse", "i", "", OP_BIT_REVERSE, { 1 }, 0 }, - { "bitfieldReverse", "u", "", OP_BIT_REVERSE, { 1 }, 0 }, - { "bitCount", "i", "", OP_BIT_COUNT, { 1 }, 0 }, - { "findLSB", "i", "GLSL.std.450", GLSL450_FIND_I_LSB, { 1 }, 0 }, - { "findLSB", "u", "GLSL.std.450", GLSL450_FIND_I_LSB, { 1 }, 0 }, - { "findMSB", "i", "GLSL.std.450", GLSL450_FIND_S_MSB, { 1 }, 0 }, - { "findMSB", "u", "GLSL.std.450", GLSL450_FIND_U_MSB, { 1 }, 0 }, - { "textureSize", "", "", OP_IMAGE_QUERY_SIZE_LOD, { 1, 2 }, 0 }, - { "texture", "", "", 0, { }, &SpirVGenerator::visit_builtin_texture }, - { "textureLod", "", "", 0, { }, &SpirVGenerator::visit_builtin_texture }, - { "texelFetch", "", "", 0, { }, &SpirVGenerator::visit_builtin_texel_fetch }, - { "EmitVertex", "", "", OP_EMIT_VERTEX, { }, 0 }, - { "EndPrimitive", "", "", OP_END_PRIMITIVE, { }, 0 }, - { "dFdx", "f", "", OP_DP_DX, { 1 }, 0 }, - { "dFdy", "f", "", OP_DP_DY, { 1 }, 0 }, - { "dFdxFine", "f", "", OP_DP_DX_FINE, { 1 }, 0 }, - { "dFdyFine", "f", "", OP_DP_DY_FINE, { 1 }, 0 }, - { "dFdxCoarse", "f", "", OP_DP_DX_COARSE, { 1 }, 0 }, - { "dFdyCoarse", "f", "", OP_DP_DY_COARSE, { 1 }, 0 }, - { "fwidth", "f", "", OP_FWIDTH, { 1 }, 0 }, - { "fwidthFine", "f", "", OP_FWIDTH_FINE, { 1 }, 0 }, - { "fwidthCoarse", "f", "", OP_FWIDTH_COARSE, { 1 }, 0 }, - { "interpolateAtCentroid", "", "", 0, { }, &SpirVGenerator::visit_builtin_interpolate }, - { "interpolateAtSample", "", "", 0, { }, &SpirVGenerator::visit_builtin_interpolate }, - { "interpolateAtOffset", "", "", 0, { }, &SpirVGenerator::visit_builtin_interpolate }, - { "", "", "", 0, { }, 0 } + { "radians", "f", "GLSL.std.450", GLSL450_RADIANS, { 1 }, 0, 0 }, + { "degrees", "f", "GLSL.std.450", GLSL450_DEGREES, { 1 }, 0, 0 }, + { "sin", "f", "GLSL.std.450", GLSL450_SIN, { 1 }, 0, 0 }, + { "cos", "f", "GLSL.std.450", GLSL450_COS, { 1 }, 0, 0 }, + { "tan", "f", "GLSL.std.450", GLSL450_TAN, { 1 }, 0, 0 }, + { "asin", "f", "GLSL.std.450", GLSL450_ASIN, { 1 }, 0, 0 }, + { "acos", "f", "GLSL.std.450", GLSL450_ACOS, { 1 }, 0, 0 }, + { "atan", "f", "GLSL.std.450", GLSL450_ATAN, { 1 }, 0, 0 }, + { "atan", "ff", "GLSL.std.450", GLSL450_ATAN2, { 1, 2 }, 0, 0 }, + { "sinh", "f", "GLSL.std.450", GLSL450_SINH, { 1 }, 0, 0 }, + { "cosh", "f", "GLSL.std.450", GLSL450_COSH, { 1 }, 0, 0 }, + { "tanh", "f", "GLSL.std.450", GLSL450_TANH, { 1 }, 0, 0 }, + { "asinh", "f", "GLSL.std.450", GLSL450_ASINH, { 1 }, 0, 0 }, + { "acosh", "f", "GLSL.std.450", GLSL450_ACOSH, { 1 }, 0, 0 }, + { "atanh", "f", "GLSL.std.450", GLSL450_ATANH, { 1 }, 0, 0 }, + { "pow", "ff", "GLSL.std.450", GLSL450_POW, { 1, 2 }, 0, 0 }, + { "exp", "f", "GLSL.std.450", GLSL450_EXP, { 1 }, 0, 0 }, + { "log", "f", "GLSL.std.450", GLSL450_LOG, { 1 }, 0, 0 }, + { "exp2", "f", "GLSL.std.450", GLSL450_EXP2, { 1 }, 0, 0 }, + { "log2", "f", "GLSL.std.450", GLSL450_LOG2, { 1 }, 0, 0 }, + { "sqrt", "f", "GLSL.std.450", GLSL450_SQRT, { 1 }, 0, 0 }, + { "inversesqrt", "f", "GLSL.std.450", GLSL450_INVERSE_SQRT, { 1 }, 0, 0 }, + { "abs", "f", "GLSL.std.450", GLSL450_F_ABS, { 1 }, 0, 0 }, + { "abs", "i", "GLSL.std.450", GLSL450_S_ABS, { 1 }, 0, 0 }, + { "sign", "f", "GLSL.std.450", GLSL450_F_SIGN, { 1 }, 0, 0 }, + { "sign", "i", "GLSL.std.450", GLSL450_S_SIGN, { 1 }, 0, 0 }, + { "floor", "f", "GLSL.std.450", GLSL450_FLOOR, { 1 }, 0, 0 }, + { "trunc", "f", "GLSL.std.450", GLSL450_TRUNC, { 1 }, 0, 0 }, + { "round", "f", "GLSL.std.450", GLSL450_ROUND, { 1 }, 0, 0 }, + { "roundEven", "f", "GLSL.std.450", GLSL450_ROUND_EVEN, { 1 }, 0, 0 }, + { "ceil", "f", "GLSL.std.450", GLSL450_CEIL, { 1 }, 0, 0 }, + { "fract", "f", "GLSL.std.450", GLSL450_FRACT, { 1 }, 0, 0 }, + { "mod", "f", "", OP_F_MOD, { 1, 2 }, 0, 0 }, + { "min", "ff", "GLSL.std.450", GLSL450_F_MIN, { 1, 2 }, 0, 0 }, + { "min", "ii", "GLSL.std.450", GLSL450_S_MIN, { 1, 2 }, 0, 0 }, + { "min", "uu", "GLSL.std.450", GLSL450_U_MIN, { 1, 2 }, 0, 0 }, + { "max", "ff", "GLSL.std.450", GLSL450_F_MAX, { 1, 2 }, 0, 0 }, + { "max", "ii", "GLSL.std.450", GLSL450_S_MAX, { 1, 2 }, 0, 0 }, + { "max", "uu", "GLSL.std.450", GLSL450_U_MAX, { 1, 2 }, 0, 0 }, + { "clamp", "fff", "GLSL.std.450", GLSL450_F_CLAMP, { 1, 2, 3 }, 0, 0 }, + { "clamp", "iii", "GLSL.std.450", GLSL450_S_CLAMP, { 1, 2, 3 }, 0, 0 }, + { "clamp", "uuu", "GLSL.std.450", GLSL450_U_CLAMP, { 1, 2, 3 }, 0, 0 }, + { "mix", "fff", "GLSL.std.450", GLSL450_F_MIX, { 1, 2, 3 }, 0, 0 }, + { "mix", "ffb", "", OP_SELECT, { 3, 2, 1 }, 0, 0 }, + { "mix", "iib", "", OP_SELECT, { 3, 2, 1 }, 0, 0 }, + { "mix", "uub", "", OP_SELECT, { 3, 2, 1 }, 0, 0 }, + { "step", "ff", "GLSL.std.450", GLSL450_F_STEP, { 1, 2 }, 0, 0 }, + { "smoothstep", "fff", "GLSL.std.450", GLSL450_F_SMOOTH_STEP, { 1, 2, 3 }, 0, 0 }, + { "isnan", "f", "", OP_IS_NAN, { 1 }, 0, 0 }, + { "isinf", "f", "", OP_IS_INF, { 1 }, 0, 0 }, + { "fma", "fff", "GLSL.std.450", GLSL450_F_FMA, { 1, 2, 3 }, 0, 0 }, + { "length", "f", "GLSL.std.450", GLSL450_LENGTH, { 1 }, 0, 0 }, + { "distance", "ff", "GLSL.std.450", GLSL450_DISTANCE, { 1, 2 }, 0, 0 }, + { "dot", "ff", "", OP_DOT, { 1, 2 }, 0, 0 }, + { "cross", "ff", "GLSL.std.450", GLSL450_CROSS, { 1, 2 }, 0, 0 }, + { "normalize", "f", "GLSL.std.450", GLSL450_NORMALIZE, { 1 }, 0, 0 }, + { "faceforward", "fff", "GLSL.std.450", GLSL450_FACE_FORWARD, { 1, 2, 3 }, 0, 0 }, + { "reflect", "ff", "GLSL.std.450", GLSL450_REFLECT, { 1, 2 }, 0, 0 }, + { "refract", "fff", "GLSL.std.450", GLSL450_REFRACT, { 1, 2, 3 }, 0, 0 }, + { "matrixCompMult", "ff", "", 0, { 0 }, 0, &SpirVGenerator::visit_builtin_matrix_comp_mult }, + { "outerProduct", "ff", "", OP_OUTER_PRODUCT, { 1, 2 }, 0, 0 }, + { "transpose", "f", "", OP_TRANSPOSE, { 1 }, 0, 0 }, + { "determinant", "f", "GLSL.std.450", GLSL450_DETERMINANT, { 1 }, 0, 0 }, + { "inverse", "f", "GLSL.std.450", GLSL450_MATRIX_INVERSE, { 1 }, 0, 0 }, + { "lessThan", "ff", "", OP_F_ORD_LESS_THAN, { 1, 2 }, 0, 0 }, + { "lessThan", "ii", "", OP_S_LESS_THAN, { 1, 2 }, 0, 0 }, + { "lessThan", "uu", "", OP_U_LESS_THAN, { 1, 2 }, 0, 0 }, + { "lessThanEqual", "ff", "", OP_F_ORD_LESS_THAN_EQUAL, { 1, 2 }, 0, 0 }, + { "lessThanEqual", "ii", "", OP_S_LESS_THAN_EQUAL, { 1, 2 }, 0, 0 }, + { "lessThanEqual", "uu", "", OP_U_LESS_THAN_EQUAL, { 1, 2 }, 0, 0 }, + { "greaterThan", "ff", "", OP_F_ORD_GREATER_THAN, { 1, 2 }, 0, 0 }, + { "greaterThan", "ii", "", OP_S_GREATER_THAN, { 1, 2 }, 0, 0 }, + { "greaterThan", "uu", "", OP_U_GREATER_THAN, { 1, 2 }, 0, 0 }, + { "greaterThanEqual", "ff", "", OP_F_ORD_GREATER_THAN_EQUAL, { 1, 2 }, 0, 0 }, + { "greaterThanEqual", "ii", "", OP_S_GREATER_THAN_EQUAL, { 1, 2 }, 0, 0 }, + { "greaterThanEqual", "uu", "", OP_U_GREATER_THAN_EQUAL, { 1, 2 }, 0, 0 }, + { "equal", "ff", "", OP_F_ORD_EQUAL, { 1, 2 }, 0, 0 }, + { "equal", "ii", "", OP_I_EQUAL, { 1, 2 }, 0, 0 }, + { "equal", "uu", "", OP_I_EQUAL, { 1, 2 }, 0, 0 }, + { "notEqual", "ff", "", OP_F_ORD_NOT_EQUAL, { 1, 2 }, 0, 0 }, + { "notEqual", "ii", "", OP_I_NOT_EQUAL, { 1, 2 }, 0, 0 }, + { "notEqual", "uu", "", OP_I_NOT_EQUAL, { 1, 2 }, 0, 0 }, + { "any", "b", "", OP_ANY, { 1 }, 0, 0 }, + { "all", "b", "", OP_ALL, { 1 }, 0, 0 }, + { "not", "b", "", OP_LOGICAL_NOT, { 1 }, 0, 0 }, + { "bitfieldExtract", "iii", "", OP_BIT_FIELD_S_EXTRACT, { 1, 2, 3 }, 0, 0 }, + { "bitfieldExtract", "uii", "", OP_BIT_FIELD_U_EXTRACT, { 1, 2, 3 }, 0, 0 }, + { "bitfieldInsert", "iiii", "", OP_BIT_FIELD_INSERT, { 1, 2, 3, 4 }, 0, 0 }, + { "bitfieldInsert", "uuii", "", OP_BIT_FIELD_INSERT, { 1, 2, 3, 4 }, 0, 0 }, + { "bitfieldReverse", "i", "", OP_BIT_REVERSE, { 1 }, 0, 0 }, + { "bitfieldReverse", "u", "", OP_BIT_REVERSE, { 1 }, 0, 0 }, + { "bitCount", "i", "", OP_BIT_COUNT, { 1 }, 0, 0 }, + { "findLSB", "i", "GLSL.std.450", GLSL450_FIND_I_LSB, { 1 }, 0, 0 }, + { "findLSB", "u", "GLSL.std.450", GLSL450_FIND_I_LSB, { 1 }, 0, 0 }, + { "findMSB", "i", "GLSL.std.450", GLSL450_FIND_S_MSB, { 1 }, 0, 0 }, + { "findMSB", "u", "GLSL.std.450", GLSL450_FIND_U_MSB, { 1 }, 0, 0 }, + { "textureSize", "", "", 0, { }, CAP_IMAGE_QUERY, &SpirVGenerator::visit_builtin_texture_query }, + { "textureQueryLod", "", "", 0, { }, CAP_IMAGE_QUERY, &SpirVGenerator::visit_builtin_texture_query }, + { "textureQueryLevels", "", "", 0, { }, CAP_IMAGE_QUERY, &SpirVGenerator::visit_builtin_texture_query }, + { "texture", "", "", 0, { }, 0, &SpirVGenerator::visit_builtin_texture }, + { "textureLod", "", "", 0, { }, 0, &SpirVGenerator::visit_builtin_texture }, + { "texelFetch", "", "", 0, { }, 0, &SpirVGenerator::visit_builtin_texel_fetch }, + { "EmitVertex", "", "", OP_EMIT_VERTEX, { }, 0, 0 }, + { "EndPrimitive", "", "", OP_END_PRIMITIVE, { }, 0, 0 }, + { "dFdx", "f", "", OP_DP_DX, { 1 }, 0, 0 }, + { "dFdy", "f", "", OP_DP_DY, { 1 }, 0, 0 }, + { "dFdxFine", "f", "", OP_DP_DX_FINE, { 1 }, CAP_DERIVATIVE_CONTROL, 0 }, + { "dFdyFine", "f", "", OP_DP_DY_FINE, { 1 }, CAP_DERIVATIVE_CONTROL, 0 }, + { "dFdxCoarse", "f", "", OP_DP_DX_COARSE, { 1 }, CAP_DERIVATIVE_CONTROL, 0 }, + { "dFdyCoarse", "f", "", OP_DP_DY_COARSE, { 1 }, CAP_DERIVATIVE_CONTROL, 0 }, + { "fwidth", "f", "", OP_FWIDTH, { 1 }, 0, 0 }, + { "fwidthFine", "f", "", OP_FWIDTH_FINE, { 1 }, CAP_DERIVATIVE_CONTROL, 0 }, + { "fwidthCoarse", "f", "", OP_FWIDTH_COARSE, { 1 }, CAP_DERIVATIVE_CONTROL, 0 }, + { "interpolateAtCentroid", "", "", 0, { }, CAP_INTERPOLATION_FUNCTION, &SpirVGenerator::visit_builtin_interpolate }, + { "interpolateAtSample", "", "", 0, { }, CAP_INTERPOLATION_FUNCTION, &SpirVGenerator::visit_builtin_interpolate }, + { "interpolateAtOffset", "", "", 0, { }, CAP_INTERPOLATION_FUNCTION, &SpirVGenerator::visit_builtin_interpolate }, + { "", "", "", 0, { }, 0, 0 } }; SpirVGenerator::SpirVGenerator(): - stage(0), - current_function(0), - writer(content), - next_id(1), - r_expression_result_id(0), - constant_expression(false), - spec_constant(false), - reachable(false), - composite_access(false), - r_composite_base_id(0), - r_composite_base(0), - assignment_source_id(0), - loop_merge_block_id(0), - loop_continue_target_id(0) + writer(content) { } void SpirVGenerator::apply(Module &module) { use_capability(CAP_SHADER); - for(list::iterator i=module.stages.begin(); i!=module.stages.end(); ++i) + for(Stage &s: module.stages) { - stage = &*i; + stage = &s; interface_layouts.clear(); - i->content.visit(*this); + s.content.visit(*this); } writer.finalize(SPIRV_GENERATOR_MSP, next_id); @@ -237,8 +227,28 @@ SpirVGenerator::Id SpirVGenerator::get_id(Node &node) const SpirVGenerator::Id SpirVGenerator::allocate_id(Node &node, Id type_id) { + auto i = declared_ids.find(&node); + if(i!=declared_ids.end()) + { + if(i->second.type_id) + throw key_error(&node); + i->second.type_id = type_id; + return i->second.id; + } + Id id = next_id++; - insert_unique(declared_ids, &node, Declaration(id, type_id)); + declared_ids.insert(make_pair(&node, Declaration(id, type_id))); + return id; +} + +SpirVGenerator::Id SpirVGenerator::allocate_forward_id(Node &node) +{ + auto i = declared_ids.find(&node); + if(i!=declared_ids.end()) + return i->second.id; + + Id id = next_id++; + declared_ids.insert(make_pair(&node, Declaration(id, 0))); return id; } @@ -323,7 +333,7 @@ SpirVGenerator::Id SpirVGenerator::get_standard_type_id(BasicTypeDeclaration::Ki bool SpirVGenerator::is_scalar_type(Id type_id, BasicTypeDeclaration::Kind kind) const { - map::const_iterator i = standard_type_ids.find(TypeKey(kind, true)); + auto i = standard_type_ids.find(TypeKey(kind, true)); return (i!=standard_type_ids.end() && i->second==type_id); } @@ -391,7 +401,7 @@ SpirVGenerator::Id SpirVGenerator::get_load_id(VariableDeclaration &var) void SpirVGenerator::prune_loads(Id min_id) { - for(map::iterator i=variable_load_ids.begin(); i!=variable_load_ids.end(); ) + for(auto i=variable_load_ids.begin(); i!=variable_load_ids.end(); ) { if(i->second>=min_id) variable_load_ids.erase(i++); @@ -477,8 +487,8 @@ SpirVGenerator::Id SpirVGenerator::write_construct(Id type_id, const Id *elem_id void SpirVGenerator::visit(Block &block) { - for(NodeList::iterator i=block.body.begin(); i!=block.body.end(); ++i) - (*i)->visit(*this); + for(const RefPtr &s: block.body) + s->visit(*this); } void SpirVGenerator::visit(Literal &literal) @@ -508,8 +518,15 @@ void SpirVGenerator::visit(VariableReference &var) r_constant_result = false; if(composite_access) { - r_composite_base = var.declaration; r_expression_result_id = 0; + if(!assignment_source_id) + { + auto i = variable_load_ids.find(var.declaration); + if(i!=variable_load_ids.end()) + r_expression_result_id = i->second; + } + if(!r_expression_result_id) + r_composite_base = var.declaration; } else if(assignment_source_id) { @@ -542,13 +559,13 @@ void SpirVGenerator::generate_composite_access(TypeDeclaration &result_type) throw internal_error("composite access through pointer in constant context"); Id int32_type_id = get_standard_type_id(BasicTypeDeclaration::INT, 1); - for(vector::iterator i=r_composite_chain.begin(); i!=r_composite_chain.end(); ++i) - *i = (*i<0x400000 ? get_constant_id(int32_type_id, static_cast(*i)) : *i&0x3FFFFF); + for(unsigned &i: r_composite_chain) + i = (i<0x400000 ? get_constant_id(int32_type_id, static_cast(i)) : i&0x3FFFFF); /* Find the storage class of the base and obtain appropriate pointer type for the result. */ const Declaration &base_decl = get_item(declared_ids, r_composite_base); - map::const_iterator i = pointer_type_ids.begin(); + auto i = pointer_type_ids.begin(); for(; (i!=pointer_type_ids.end() && i->second!=base_decl.type_id); ++i) ; if(i==pointer_type_ids.end()) throw internal_error("could not find storage class"); @@ -560,18 +577,18 @@ void SpirVGenerator::generate_composite_access(TypeDeclaration &result_type) throw internal_error("assignment to temporary composite"); else { - for(vector::iterator i=r_composite_chain.begin(); i!=r_composite_chain.end(); ++i) - for(map::iterator j=constant_ids.begin(); (*i>=0x400000 && j!=constant_ids.end()); ++j) - if(j->second==(*i&0x3FFFFF)) - *i = j->first.int_value; + for(unsigned &i: r_composite_chain) + for(auto j=constant_ids.begin(); (i>=0x400000 && j!=constant_ids.end()); ++j) + if(j->second==(i&0x3FFFFF)) + i = j->first.int_value; opcode = OP_COMPOSITE_EXTRACT; } Id access_id = begin_expression(opcode, access_type_id, 1+r_composite_chain.size()); writer.write(r_composite_base_id); - for(vector::const_iterator i=r_composite_chain.begin(); i!=r_composite_chain.end(); ++i) - writer.write(*i); + for(unsigned i: r_composite_chain) + writer.write(i); end_expression(opcode); r_constant_result = false; @@ -1040,9 +1057,9 @@ void SpirVGenerator::visit(FunctionCall &call) vector argument_ids; argument_ids.reserve(call.arguments.size()); bool all_args_const = true; - for(NodeArray::const_iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) + for(const RefPtr &a: call.arguments) { - (*i)->visit(*this); + a->visit(*this); argument_ids.push_back(r_expression_result_id); all_args_const &= r_constant_result; } @@ -1058,8 +1075,8 @@ void SpirVGenerator::visit(FunctionCall &call) else if(call.declaration->source==BUILTIN_SOURCE) { string arg_types; - for(NodeArray::const_iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) - if(BasicTypeDeclaration *basic_arg = dynamic_cast((*i)->type)) + for(const RefPtr &a: call.arguments) + if(BasicTypeDeclaration *basic_arg = dynamic_cast(a->type)) { BasicTypeDeclaration &elem_arg = *get_element_type(*basic_arg); switch(elem_arg.kind) @@ -1076,6 +1093,9 @@ void SpirVGenerator::visit(FunctionCall &call) if(builtin_info->function==call.name && (!builtin_info->arg_types[0] || builtin_info->arg_types==arg_types)) break; + if(builtin_info->capability) + use_capability(static_cast(builtin_info->capability)); + if(builtin_info->opcode) { Opcode opcode; @@ -1112,14 +1132,14 @@ void SpirVGenerator::visit(FunctionCall &call) { r_expression_result_id = begin_expression(OP_FUNCTION_CALL, result_type_id, 1+call.arguments.size()); writer.write(get_id(*call.declaration->definition)); - for(vector::const_iterator i=argument_ids.begin(); i!=argument_ids.end(); ++i) - writer.write(*i); + for(Id i: argument_ids) + writer.write(i); end_expression(OP_FUNCTION_CALL); // Any global variables the called function uses might have changed value set dependencies = DependencyCollector().apply(*call.declaration->definition); - for(set::const_iterator i=dependencies.begin(); i!=dependencies.end(); ++i) - if(const VariableDeclaration *var = dynamic_cast(*i)) + for(Node *n: dependencies) + if(const VariableDeclaration *var = dynamic_cast(n)) variable_load_ids.erase(var); } } @@ -1157,7 +1177,7 @@ void SpirVGenerator::visit_constructor(FunctionCall &call, const vector &arg Id zero_id = get_constant_id(get_id(elem), 0.0f); for(unsigned i=0; i &argument_ids) +{ + if(argument_ids.size()<1) + throw internal_error("invalid texture query call"); + + Opcode opcode; + if(call.name=="textureSize") + opcode = OP_IMAGE_QUERY_SIZE_LOD; + else if(call.name=="textureQueryLod") + opcode = OP_IMAGE_QUERY_LOD; + else if(call.name=="textureQueryLevels") + opcode = OP_IMAGE_QUERY_LEVELS; + else + throw internal_error("invalid texture query call"); + + ImageTypeDeclaration &image_arg0 = dynamic_cast(*call.arguments[0]->type); + + Id image_id; + if(image_arg0.sampled) + { + Id image_type_id = get_item(image_type_ids, get_id(image_arg0)); + image_id = write_expression(OP_IMAGE, image_type_id, argument_ids[0]); + } + else + image_id = argument_ids[0]; + + Id result_type_id = get_id(*call.type); + r_expression_result_id = begin_expression(opcode, result_type_id, argument_ids.size()); + writer.write(image_id); + for(unsigned i=1; i &argument_ids) { if(argument_ids.size()<2) @@ -1341,14 +1395,12 @@ void SpirVGenerator::visit_builtin_interpolate(FunctionCall &call, const vector< else throw internal_error("invalid interpolate call"); - use_capability(CAP_INTERPOLATION_FUNCTION); - Id ext_id = import_extension("GLSL.std.450"); r_expression_result_id = begin_expression(OP_EXT_INST, get_id(*call.type)); writer.write(ext_id); writer.write(opcode); writer.write(get_id(*var->declaration)); - for(vector::const_iterator i=argument_ids.begin(); ++i!=argument_ids.end(); ) + for(auto i=argument_ids.begin(); ++i!=argument_ids.end(); ) writer.write(*i); end_expression(OP_EXT_INST); } @@ -1365,11 +1417,11 @@ void SpirVGenerator::visit(InterfaceLayout &layout) bool SpirVGenerator::check_duplicate_type(TypeDeclaration &type) { - for(map::const_iterator i=declared_ids.begin(); i!=declared_ids.end(); ++i) - if(TypeDeclaration *type2 = dynamic_cast(i->first)) + for(const auto &kvp: declared_ids) + if(TypeDeclaration *type2 = dynamic_cast(kvp.first)) if(TypeComparer().apply(type, *type2)) { - insert_unique(declared_ids, &type, i->second); + insert_unique(declared_ids, &type, kvp.second); return true; } @@ -1447,6 +1499,7 @@ void SpirVGenerator::visit(ImageTypeDeclaration &image) { writer.write_op_name(type_id, image.name); writer.write_op(content.globals, OP_TYPE_SAMPLED_IMAGE, type_id, image_id); + insert_unique(image_type_ids, type_id, image_id); } if(image.dimensions==ImageTypeDeclaration::ONE) @@ -1469,9 +1522,9 @@ void SpirVGenerator::visit(StructDeclaration &strct) bool builtin = (strct.interface_block && !strct.interface_block->block_name.compare(0, 3, "gl_")); vector member_type_ids; member_type_ids.reserve(strct.members.body.size()); - for(NodeList::const_iterator i=strct.members.body.begin(); i!=strct.members.body.end(); ++i) + for(const RefPtr &s: strct.members.body) { - const VariableDeclaration *var = dynamic_cast(i->get()); + const VariableDeclaration *var = dynamic_cast(s.get()); if(!var) continue; @@ -1489,14 +1542,13 @@ void SpirVGenerator::visit(StructDeclaration &strct) { if(var->layout) { - const vector &qualifiers = var->layout->qualifiers; - for(vector::const_iterator j=qualifiers.begin(); j!=qualifiers.end(); ++j) + for(const Layout::Qualifier &q: var->layout->qualifiers) { - if(j->name=="offset") - writer.write_op_member_decorate(type_id, index, DECO_OFFSET, j->value); - else if(j->name=="column_major") + if(q.name=="offset") + writer.write_op_member_decorate(type_id, index, DECO_OFFSET, q.value); + else if(q.name=="column_major") writer.write_op_member_decorate(type_id, index, DECO_COL_MAJOR); - else if(j->name=="row_major") + else if(q.name=="row_major") writer.write_op_member_decorate(type_id, index, DECO_ROW_MAJOR); } } @@ -1514,8 +1566,8 @@ void SpirVGenerator::visit(StructDeclaration &strct) writer.begin_op(content.globals, OP_TYPE_STRUCT); writer.write(type_id); - for(vector::const_iterator i=member_type_ids.begin(); i!=member_type_ids.end(); ++i) - writer.write(*i); + for(Id i: member_type_ids) + writer.write(i); writer.end_op(OP_TYPE_STRUCT); } @@ -1526,9 +1578,9 @@ void SpirVGenerator::visit(VariableDeclaration &var) int spec_id = -1; if(layout_ql) { - for(vector::const_iterator i=layout_ql->begin(); (spec_id<0 && i!=layout_ql->end()); ++i) - if(i->name=="constant_id") - spec_id = i->value; + auto i = find_member(*layout_ql, string("constant_id"), &Layout::Qualifier::name); + if(i!=layout_ql->end()) + spec_id = i->value; } Id type_id = get_variable_type_id(var); @@ -1591,19 +1643,27 @@ void SpirVGenerator::visit(VariableDeclaration &var) if(layout_ql) { - for(vector::const_iterator i=layout_ql->begin(); i!=layout_ql->end(); ++i) + for(const Layout::Qualifier &q: *layout_ql) { - if(i->name=="location") - writer.write_op_decorate(var_id, DECO_LOCATION, i->value); - else if(i->name=="set") - writer.write_op_decorate(var_id, DECO_DESCRIPTOR_SET, i->value); - else if(i->name=="binding") - writer.write_op_decorate(var_id, DECO_BINDING, i->value); + if(q.name=="location") + writer.write_op_decorate(var_id, DECO_LOCATION, q.value); + else if(q.name=="set") + writer.write_op_decorate(var_id, DECO_DESCRIPTOR_SET, q.value); + else if(q.name=="binding") + writer.write_op_decorate(var_id, DECO_BINDING, q.value); } } + if(!var.name.compare(0, 3, "gl_")) + { + BuiltinSemantic semantic = get_builtin_semantic(var.name); + writer.write_op_decorate(var_id, DECO_BUILTIN, semantic); + } if(init_id && current_function) + { writer.write_op(content.function_body, OP_STORE, var_id, init_id); + variable_load_ids[&var] = init_id; + } } writer.write_op_name(var_id, var.name); @@ -1639,10 +1699,9 @@ void SpirVGenerator::visit(InterfaceBlock &iface) if(iface.layout) { - const vector &qualifiers = iface.layout->qualifiers; - for(vector::const_iterator i=qualifiers.begin(); i!=qualifiers.end(); ++i) - if(i->name=="binding") - writer.write_op_decorate(block_id, DECO_BINDING, i->value); + auto i = find_member(iface.layout->qualifiers, string("binding"), &Layout::Qualifier::name); + if(i!=iface.layout->qualifiers.end()) + writer.write_op_decorate(block_id, DECO_BINDING, i->value); } } @@ -1660,15 +1719,15 @@ void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id) writer.write_string(func.name); set dependencies = DependencyCollector().apply(func); - for(set::const_iterator i=dependencies.begin(); i!=dependencies.end(); ++i) + for(Node *n: dependencies) { - if(const VariableDeclaration *var = dynamic_cast(*i)) + if(const VariableDeclaration *var = dynamic_cast(n)) { if(!var->interface.empty()) - writer.write(get_id(**i)); + writer.write(get_id(*n)); } - else if(dynamic_cast(*i)) - writer.write(get_id(**i)); + else if(dynamic_cast(n)) + writer.write(get_id(*n)); } writer.end_op(OP_ENTRY_POINT); @@ -1678,42 +1737,47 @@ void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id) else if(stage->type==Stage::GEOMETRY) use_capability(CAP_GEOMETRY); - for(vector::const_iterator i=interface_layouts.begin(); i!=interface_layouts.end(); ++i) + for(const InterfaceLayout *i: interface_layouts) { - const vector &qualifiers = (*i)->layout.qualifiers; - for(vector::const_iterator j=qualifiers.begin(); j!=qualifiers.end(); ++j) + for(const Layout::Qualifier &q: i->layout.qualifiers) { - if(j->name=="point") + if(q.name=="point") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, - ((*i)->interface=="in" ? EXEC_INPUT_POINTS : EXEC_OUTPUT_POINTS)); - else if(j->name=="lines") + (i->interface=="in" ? EXEC_INPUT_POINTS : EXEC_OUTPUT_POINTS)); + else if(q.name=="lines") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INPUT_LINES); - else if(j->name=="lines_adjacency") + else if(q.name=="lines_adjacency") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INPUT_LINES_ADJACENCY); - else if(j->name=="triangles") + else if(q.name=="triangles") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_TRIANGLES); - else if(j->name=="triangles_adjacency") + else if(q.name=="triangles_adjacency") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_INPUT_TRIANGLES_ADJACENCY); - else if(j->name=="line_strip") + else if(q.name=="line_strip") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_LINE_STRIP); - else if(j->name=="triangle_strip") + else if(q.name=="triangle_strip") writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_TRIANGLE_STRIP); - else if(j->name=="max_vertices") - writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_VERTICES, j->value); + else if(q.name=="max_vertices") + writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_OUTPUT_VERTICES, q.value); } } } void SpirVGenerator::visit(FunctionDeclaration &func) { - if(func.source==BUILTIN_SOURCE || func.definition!=&func) + if(func.source==BUILTIN_SOURCE) + return; + else if(func.definition!=&func) + { + if(func.definition) + allocate_forward_id(*func.definition); return; + } Id return_type_id = get_id(*func.return_type_declaration); vector param_type_ids; param_type_ids.reserve(func.parameters.size()); - for(NodeArray::const_iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) - param_type_ids.push_back(get_variable_type_id(**i)); + for(const RefPtr &p: func.parameters) + param_type_ids.push_back(get_variable_type_id(*p)); string sig_with_return = func.return_type+func.signature; Id &type_id = function_type_ids[sig_with_return]; @@ -1723,8 +1787,8 @@ void SpirVGenerator::visit(FunctionDeclaration &func) writer.begin_op(content.globals, OP_TYPE_FUNCTION); writer.write(type_id); writer.write(return_type_id); - for(vector::const_iterator i=param_type_ids.begin(); i!=param_type_ids.end(); ++i) - writer.write(*i); + for(unsigned i: param_type_ids) + writer.write(i); writer.end_op(OP_TYPE_FUNCTION); writer.write_op_name(type_id, sig_with_return); @@ -1806,6 +1870,9 @@ void SpirVGenerator::visit(Iteration &iter) if(iter.init_statement) iter.init_statement->visit(*this); + for(VariableDeclaration *v: AssignmentCollector().apply(iter)) + variable_load_ids.erase(v); + Id header_id = next_id++; Id continue_id = next_id++; Id merge_block_id = next_id++;