]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/spirv.cpp
Add support for uint types in GLSL
[libs/gl.git] / source / glsl / spirv.cpp
index 2220dcc1f012c00655fb207e841787b76be09238..52885342b004492a11cb8e4bb8c61d54801cea79 100644 (file)
@@ -46,13 +46,17 @@ const SpirVGenerator::BuiltinFunctionInfo SpirVGenerator::builtin_functions[] =
        { "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 },
@@ -73,25 +77,36 @@ const SpirVGenerator::BuiltinFunctionInfo SpirVGenerator::builtin_functions[] =
        { "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 },
@@ -250,6 +265,8 @@ SpirVGenerator::ConstantKey SpirVGenerator::get_constant_key(Id type_id, const V
                return ConstantKey(type_id, value.value<bool>());
        else if(value.check_type<int>())
                return ConstantKey(type_id, value.value<int>());
+       else if(value.check_type<unsigned>())
+               return ConstantKey(type_id, value.value<unsigned>());
        else if(value.check_type<float>())
                return ConstantKey(type_id, value.value<float>());
        else
@@ -281,10 +298,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<unsigned>(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 +312,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 +323,7 @@ SpirVGenerator::Id SpirVGenerator::get_standard_type_id(BasicTypeDeclaration::Ki
 
 bool SpirVGenerator::is_scalar_type(Id type_id, BasicTypeDeclaration::Kind kind) const
 {
-       map<TypeKey, Id>::const_iterator i = standard_type_ids.find(TypeKey(0, kind));
+       map<TypeKey, Id>::const_iterator i = standard_type_ids.find(TypeKey(kind, true));
        return (i!=standard_type_ids.end() && i->second==type_id);
 }
 
@@ -769,8 +786,14 @@ void SpirVGenerator::visit(BinaryExpression &binary)
        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));
@@ -835,12 +858,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);
 
@@ -1036,7 +1064,7 @@ void SpirVGenerator::visit(FunctionCall &call)
                                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 += '?';
                                }
@@ -1201,9 +1229,11 @@ void SpirVGenerator::visit_constructor(FunctionCall &call, const vector<Id> &arg
                // 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");
 
@@ -1354,7 +1384,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);
 
@@ -1377,7 +1407,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);
@@ -1831,6 +1861,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)