X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fglsl%2Fspirv.cpp;h=07d4eb072c0989eb1745405aae0c85ea2ae59fc7;hp=036446f5bab630d83613f7c97e774c3b1dd7bb30;hb=0585e361d8714ac4efc3ae3e1d5c8c9aa8841c34;hpb=55e3f2d494d939280a4ea48676fd17ca2342b457 diff --git a/source/glsl/spirv.cpp b/source/glsl/spirv.cpp index 036446f5..07d4eb07 100644 --- a/source/glsl/spirv.cpp +++ b/source/glsl/spirv.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "reflect.h" @@ -11,149 +12,139 @@ 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) +void SpirVGenerator::apply(Module &module, const Features &f) { + features = f; 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,7 +228,7 @@ 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); + auto i = declared_ids.find(&node); if(i!=declared_ids.end()) { if(i->second.type_id) @@ -253,7 +244,7 @@ SpirVGenerator::Id SpirVGenerator::allocate_id(Node &node, Id type_id) SpirVGenerator::Id SpirVGenerator::allocate_forward_id(Node &node) { - map::iterator i = declared_ids.find(&node); + auto i = declared_ids.find(&node); if(i!=declared_ids.end()) return i->second.id; @@ -343,14 +334,14 @@ 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); } -SpirVGenerator::Id SpirVGenerator::get_array_type_id(TypeDeclaration &base_type, Id size_id) +SpirVGenerator::Id SpirVGenerator::get_array_type_id(TypeDeclaration &base_type, Id size_id, bool extended_align) { Id base_type_id = get_id(base_type); - Id &array_type_id = array_type_ids[TypeKey(base_type_id, size_id)]; + Id &array_type_id = array_type_ids[TypeKey(base_type_id, extended_align*0x400000 | size_id)]; if(!array_type_id) { array_type_id = next_id++; @@ -360,6 +351,8 @@ SpirVGenerator::Id SpirVGenerator::get_array_type_id(TypeDeclaration &base_type, writer.write_op(content.globals, OP_TYPE_RUNTIME_ARRAY, array_type_id, base_type_id); unsigned stride = MemoryRequirementsCalculator().apply(base_type).stride; + if(extended_align) + stride = (stride+15)&~15U; writer.write_op_decorate(array_type_id, DECO_ARRAY_STRIDE, stride); } @@ -392,7 +385,7 @@ SpirVGenerator::Id SpirVGenerator::get_variable_type_id(const VariableDeclaratio } else size_id = get_constant_id(get_standard_type_id(BasicTypeDeclaration::INT, 1), 1); - return get_array_type_id(*basic->base_type, size_id); + return get_array_type_id(*basic->base_type, size_id, true); } return get_id(*var.type_declaration); @@ -411,7 +404,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++); @@ -497,8 +490,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) @@ -528,8 +521,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) { @@ -562,13 +562,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"); @@ -580,18 +580,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; @@ -693,6 +693,9 @@ void SpirVGenerator::visit(Swizzle &swizzle) void SpirVGenerator::visit(UnaryExpression &unary) { + if(composite_access) + return visit_isolated(unary); + unary.expression->visit(*this); char oper = unary.oper->token[0]; @@ -777,6 +780,8 @@ void SpirVGenerator::visit(BinaryExpression &binary) visit_isolated(*binary.right); return visit_composite(*binary.left, 0x400000|r_expression_result_id, *binary.type); } + else if(composite_access) + return visit_isolated(binary); if(assignment_source_id) throw internal_error("invalid binary expression in assignment target"); @@ -1001,6 +1006,8 @@ void SpirVGenerator::visit(Assignment &assign) void SpirVGenerator::visit(TernaryExpression &ternary) { + if(composite_access) + return visit_isolated(ternary); if(constant_expression) { ternary.condition->visit(*this); @@ -1031,11 +1038,13 @@ void SpirVGenerator::visit(TernaryExpression &ternary) writer.write_op_label(true_label_id); ternary.true_expr->visit(*this); Id true_result_id = r_expression_result_id; + true_label_id = writer.get_current_block(); writer.write_op(content.function_body, OP_BRANCH, merge_block_id); writer.write_op_label(false_label_id); ternary.false_expr->visit(*this); Id false_result_id = r_expression_result_id; + false_label_id = writer.get_current_block(); writer.write_op_label(merge_block_id); r_expression_result_id = begin_expression(OP_PHI, get_id(*ternary.type), 4); @@ -1060,9 +1069,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; } @@ -1078,8 +1087,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) @@ -1096,6 +1105,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; @@ -1132,14 +1144,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); } } @@ -1281,6 +1293,40 @@ void SpirVGenerator::visit_builtin_matrix_comp_mult(FunctionCall &call, const ve r_expression_result_id = write_construct(get_id(*call.type), column_ids, n_columns); } +void SpirVGenerator::visit_builtin_texture_query(FunctionCall &call, const vector &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) @@ -1361,14 +1407,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); } @@ -1385,11 +1429,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; } @@ -1467,6 +1511,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) @@ -1489,9 +1534,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; @@ -1509,14 +1554,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); } } @@ -1534,23 +1578,13 @@ 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); } void SpirVGenerator::visit(VariableDeclaration &var) { - const vector *layout_ql = (var.layout ? &var.layout->qualifiers : 0); - - 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; - } - Id type_id = get_variable_type_id(var); Id var_id; @@ -1559,18 +1593,25 @@ void SpirVGenerator::visit(VariableDeclaration &var) if(!var.init_expression) throw internal_error("const variable without initializer"); + int spec_id = get_layout_value(var.layout.get(), "constant_id"); + Id *spec_var_id = (spec_id>=0 ? &declared_spec_ids[spec_id] : 0); + if(spec_id>=0 && *spec_var_id) + { + insert_unique(declared_ids, &var, Declaration(*spec_var_id, type_id)); + return; + } + SetFlag set_const(constant_expression); SetFlag set_spec(spec_constant, spec_id>=0); r_expression_result_id = 0; var.init_expression->visit(*this); var_id = r_expression_result_id; insert_unique(declared_ids, &var, Declaration(var_id, type_id)); - writer.write_op_decorate(var_id, DECO_SPEC_ID, spec_id); - - /* It's unclear what should be done if a specialization constant is - initialized with anything other than a literal. GLSL doesn't seem to - prohibit that but SPIR-V says OpSpecConstantOp can't be updated via - specialization. */ + if(spec_id>=0) + { + writer.write_op_decorate(var_id, DECO_SPEC_ID, spec_id); + *spec_var_id = var_id; + } } else { @@ -1609,18 +1650,23 @@ void SpirVGenerator::visit(VariableDeclaration &var) writer.write(init_id); writer.end_op(OP_VARIABLE); - if(layout_ql) + if(var.layout) { - for(vector::const_iterator i=layout_ql->begin(); i!=layout_ql->end(); ++i) + for(const Layout::Qualifier &q: var.layout->qualifiers) { - 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) { @@ -1634,10 +1680,12 @@ void SpirVGenerator::visit(VariableDeclaration &var) void SpirVGenerator::visit(InterfaceBlock &iface) { - StorageClass storage = get_interface_storage(iface.interface, true); + bool push_const = has_layout_qualifier(iface.layout.get(), "push_constant"); + + StorageClass storage = (push_const ? STORAGE_PUSH_CONSTANT : get_interface_storage(iface.interface, true)); Id type_id; if(iface.array) - type_id = get_array_type_id(*iface.struct_declaration, 0); + type_id = get_array_type_id(*iface.struct_declaration, 0, true); else type_id = get_id(*iface.struct_declaration); Id ptr_type_id = get_pointer_type_id(type_id, storage); @@ -1662,10 +1710,13 @@ 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); + for(const Layout::Qualifier &q: iface.layout->qualifiers) + { + if(q.name=="set") + writer.write_op_decorate(block_id, DECO_DESCRIPTOR_SET, q.value); + else if(q.name=="binding") + writer.write_op_decorate(block_id, DECO_BINDING, q.value); + } } } @@ -1683,46 +1734,48 @@ 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); if(stage->type==Stage::FRAGMENT) - writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, EXEC_ORIGIN_LOWER_LEFT); + { + SpirVExecutionMode origin = (features.target_api==VULKAN ? EXEC_ORIGIN_UPPER_LEFT : EXEC_ORIGIN_LOWER_LEFT); + writer.write_op(content.exec_modes, OP_EXECUTION_MODE, func_id, origin); + } 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); } } } @@ -1741,8 +1794,8 @@ void SpirVGenerator::visit(FunctionDeclaration &func) 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]; @@ -1752,8 +1805,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); @@ -1780,11 +1833,12 @@ void SpirVGenerator::visit(FunctionDeclaration &func) variable_load_ids[func.parameters[i].get()] = param_id; } + reachable = true; writer.begin_function_body(next_id++); SetForScope set_func(current_function, &func); func.body.visit(*this); - if(writer.has_current_block()) + if(writer.get_current_block()) { if(!reachable) writer.write_op(content.function_body, OP_UNREACHABLE); @@ -1811,9 +1865,11 @@ void SpirVGenerator::visit(Conditional &cond) writer.write_op(content.function_body, OP_SELECTION_MERGE, merge_block_id, 0); // Selection control (none) writer.write_op(content.function_body, OP_BRANCH_CONDITIONAL, r_expression_result_id, true_label_id, false_label_id); + std::map saved_load_ids = variable_load_ids; + writer.write_op_label(true_label_id); cond.body.visit(*this); - if(writer.has_current_block()) + if(writer.get_current_block()) writer.write_op(content.function_body, OP_BRANCH, merge_block_id); bool reachable_if_true = reachable; @@ -1821,6 +1877,7 @@ void SpirVGenerator::visit(Conditional &cond) reachable = true; if(!cond.else_body.body.empty()) { + swap(saved_load_ids, variable_load_ids); writer.write_op_label(false_label_id); cond.else_body.visit(*this); reachable |= reachable_if_true; @@ -1835,7 +1892,9 @@ void SpirVGenerator::visit(Iteration &iter) if(iter.init_statement) iter.init_statement->visit(*this); - variable_load_ids.clear(); + for(Node *n: AssignmentCollector().apply(iter)) + if(VariableDeclaration *var = dynamic_cast(n)) + variable_load_ids.erase(var); Id header_id = next_id++; Id continue_id = next_id++; @@ -1864,6 +1923,7 @@ 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; }