X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fspirv.cpp;h=33da0d5ca86c830bbb8f2248f4ee774b8ecc5e0d;hb=69bf91a6b169934f2853538580f46ffa8bde1109;hp=799e31d6493aa652064bfe06885760a1b2b65dbd;hpb=cc5483cc709fdf7b6966a3e69dabfcafebaaffa0;p=libs%2Fgl.git diff --git a/source/glsl/spirv.cpp b/source/glsl/spirv.cpp index 799e31d6..33da0d5c 100644 --- a/source/glsl/spirv.cpp +++ b/source/glsl/spirv.cpp @@ -11,106 +11,121 @@ 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 }, - { "max", "ff", "GLSL.std.450", GLSL450_F_MAX, { 1, 2 }, 0 }, - { "max", "ii", "GLSL.std.450", GLSL450_S_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 }, - { "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 }, - { "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 }, - { "lessThanEqual", "ff", "", OP_F_ORD_LESS_THAN_EQUAL, { 1, 2 }, 0 }, - { "lessThanEqual", "ii", "", OP_S_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 }, - { "greaterThanEqual", "ff", "", OP_F_ORD_GREATER_THAN_EQUAL, { 1, 2 }, 0 }, - { "greaterThanEqual", "ii", "", OP_S_GREATER_THAN_EQUAL, { 1, 2 }, 0 }, - { "equal", "ff", "", OP_F_ORD_EQUAL, { 1, 2 }, 0 }, - { "equal", "ii", "", 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 }, - { "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 }, - { "bitfieldInsert", "iiii", "", OP_BIT_FIELD_INSERT, { 1, 2, 3, 4 }, 0 }, - { "bitfieldReverse", "i", "", OP_BIT_REVERSE, { 1 }, 0 }, - { "bitCount", "i", "", OP_BIT_COUNT, { 1 }, 0 }, - { "findLSB", "i", "GLSL.std.450", GLSL450_FIND_I_LSB, { 1 }, 0 }, - { "findMSB", "i", "GLSL.std.450", GLSL450_FIND_S_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", "", "", OP_IMAGE_QUERY_SIZE_LOD, { 1, 2 }, CAP_IMAGE_QUERY, 0 }, + { "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(): @@ -141,7 +156,7 @@ void SpirVGenerator::apply(Module &module) i->content.visit(*this); } - writer.finalize(next_id); + writer.finalize(SPIRV_GENERATOR_MSP, next_id); } SpirVGenerator::StorageClass SpirVGenerator::get_interface_storage(const string &iface, bool block) @@ -222,8 +237,28 @@ SpirVGenerator::Id SpirVGenerator::get_id(Node &node) const SpirVGenerator::Id SpirVGenerator::allocate_id(Node &node, Id type_id) { + map::iterator 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++; + declared_ids.insert(make_pair(&node, Declaration(id, type_id))); + return id; +} + +SpirVGenerator::Id SpirVGenerator::allocate_forward_id(Node &node) +{ + map::iterator i = declared_ids.find(&node); + if(i!=declared_ids.end()) + 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, 0))); return id; } @@ -250,6 +285,8 @@ SpirVGenerator::ConstantKey SpirVGenerator::get_constant_key(Id type_id, const V return ConstantKey(type_id, value.value()); else if(value.check_type()) return ConstantKey(type_id, value.value()); + else if(value.check_type()) + return ConstantKey(type_id, value.value()); else if(value.check_type()) return ConstantKey(type_id, value.value()); else @@ -281,10 +318,10 @@ SpirVGenerator::Id SpirVGenerator::get_vector_constant_id(Id type_id, unsigned s return const_id; } -SpirVGenerator::Id SpirVGenerator::get_standard_type_id(BasicTypeDeclaration::Kind kind, unsigned size) +SpirVGenerator::Id SpirVGenerator::get_standard_type_id(BasicTypeDeclaration::Kind kind, unsigned size, bool sign) { - Id base_id = (size>1 ? get_standard_type_id(kind, 1) : 0); - Id &type_id = standard_type_ids[TypeKey(base_id, (size>1 ? size : static_cast(kind)))]; + Id base_id = (size>1 ? get_standard_type_id(kind, 1, sign) : 0); + Id &type_id = standard_type_ids[base_id ? TypeKey(base_id, size) : TypeKey(kind, sign)]; if(!type_id) { type_id = next_id++; @@ -295,7 +332,7 @@ SpirVGenerator::Id SpirVGenerator::get_standard_type_id(BasicTypeDeclaration::Ki else if(kind==BasicTypeDeclaration::BOOL) writer.write_op(content.globals, OP_TYPE_BOOL, type_id); else if(kind==BasicTypeDeclaration::INT) - writer.write_op(content.globals, OP_TYPE_INT, type_id, 32, 1); + writer.write_op(content.globals, OP_TYPE_INT, type_id, 32, sign); else if(kind==BasicTypeDeclaration::FLOAT) writer.write_op(content.globals, OP_TYPE_FLOAT, type_id, 32); else @@ -306,7 +343,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(0, kind)); + map::const_iterator i = standard_type_ids.find(TypeKey(kind, true)); return (i!=standard_type_ids.end() && i->second==type_id); } @@ -394,9 +431,12 @@ SpirVGenerator::Id SpirVGenerator::begin_expression(Opcode opcode, Id type_id, u writer.begin_op(content.function_body, opcode, (n_args ? 1+has_result*2+n_args : 0)); } else if(opcode==OP_COMPOSITE_CONSTRUCT) - writer.begin_op(content.function_body, OP_SPEC_CONSTANT_COMPOSITE, (n_args ? 1+has_result*2+n_args : 0)); + writer.begin_op(content.globals, (spec_constant ? OP_SPEC_CONSTANT_COMPOSITE : OP_CONSTANT_COMPOSITE), + (n_args ? 1+has_result*2+n_args : 0)); + else if(!spec_constant) + throw internal_error("invalid non-specialization constant expression"); else - writer.begin_op(content.function_body, OP_SPEC_CONSTANT_OP, (n_args ? 2+has_result*2+n_args : 0)); + writer.begin_op(content.globals, OP_SPEC_CONSTANT_OP, (n_args ? 2+has_result*2+n_args : 0)); Id result_id = next_id++; if(has_result) @@ -404,7 +444,7 @@ SpirVGenerator::Id SpirVGenerator::begin_expression(Opcode opcode, Id type_id, u writer.write(type_id); writer.write(result_id); } - if(constant_expression && opcode!=OP_COMPOSITE_CONSTRUCT) + if(spec_constant && opcode!=OP_COMPOSITE_CONSTRUCT) writer.write(opcode); return result_id; @@ -413,7 +453,7 @@ SpirVGenerator::Id SpirVGenerator::begin_expression(Opcode opcode, Id type_id, u void SpirVGenerator::end_expression(Opcode opcode) { if(constant_expression) - opcode = (opcode==OP_COMPOSITE_CONSTRUCT ? OP_SPEC_CONSTANT_COMPOSITE : OP_SPEC_CONSTANT_OP); + opcode = (opcode==OP_COMPOSITE_CONSTRUCT ? spec_constant ? OP_SPEC_CONSTANT_COMPOSITE : OP_CONSTANT_COMPOSITE : OP_SPEC_CONSTANT_OP); writer.end_op(opcode); } @@ -455,16 +495,6 @@ SpirVGenerator::Id SpirVGenerator::write_construct(Id type_id, const Id *elem_id return result_id; } -BasicTypeDeclaration &SpirVGenerator::get_element_type(BasicTypeDeclaration &basic) -{ - if(basic.kind==BasicTypeDeclaration::BOOL || basic.kind==BasicTypeDeclaration::INT || basic.kind==BasicTypeDeclaration::FLOAT) - return basic; - else if((basic.kind==BasicTypeDeclaration::VECTOR || basic.kind==BasicTypeDeclaration::MATRIX) && basic.base_type) - return get_element_type(dynamic_cast(*basic.base_type)); - else - throw invalid_argument("SpirVGenerator::get_element_type"); -} - void SpirVGenerator::visit(Block &block) { for(NodeList::iterator i=block.body.begin(); i!=block.body.end(); ++i) @@ -478,6 +508,7 @@ void SpirVGenerator::visit(Literal &literal) r_expression_result_id = write_constant(type_id, get_constant_key(type_id, literal.value).int_value, true); else r_expression_result_id = get_constant_id(type_id, literal.value); + r_constant_result = true; } void SpirVGenerator::visit(VariableReference &var) @@ -488,11 +519,13 @@ void SpirVGenerator::visit(VariableReference &var) throw internal_error("reference to non-constant variable in constant context"); r_expression_result_id = get_id(*var.declaration); + r_constant_result = true; return; } else if(!current_function) throw internal_error("non-constant context outside a function"); + r_constant_result = false; if(composite_access) { r_composite_base = var.declaration; @@ -515,6 +548,7 @@ void SpirVGenerator::visit(InterfaceBlockReference &iface) r_composite_base = iface.declaration; r_expression_result_id = 0; + r_constant_result = false; } void SpirVGenerator::generate_composite_access(TypeDeclaration &result_type) @@ -560,6 +594,7 @@ void SpirVGenerator::generate_composite_access(TypeDeclaration &result_type) writer.write(*i); end_expression(opcode); + r_constant_result = false; if(r_composite_base) { if(assignment_source_id) @@ -653,6 +688,7 @@ void SpirVGenerator::visit(Swizzle &swizzle) writer.write(swizzle.components[i]); end_expression(OP_VECTOR_SHUFFLE); } + r_constant_result = false; } void SpirVGenerator::visit(UnaryExpression &unary) @@ -665,7 +701,7 @@ void SpirVGenerator::visit(UnaryExpression &unary) return; BasicTypeDeclaration &basic = dynamic_cast(*unary.expression->type); - BasicTypeDeclaration &elem = get_element_type(basic); + BasicTypeDeclaration &elem = *get_element_type(basic); if(constant_expression && elem.kind!=BasicTypeDeclaration::BOOL && elem.kind!=BasicTypeDeclaration::INT) /* SPIR-V allows constant operations on floating-point values only for @@ -675,6 +711,7 @@ void SpirVGenerator::visit(UnaryExpression &unary) Id result_type_id = get_id(*unary.type); Opcode opcode = OP_NOP; + r_constant_result = false; if(oper=='!') opcode = OP_LOGICAL_NOT; else if(oper=='~') @@ -747,7 +784,7 @@ void SpirVGenerator::visit(BinaryExpression &binary) BasicTypeDeclaration &basic_left = dynamic_cast(*binary.left->type); BasicTypeDeclaration &basic_right = dynamic_cast(*binary.right->type); // Expression resolver ensures that element types are the same - BasicTypeDeclaration &elem = get_element_type(basic_left); + BasicTypeDeclaration &elem = *get_element_type(basic_left); if(constant_expression && elem.kind!=BasicTypeDeclaration::BOOL && elem.kind!=BasicTypeDeclaration::INT) /* SPIR-V allows constant operations on floating-point values only for @@ -763,12 +800,20 @@ void SpirVGenerator::visit(BinaryExpression &binary) Opcode opcode = OP_NOP; bool swap_operands = false; + r_constant_result = false; + char oper2 = binary.oper->token[1]; if((oper=='<' || oper=='>') && oper2!=oper) { if(basic_left.kind==BasicTypeDeclaration::INT) - opcode = (oper=='<' ? (oper2=='=' ? OP_S_LESS_THAN_EQUAL : OP_S_LESS_THAN) : - (oper2=='=' ? OP_S_GREATER_THAN_EQUAL : OP_S_GREATER_THAN)); + { + if(basic_left.sign) + opcode = (oper=='<' ? (oper2=='=' ? OP_S_LESS_THAN_EQUAL : OP_S_LESS_THAN) : + (oper2=='=' ? OP_S_GREATER_THAN_EQUAL : OP_S_GREATER_THAN)); + else + opcode = (oper=='<' ? (oper2=='=' ? OP_U_LESS_THAN_EQUAL : OP_U_LESS_THAN) : + (oper2=='=' ? OP_U_GREATER_THAN_EQUAL : OP_U_GREATER_THAN)); + } else if(basic_left.kind==BasicTypeDeclaration::FLOAT) opcode = (oper=='<' ? (oper2=='=' ? OP_F_ORD_LESS_THAN_EQUAL : OP_F_ORD_LESS_THAN) : (oper2=='=' ? OP_F_ORD_GREATER_THAN_EQUAL : OP_F_ORD_GREATER_THAN)); @@ -833,12 +878,17 @@ void SpirVGenerator::visit(BinaryExpression &binary) else if(oper=='>' && oper2==oper && elem.kind==BasicTypeDeclaration::INT) opcode = OP_SHIFT_RIGHT_ARITHMETIC; else if(oper=='%' && elem.kind==BasicTypeDeclaration::INT) - opcode = OP_S_MOD; + opcode = (elem.sign ? OP_S_MOD : OP_U_MOD); else if(oper=='+' || oper=='-' || oper=='*' || oper=='/') { Opcode elem_op = OP_NOP; if(elem.kind==BasicTypeDeclaration::INT) - elem_op = (oper=='+' ? OP_I_ADD : oper=='-' ? OP_I_SUB : oper=='*' ? OP_I_MUL : OP_S_DIV); + { + if(oper=='/') + elem_op = (elem.sign ? OP_S_DIV : OP_U_DIV); + else + elem_op = (oper=='+' ? OP_I_ADD : oper=='-' ? OP_I_SUB : OP_I_MUL); + } else if(elem.kind==BasicTypeDeclaration::FLOAT) elem_op = (oper=='+' ? OP_F_ADD : oper=='-' ? OP_F_SUB : oper=='*' ? OP_F_MUL : OP_F_DIV); @@ -946,6 +996,7 @@ void SpirVGenerator::visit(Assignment &assign) SetForScope set_assign(assignment_source_id, r_expression_result_id); assign.left->visit(*this); + r_constant_result = false; } void SpirVGenerator::visit(TernaryExpression &ternary) @@ -993,13 +1044,13 @@ void SpirVGenerator::visit(TernaryExpression &ternary) writer.write(false_result_id); writer.write(false_label_id); end_expression(OP_PHI); + + r_constant_result = false; } void SpirVGenerator::visit(FunctionCall &call) { - if(constant_expression) - throw internal_error("function call in constant expression"); - else if(assignment_source_id) + if(assignment_source_id) throw internal_error("assignment to function call"); else if(composite_access) return visit_isolated(call); @@ -1008,27 +1059,33 @@ 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) { (*i)->visit(*this); argument_ids.push_back(r_expression_result_id); + all_args_const &= r_constant_result; } + if(constant_expression && (!call.constructor || !all_args_const)) + throw internal_error("function call in constant expression"); + Id result_type_id = get_id(*call.type); + r_constant_result = false; if(call.constructor) - visit_constructor(call, argument_ids); + visit_constructor(call, argument_ids, all_args_const); 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)) { - BasicTypeDeclaration &elem_arg = get_element_type(*basic_arg); + BasicTypeDeclaration &elem_arg = *get_element_type(*basic_arg); switch(elem_arg.kind) { case BasicTypeDeclaration::BOOL: arg_types += 'b'; break; - case BasicTypeDeclaration::INT: arg_types += 'i'; break; + case BasicTypeDeclaration::INT: arg_types += (elem_arg.sign ? 'i' : 'u'); break; case BasicTypeDeclaration::FLOAT: arg_types += 'f'; break; default: arg_types += '?'; } @@ -1039,6 +1096,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; @@ -1087,7 +1147,7 @@ void SpirVGenerator::visit(FunctionCall &call) } } -void SpirVGenerator::visit_constructor(FunctionCall &call, const vector &argument_ids) +void SpirVGenerator::visit_constructor(FunctionCall &call, const vector &argument_ids, bool all_args_const) { Id result_type_id = get_id(*call.type); @@ -1101,9 +1161,11 @@ void SpirVGenerator::visit_constructor(FunctionCall &call, const vector &arg return; } - BasicTypeDeclaration &elem = get_element_type(*basic); + SetFlag set_const(constant_expression, constant_expression || all_args_const); + + BasicTypeDeclaration &elem = *get_element_type(*basic); BasicTypeDeclaration &basic_arg0 = dynamic_cast(*call.arguments[0]->type); - BasicTypeDeclaration &elem_arg0 = get_element_type(basic_arg0); + BasicTypeDeclaration &elem_arg0 = *get_element_type(basic_arg0); if(basic->kind==BasicTypeDeclaration::MATRIX) { @@ -1118,7 +1180,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 &arg } else if(elem.kind==BasicTypeDeclaration::BOOL) { + if(constant_expression) + throw internal_error("unconverted constant"); + // Conversion to boolean is implemented as comparing against zero. Id number_type_id = get_id(elem_arg0); Id zero_id = (elem_arg0.kind==BasicTypeDeclaration::FLOAT ? @@ -1158,6 +1223,9 @@ void SpirVGenerator::visit_constructor(FunctionCall &call, const vector &arg } else if(elem_arg0.kind==BasicTypeDeclaration::BOOL) { + if(constant_expression) + throw internal_error("unconverted constant"); + /* Conversion from boolean is implemented as selecting from zero or one. */ Id number_type_id = get_id(elem); @@ -1179,12 +1247,17 @@ void SpirVGenerator::visit_constructor(FunctionCall &call, const vector &arg } else { + if(constant_expression) + throw internal_error("unconverted constant"); + // Scalar or vector conversion between types of equal size. Opcode opcode; if(elem.kind==BasicTypeDeclaration::INT && elem_arg0.kind==BasicTypeDeclaration::FLOAT) - opcode = OP_CONVERT_F_TO_S; + opcode = (elem.sign ? OP_CONVERT_F_TO_S : OP_CONVERT_F_TO_U); else if(elem.kind==BasicTypeDeclaration::FLOAT && elem_arg0.kind==BasicTypeDeclaration::INT) - opcode = OP_CONVERT_S_TO_F; + opcode = (elem_arg0.sign ? OP_CONVERT_S_TO_F : OP_CONVERT_U_TO_F); + else if(elem.kind==BasicTypeDeclaration::INT && elem_arg0.kind==BasicTypeDeclaration::INT) + opcode = OP_BITCAST; else throw internal_error("invalid conversion"); @@ -1291,8 +1364,6 @@ 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); @@ -1335,7 +1406,7 @@ bool SpirVGenerator::check_standard_type(BasicTypeDeclaration &basic) if((elem->kind==BasicTypeDeclaration::INT || elem->kind==BasicTypeDeclaration::FLOAT) && elem->size!=32) return false; - Id standard_id = get_standard_type_id(elem->kind, (basic.kind==BasicTypeDeclaration::VECTOR ? basic.size : 1)); + Id standard_id = get_standard_type_id(elem->kind, (basic.kind==BasicTypeDeclaration::VECTOR ? basic.size : 1), elem->sign); insert_unique(declared_ids, &basic, Declaration(standard_id, 0)); writer.write_op_name(standard_id, basic.name); @@ -1358,7 +1429,7 @@ void SpirVGenerator::visit(BasicTypeDeclaration &basic) switch(basic.kind) { case BasicTypeDeclaration::INT: - writer.write_op(content.globals, OP_TYPE_INT, type_id, basic.size, 1); + writer.write_op(content.globals, OP_TYPE_INT, type_id, basic.size, basic.sign); break; case BasicTypeDeclaration::FLOAT: writer.write_op(content.globals, OP_TYPE_FLOAT, type_id, basic.size); @@ -1525,6 +1596,7 @@ void SpirVGenerator::visit(VariableDeclaration &var) { SetFlag set_const(constant_expression, !current_function); r_expression_result_id = 0; + r_constant_result = false; var.init_expression->visit(*this); init_id = r_expression_result_id; } @@ -1552,7 +1624,10 @@ void SpirVGenerator::visit(VariableDeclaration &var) } 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); @@ -1655,8 +1730,14 @@ void SpirVGenerator::visit_entry_point(FunctionDeclaration &func, Id func_id) 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; @@ -1755,6 +1836,8 @@ void SpirVGenerator::visit(Iteration &iter) if(iter.init_statement) iter.init_statement->visit(*this); + variable_load_ids.clear(); + Id header_id = next_id++; Id continue_id = next_id++; Id merge_block_id = next_id++; @@ -1782,7 +1865,6 @@ void SpirVGenerator::visit(Iteration &iter) writer.write_op(content.function_body, OP_BRANCH, header_id); writer.write_op_label(merge_block_id); - prune_loads(header_id); reachable = true; } @@ -1812,6 +1894,19 @@ void SpirVGenerator::visit(Jump &jump) } +SpirVGenerator::TypeKey::TypeKey(BasicTypeDeclaration::Kind kind, bool sign): + type_id(0) +{ + switch(kind) + { + case BasicTypeDeclaration::VOID: detail = 'v'; break; + case BasicTypeDeclaration::BOOL: detail = 'b'; break; + case BasicTypeDeclaration::INT: detail = (sign ? 'i' : 'u'); break; + case BasicTypeDeclaration::FLOAT: detail = 'f'; break; + default: throw invalid_argument("TypeKey::TypeKey"); + } +} + bool SpirVGenerator::TypeKey::operator<(const TypeKey &other) const { if(type_id!=other.type_id)