]> git.tdb.fi Git - libs/gl.git/commitdiff
Add support for uint types in GLSL
authorMikko Rasa <tdb@tdb.fi>
Tue, 20 Apr 2021 16:26:16 +0000 (19:26 +0300)
committerMikko Rasa <tdb@tdb.fi>
Tue, 20 Apr 2021 17:19:04 +0000 (20:19 +0300)
15 files changed:
builtin_data/_builtin.glsl
scripts/builtin_funcs.py
source/glsl/builtin.cpp
source/glsl/optimize.cpp
source/glsl/parser.cpp
source/glsl/reflect.cpp
source/glsl/resolve.cpp
source/glsl/resolve.h
source/glsl/spirv.cpp
source/glsl/spirv.h
source/glsl/spirvconstants.h
source/glsl/syntax.cpp
source/glsl/syntax.h
source/glsl/tokenizer.cpp
tests/glsl/unsigned_int.glsl [new file with mode: 0644]

index 3bf722cd441b13a627d58e8b8cb85b9841fd5ef8..94a7ca696c4f9d5187f15a5cd8abbc9656b5c737 100644 (file)
@@ -18,6 +18,10 @@ typedef vector(2) int ivec2;
 typedef vector(3) int ivec3;
 typedef vector(4) int ivec4;
 
+typedef vector(2) uint uvec2;
+typedef vector(3) uint uvec3;
+typedef vector(4) uint uvec4;
+
 typedef vector(2) bool bvec2;
 typedef vector(3) bool bvec3;
 typedef vector(4) bool bvec4;
@@ -180,12 +184,19 @@ int min(int x, int y);
 ivec2 min(ivec2 x, ivec2 y);
 ivec3 min(ivec3 x, ivec3 y);
 ivec4 min(ivec4 x, ivec4 y);
+uint min(uint x, uint y);
+uvec2 min(uvec2 x, uvec2 y);
+uvec3 min(uvec3 x, uvec3 y);
+uvec4 min(uvec4 x, uvec4 y);
 vec2 min(vec2 x, float y) { return min(x, vec2(y)); }
 vec3 min(vec3 x, float y) { return min(x, vec3(y)); }
 vec4 min(vec4 x, float y) { return min(x, vec4(y)); }
 ivec2 min(ivec2 x, int y) { return min(x, ivec2(y)); }
 ivec3 min(ivec3 x, int y) { return min(x, ivec3(y)); }
 ivec4 min(ivec4 x, int y) { return min(x, ivec4(y)); }
+uvec2 min(uvec2 x, uint y) { return min(x, uvec2(y)); }
+uvec3 min(uvec3 x, uint y) { return min(x, uvec3(y)); }
+uvec4 min(uvec4 x, uint y) { return min(x, uvec4(y)); }
 float max(float x, float y);
 vec2 max(vec2 x, vec2 y);
 vec3 max(vec3 x, vec3 y);
@@ -194,12 +205,19 @@ int max(int x, int y);
 ivec2 max(ivec2 x, ivec2 y);
 ivec3 max(ivec3 x, ivec3 y);
 ivec4 max(ivec4 x, ivec4 y);
+uint max(uint x, uint y);
+uvec2 max(uvec2 x, uvec2 y);
+uvec3 max(uvec3 x, uvec3 y);
+uvec4 max(uvec4 x, uvec4 y);
 vec2 max(vec2 x, float y) { return max(x, vec2(y)); }
 vec3 max(vec3 x, float y) { return max(x, vec3(y)); }
 vec4 max(vec4 x, float y) { return max(x, vec4(y)); }
 ivec2 max(ivec2 x, int y) { return max(x, ivec2(y)); }
 ivec3 max(ivec3 x, int y) { return max(x, ivec3(y)); }
 ivec4 max(ivec4 x, int y) { return max(x, ivec4(y)); }
+uvec2 max(uvec2 x, uint y) { return max(x, uvec2(y)); }
+uvec3 max(uvec3 x, uint y) { return max(x, uvec3(y)); }
+uvec4 max(uvec4 x, uint y) { return max(x, uvec4(y)); }
 float clamp(float x, float minVal, float maxVal);
 vec2 clamp(vec2 x, vec2 minVal, vec2 maxVal);
 vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal);
@@ -208,12 +226,19 @@ int clamp(int x, int minVal, int maxVal);
 ivec2 clamp(ivec2 x, ivec2 minVal, ivec2 maxVal);
 ivec3 clamp(ivec3 x, ivec3 minVal, ivec3 maxVal);
 ivec4 clamp(ivec4 x, ivec4 minVal, ivec4 maxVal);
+uint clamp(uint x, uint minVal, uint maxVal);
+uvec2 clamp(uvec2 x, uvec2 minVal, uvec2 maxVal);
+uvec3 clamp(uvec3 x, uvec3 minVal, uvec3 maxVal);
+uvec4 clamp(uvec4 x, uvec4 minVal, uvec4 maxVal);
 vec2 clamp(vec2 x, float minVal, float maxVal) { return clamp(x, vec2(minVal), vec2(maxVal)); }
 vec3 clamp(vec3 x, float minVal, float maxVal) { return clamp(x, vec3(minVal), vec3(maxVal)); }
 vec4 clamp(vec4 x, float minVal, float maxVal) { return clamp(x, vec4(minVal), vec4(maxVal)); }
 ivec2 clamp(ivec2 x, int minVal, int maxVal) { return clamp(x, ivec2(minVal), ivec2(maxVal)); }
 ivec3 clamp(ivec3 x, int minVal, int maxVal) { return clamp(x, ivec3(minVal), ivec3(maxVal)); }
 ivec4 clamp(ivec4 x, int minVal, int maxVal) { return clamp(x, ivec4(minVal), ivec4(maxVal)); }
+uvec2 clamp(uvec2 x, uint minVal, uint maxVal) { return clamp(x, uvec2(minVal), uvec2(maxVal)); }
+uvec3 clamp(uvec3 x, uint minVal, uint maxVal) { return clamp(x, uvec3(minVal), uvec3(maxVal)); }
+uvec4 clamp(uvec4 x, uint minVal, uint maxVal) { return clamp(x, uvec4(minVal), uvec4(maxVal)); }
 float mix(float x, float y, float a);
 vec2 mix(vec2 x, vec2 y, vec2 a);
 vec3 mix(vec3 x, vec3 y, vec3 a);
@@ -230,6 +255,10 @@ int mix(int x, int y, bool a);
 ivec2 mix(ivec2 x, ivec2 y, bvec2 a);
 ivec3 mix(ivec3 x, ivec3 y, bvec3 a);
 ivec4 mix(ivec4 x, ivec4 y, bvec4 a);
+uint mix(uint x, uint y, bool a);
+uvec2 mix(uvec2 x, uvec2 y, bvec2 a);
+uvec3 mix(uvec3 x, uvec3 y, bvec3 a);
+uvec4 mix(uvec4 x, uvec4 y, bvec4 a);
 float step(float edge, float x);
 vec2 step(vec2 edge, vec2 x);
 vec3 step(vec3 edge, vec3 x);
@@ -324,36 +353,54 @@ bvec4 lessThan(vec4 x, vec4 y);
 bvec2 lessThan(ivec2 x, ivec2 y);
 bvec3 lessThan(ivec3 x, ivec3 y);
 bvec4 lessThan(ivec4 x, ivec4 y);
+bvec2 lessThan(uvec2 x, uvec2 y);
+bvec3 lessThan(uvec3 x, uvec3 y);
+bvec4 lessThan(uvec4 x, uvec4 y);
 bvec2 lessThanEqual(vec2 x, vec2 y);
 bvec3 lessThanEqual(vec3 x, vec3 y);
 bvec4 lessThanEqual(vec4 x, vec4 y);
 bvec2 lessThanEqual(ivec2 x, ivec2 y);
 bvec3 lessThanEqual(ivec3 x, ivec3 y);
 bvec4 lessThanEqual(ivec4 x, ivec4 y);
+bvec2 lessThanEqual(uvec2 x, uvec2 y);
+bvec3 lessThanEqual(uvec3 x, uvec3 y);
+bvec4 lessThanEqual(uvec4 x, uvec4 y);
 bvec2 greaterThan(vec2 x, vec2 y);
 bvec3 greaterThan(vec3 x, vec3 y);
 bvec4 greaterThan(vec4 x, vec4 y);
 bvec2 greaterThan(ivec2 x, ivec2 y);
 bvec3 greaterThan(ivec3 x, ivec3 y);
 bvec4 greaterThan(ivec4 x, ivec4 y);
+bvec2 greaterThan(uvec2 x, uvec2 y);
+bvec3 greaterThan(uvec3 x, uvec3 y);
+bvec4 greaterThan(uvec4 x, uvec4 y);
 bvec2 greaterThanEqual(vec2 x, vec2 y);
 bvec3 greaterThanEqual(vec3 x, vec3 y);
 bvec4 greaterThanEqual(vec4 x, vec4 y);
 bvec2 greaterThanEqual(ivec2 x, ivec2 y);
 bvec3 greaterThanEqual(ivec3 x, ivec3 y);
 bvec4 greaterThanEqual(ivec4 x, ivec4 y);
+bvec2 greaterThanEqual(uvec2 x, uvec2 y);
+bvec3 greaterThanEqual(uvec3 x, uvec3 y);
+bvec4 greaterThanEqual(uvec4 x, uvec4 y);
 bvec2 equal(vec2 x, vec2 y);
 bvec3 equal(vec3 x, vec3 y);
 bvec4 equal(vec4 x, vec4 y);
 bvec2 equal(ivec2 x, ivec2 y);
 bvec3 equal(ivec3 x, ivec3 y);
 bvec4 equal(ivec4 x, ivec4 y);
+bvec2 equal(uvec2 x, uvec2 y);
+bvec3 equal(uvec3 x, uvec3 y);
+bvec4 equal(uvec4 x, uvec4 y);
 bvec2 notEqual(vec2 x, vec2 y);
 bvec3 notEqual(vec3 x, vec3 y);
 bvec4 notEqual(vec4 x, vec4 y);
 bvec2 notEqual(ivec2 x, ivec2 y);
 bvec3 notEqual(ivec3 x, ivec3 y);
 bvec4 notEqual(ivec4 x, ivec4 y);
+bvec2 notEqual(uvec2 x, uvec2 y);
+bvec3 notEqual(uvec3 x, uvec3 y);
+bvec4 notEqual(uvec4 x, uvec4 y);
 bool any(bvec2 x);
 bool any(bvec3 x);
 bool any(bvec4 x);
@@ -367,26 +414,50 @@ int bitfieldExtract(int value, int offset, int bits);
 ivec2 bitfieldExtract(ivec2 value, int offset, int bits);
 ivec3 bitfieldExtract(ivec3 value, int offset, int bits);
 ivec4 bitfieldExtract(ivec4 value, int offset, int bits);
+uint bitfieldExtract(uint value, int offset, int bits);
+uvec2 bitfieldExtract(uvec2 value, int offset, int bits);
+uvec3 bitfieldExtract(uvec3 value, int offset, int bits);
+uvec4 bitfieldExtract(uvec4 value, int offset, int bits);
 int bitfieldInsert(int value, int insert, int offset, int bits);
 ivec2 bitfieldInsert(ivec2 value, ivec2 insert, int offset, int bits);
 ivec3 bitfieldInsert(ivec3 value, ivec3 insert, int offset, int bits);
 ivec4 bitfieldInsert(ivec4 value, ivec4 insert, int offset, int bits);
+uint bitfieldInsert(uint value, uint insert, int offset, int bits);
+uvec2 bitfieldInsert(uvec2 value, uvec2 insert, int offset, int bits);
+uvec3 bitfieldInsert(uvec3 value, uvec3 insert, int offset, int bits);
+uvec4 bitfieldInsert(uvec4 value, uvec4 insert, int offset, int bits);
 int bitfieldReverse(int value);
 ivec2 bitfieldReverse(ivec2 value);
 ivec3 bitfieldReverse(ivec3 value);
 ivec4 bitfieldReverse(ivec4 value);
+uint bitfieldReverse(uint value);
+uvec2 bitfieldReverse(uvec2 value);
+uvec3 bitfieldReverse(uvec3 value);
+uvec4 bitfieldReverse(uvec4 value);
 int bitCount(int value);
 ivec2 bitCount(ivec2 value);
 ivec3 bitCount(ivec3 value);
 ivec4 bitCount(ivec4 value);
+uint bitCount(uint value);
+uvec2 bitCount(uvec2 value);
+uvec3 bitCount(uvec3 value);
+uvec4 bitCount(uvec4 value);
 int findLSB(int value);
 ivec2 findLSB(ivec2 value);
 ivec3 findLSB(ivec3 value);
 ivec4 findLSB(ivec4 value);
+int findLSB(uint value);
+ivec2 findLSB(uvec2 value);
+ivec3 findLSB(uvec3 value);
+ivec4 findLSB(uvec4 value);
 int findMSB(int value);
 ivec2 findMSB(ivec2 value);
 ivec3 findMSB(ivec3 value);
 ivec4 findMSB(ivec4 value);
+int findMSB(uint value);
+ivec2 findMSB(uvec2 value);
+ivec3 findMSB(uvec3 value);
+ivec4 findMSB(uvec4 value);
 int textureSize(sampler1D sampler, int lod);
 ivec2 textureSize(sampler2D sampler, int lod);
 ivec3 textureSize(sampler3D sampler, int lod);
index 3825cb2b216f5e81204d8e8bcfd9fa28e3a00aa0..ef19d54fd9162d9e4bf92cfa94d22dfcac648c83 100755 (executable)
@@ -24,6 +24,10 @@ traits = {
        "ivec2": { "Base": "int", "Dim": 2 },
        "ivec3": { "Base": "int", "Dim": 3 },
        "ivec4": { "Base": "int", "Dim": 4 },
+       "uint": { "Base": "uint", "Dim": 1, "Vec": "uvec" },
+       "uvec2": { "Base": "uint", "Dim": 2 },
+       "uvec3": { "Base": "uint", "Dim": 3 },
+       "uvec4": { "Base": "uint", "Dim": 4 },
        "bool": { "Base": "bool", "Dim": 1, "Vec": "bvec" },
        "bvec2": { "Base": "bool", "Dim": 2 },
        "bvec3": { "Base": "bool", "Dim": 3 },
@@ -43,11 +47,15 @@ float32vectypes = ("vec2", "vec3", "vec4")
 float32types = ("float",)+float32vectypes
 floatvectypes = float32vectypes
 floattypes = float32types
-int32vectypes = ("ivec2", "ivec3", "ivec4")
-int32types = ("int",)+int32vectypes
-signedtypes = floattypes+int32types
-arithmetictypes = signedtypes
-arithmeticvectypes = float32vectypes+int32vectypes
+sint32vectypes = ("ivec2", "ivec3", "ivec4")
+sint32types = ("int",)+sint32vectypes
+signedtypes = floattypes+sint32types
+uint32vectypes = ("uvec2", "uvec3", "uvec4")
+uint32types = ("uint",)+uint32vectypes
+int32types = sint32types+uint32types
+unsignedtypes = uint32types
+arithmetictypes = signedtypes+unsignedtypes
+arithmeticvectypes = float32vectypes+sint32vectypes+uint32vectypes
 boolvectypes = ("bvec2", "bvec3", "bvec4")
 squarematrixtypes = ("mat2", "mat3", "mat4")
 matrixtypes = squarematrixtypes+("mat2x3", "mat3x2", "mat2x4", "mat4x2", "mat3x4", "mat4x3")
index f60d2a8a1d0736ff9d2d171b1a583fd39bedc879..12602707db80ca5043b6582f5b6917422cb2f477 100644 (file)
@@ -54,6 +54,14 @@ Module *get_builtins_module()
                type->kind = BasicTypeDeclaration::INT;
                shared_body.insert(insert_point, type);
 
+               type = new BasicTypeDeclaration;
+               type->source = BUILTIN_SOURCE;
+               type->name = "uint";
+               type->size = 32;
+               type->sign = false;
+               type->kind = BasicTypeDeclaration::INT;
+               shared_body.insert(insert_point, type);
+
                type = new BasicTypeDeclaration;
                type->source = BUILTIN_SOURCE;
                type->name = "float";
index d21512f6c82e4e6bdef3ccbdf38f70cd6e018e66..0139ec5fbec94d4f1c47493549914d8977b2af8e 100644 (file)
@@ -611,6 +611,8 @@ void ConstantFolder::convert_to_result(const Variant &value)
                set_result(static_cast<T>(value.value<bool>()));
        else if(value.check_type<int>())
                set_result(static_cast<T>(value.value<int>()));
+       else if(value.check_type<unsigned>())
+               set_result(static_cast<T>(value.value<unsigned>()));
        else if(value.check_type<float>())
                set_result(static_cast<T>(value.value<float>()));
 }
@@ -640,6 +642,8 @@ void ConstantFolder::visit(RefPtr<Expression> &expr)
                literal->token = (r_constant_value.value<bool>() ? "true" : "false");
        else if(r_constant_value.check_type<int>())
                literal->token = lexical_cast<string>(r_constant_value.value<int>());
+       else if(r_constant_value.check_type<unsigned>())
+               literal->token = lexical_cast<string>(r_constant_value.value<unsigned>())+"u";
        else if(r_constant_value.check_type<float>())
        {
                literal->token = lexical_cast<string>(r_constant_value.value<float>());
@@ -744,11 +748,15 @@ void ConstantFolder::visit(BinaryExpression &binary)
                        set_result(evaluate_logical(oper, left_value.value<bool>(), r_constant_value.value<bool>()));
                else if(!oper2 && left_value.check_type<int>())
                        set_result(evaluate_logical(oper, left_value.value<int>(), r_constant_value.value<int>()));
+               else if(!oper2 && left_value.check_type<unsigned>())
+                       set_result(evaluate_logical(oper, left_value.value<unsigned>(), r_constant_value.value<unsigned>()));
        }
        else if((oper=='<' || oper=='>') && oper2!=oper)
        {
                if(left_value.check_type<int>())
                        set_result(evaluate_relation(binary.oper->token, left_value.value<int>(), r_constant_value.value<int>()));
+               else if(left_value.check_type<unsigned>())
+                       set_result(evaluate_relation(binary.oper->token, left_value.value<unsigned>(), r_constant_value.value<unsigned>()));
                else if(left_value.check_type<float>())
                        set_result(evaluate_relation(binary.oper->token, left_value.value<float>(), r_constant_value.value<float>()));
        }
@@ -756,13 +764,17 @@ void ConstantFolder::visit(BinaryExpression &binary)
        {
                if(left_value.check_type<int>())
                        set_result((left_value.value<int>()==r_constant_value.value<int>()) == (oper=='='));
-               if(left_value.check_type<float>())
+               else if(left_value.check_type<unsigned>())
+                       set_result((left_value.value<unsigned>()==r_constant_value.value<unsigned>()) == (oper=='='));
+               else if(left_value.check_type<float>())
                        set_result((left_value.value<float>()==r_constant_value.value<float>()) == (oper=='='));
        }
        else if(oper=='+' || oper=='-' || oper=='*' || oper=='/')
        {
                if(left_value.check_type<int>())
                        set_result(evaluate_arithmetic(oper, left_value.value<int>(), r_constant_value.value<int>()));
+               else if(left_value.check_type<unsigned>())
+                       set_result(evaluate_arithmetic(oper, left_value.value<unsigned>(), r_constant_value.value<unsigned>()));
                else if(left_value.check_type<float>())
                        set_result(evaluate_arithmetic(oper, left_value.value<float>(), r_constant_value.value<float>()));
        }
@@ -770,6 +782,8 @@ void ConstantFolder::visit(BinaryExpression &binary)
        {
                if(left_value.check_type<int>())
                        set_result(evaluate_int_special_op(oper, left_value.value<int>(), r_constant_value.value<int>()));
+               else if(left_value.check_type<unsigned>())
+                       set_result(evaluate_int_special_op(oper, left_value.value<unsigned>(), r_constant_value.value<unsigned>()));
        }
 }
 
@@ -800,8 +814,10 @@ void ConstantFolder::visit(FunctionCall &call)
 
                        if(basic->kind==BasicTypeDeclaration::BOOL)
                                convert_to_result<bool>(r_constant_value);
-                       else if(basic->kind==BasicTypeDeclaration::INT && basic->size==32)
+                       else if(basic->kind==BasicTypeDeclaration::INT && basic->size==32 && basic->sign)
                                convert_to_result<int>(r_constant_value);
+                       else if(basic->kind==BasicTypeDeclaration::INT && basic->size==32 && !basic->sign)
+                               convert_to_result<unsigned>(r_constant_value);
                        else if(basic->kind==BasicTypeDeclaration::FLOAT && basic->size==32)
                                convert_to_result<float>(r_constant_value);
 
index 72f8ebfa6279982e675b98b9c5364044e90f3150..0512c10b235ea6d384d17e319d9a4a5ce3e5c7b2 100644 (file)
@@ -72,6 +72,7 @@ void Parser::parse_source(const string &name, int index)
                declared_types.insert("void");
                declared_types.insert("bool");
                declared_types.insert("int");
+               declared_types.insert("uint");
                declared_types.insert("float");
        }
 
@@ -536,7 +537,9 @@ RefPtr<Literal> Parser::parse_literal()
        if(isdigit(literal->token[0]))
        {
                // TODO have the tokenizer return the type of the token
-               if(literal->token.back()=='f')
+               if(literal->token.back()=='u')
+                       literal->value = lexical_cast<unsigned>(literal->token.substr(0, literal->token.size()-1));
+               else if(literal->token.back()=='f')
                        literal->value = lexical_cast<float>(literal->token.substr(0, literal->token.size()-1));
                else if(literal->token.find('.')!=string::npos)
                        literal->value = lexical_cast<float>(literal->token);
index c2a913f982acfcb61c6ca7a0289f3233f3d434e9..8c10acccd697c265063d481a8f1a8b055ac492bb 100644 (file)
@@ -33,6 +33,8 @@ bool can_convert(const BasicTypeDeclaration &from, const BasicTypeDeclaration &t
                return from.size<=to.size;
        else if(from.kind!=to.kind)
                return false;
+       else if(from.kind==BasicTypeDeclaration::INT && from.sign!=to.sign)
+               return from.sign && from.size<=to.size;
        else if(is_vector_or_matrix(from) && from.size==to.size)
        {
                BasicTypeDeclaration *from_base = dynamic_cast<BasicTypeDeclaration *>(from.base_type);
@@ -123,7 +125,7 @@ void TypeComparer::visit(BasicTypeDeclaration &basic)
 {
        if(BasicTypeDeclaration *basic1 = multi_visit(basic))
        {
-               if(basic1->kind!=basic.kind || basic1->size!=basic.size)
+               if(basic1->kind!=basic.kind || basic1->size!=basic.size || basic1->sign!=basic.sign)
                        r_result = false;
                else if(basic1->base_type && basic.base_type)
                        compare(*basic1->base_type, *basic.base_type);
index 3f959a7d03bad94db6fe4f7138b00f0fbb546bf7..f2670b53e6805a78f7a2ce6627882299904ff254 100644 (file)
@@ -472,10 +472,10 @@ ExpressionResolver::Compatibility ExpressionResolver::get_compatibility(BasicTyp
                return NOT_COMPATIBLE;
 }
 
-BasicTypeDeclaration *ExpressionResolver::find_type(BasicTypeDeclaration::Kind kind, unsigned size)
+BasicTypeDeclaration *ExpressionResolver::find_type(BasicTypeDeclaration::Kind kind, unsigned size, bool sign)
 {
        for(vector<BasicTypeDeclaration *>::const_iterator i=basic_types.begin(); i!=basic_types.end(); ++i)
-               if((*i)->kind==kind && (*i)->size==size)
+               if((*i)->kind==kind && (*i)->size==size && (*i)->sign==sign)
                        return *i;
        return 0;
 }
@@ -561,7 +561,9 @@ void ExpressionResolver::visit(Literal &literal)
        if(literal.value.check_type<bool>())
                resolve(literal, find_type(BasicTypeDeclaration::BOOL, 1), false);
        else if(literal.value.check_type<int>())
-               resolve(literal, find_type(BasicTypeDeclaration::INT, 32), false);
+               resolve(literal, find_type(BasicTypeDeclaration::INT, 32, true), false);
+       else if(literal.value.check_type<unsigned>())
+               resolve(literal, find_type(BasicTypeDeclaration::INT, 32, false), false);
        else if(literal.value.check_type<float>())
                resolve(literal, find_type(BasicTypeDeclaration::FLOAT, 32), false);
 }
index 69c877fc6e542e24a5fd9edaf382662e2a83243d..633ff11d27b4382e66ce6240847ac84907b54f5a 100644 (file)
@@ -120,7 +120,7 @@ public:
 
 private:
        static Compatibility get_compatibility(BasicTypeDeclaration &, BasicTypeDeclaration &);
-       BasicTypeDeclaration *find_type(BasicTypeDeclaration::Kind, unsigned);
+       BasicTypeDeclaration *find_type(BasicTypeDeclaration::Kind, unsigned, bool = true);
        BasicTypeDeclaration *find_type(BasicTypeDeclaration &, BasicTypeDeclaration::Kind, unsigned);
        void convert_to(RefPtr<Expression> &, BasicTypeDeclaration &);
        bool convert_to_element(RefPtr<Expression> &, BasicTypeDeclaration &);
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)
index 98aa673ed8d963ba23aa89cedd90d3433d00f619..add5a967d3659d525901101cb25e3712601a2f03 100644 (file)
@@ -48,6 +48,7 @@ private:
                unsigned detail;
 
                TypeKey(Id i, unsigned d): type_id(i), detail(d) { }
+               TypeKey(BasicTypeDeclaration::Kind, bool);
 
                bool operator<(const TypeKey &) const;
        };
@@ -62,6 +63,7 @@ private:
                };
 
                ConstantKey(Id t, int i): type_id(t), int_value(i) { }
+               ConstantKey(Id t, unsigned u): type_id(t), int_value(u) { }
                ConstantKey(Id t, float f): type_id(t), float_value(f) { }
 
                bool operator<(const ConstantKey &) const;
@@ -115,7 +117,7 @@ private:
        static ConstantKey get_constant_key(Id, const Variant &value);
        Id get_constant_id(Id, const Variant &value);
        Id get_vector_constant_id(Id, unsigned, Id);
-       Id get_standard_type_id(BasicTypeDeclaration::Kind, unsigned);
+       Id get_standard_type_id(BasicTypeDeclaration::Kind, unsigned, bool = true);
        bool is_scalar_type(Id, BasicTypeDeclaration::Kind) const;
        Id get_array_type_id(TypeDeclaration &, unsigned);
        Id get_pointer_type_id(Id, StorageClass);
index 9e21b26973ea967b8c46581d5fedacb07450d3a5..3f780b1b247f706e0a833cc87e2e1555b4ad0844 100644 (file)
@@ -65,8 +65,11 @@ enum SpirVOpcode
        OP_IMAGE_SAMPLE_DREF_EXPLICIT_LOD = 89,
        OP_IMAGE_FETCH = 95,
        OP_IMAGE_QUERY_SIZE_LOD = 103,
+       OP_CONVERT_F_TO_U = 109,
        OP_CONVERT_F_TO_S = 110,
        OP_CONVERT_S_TO_F = 111,
+       OP_CONVERT_U_TO_F = 112,
+       OP_BITCAST = 124,
        OP_S_NEGATE = 126,
        OP_F_NEGATE = 127,
        OP_I_ADD = 128,
@@ -75,8 +78,10 @@ enum SpirVOpcode
        OP_F_SUB = 131,
        OP_I_MUL = 132,
        OP_F_MUL = 133,
+       OP_U_DIV = 134,
        OP_S_DIV = 135,
        OP_F_DIV = 136,
+       OP_U_MOD = 137,
        OP_S_MOD = 139,
        OP_F_MOD = 141,
        OP_VECTOR_TIMES_SCALAR = 142,
@@ -98,9 +103,13 @@ enum SpirVOpcode
        OP_SELECT = 169,
        OP_I_EQUAL = 170,
        OP_I_NOT_EQUAL = 171,
+       OP_U_GREATER_THAN = 172,
        OP_S_GREATER_THAN = 173,
+       OP_U_GREATER_THAN_EQUAL = 174,
        OP_S_GREATER_THAN_EQUAL = 175,
+       OP_U_LESS_THAN = 176,
        OP_S_LESS_THAN = 177,
+       OP_U_LESS_THAN_EQUAL = 178,
        OP_S_LESS_THAN_EQUAL = 179,
        OP_F_ORD_EQUAL = 180,
        OP_F_ORD_NOT_EQUAL = 182,
@@ -116,6 +125,7 @@ enum SpirVOpcode
        OP_NOT = 200,
        OP_BIT_FIELD_INSERT = 201,
        OP_BIT_FIELD_S_EXTRACT = 202,
+       OP_BIT_FIELD_U_EXTRACT = 203,
        OP_BIT_REVERSE = 204,
        OP_BIT_COUNT = 205,
        OP_DP_DX = 207,
@@ -246,10 +256,13 @@ enum SpirVGlslStd450Opcode
        GLSL450_DETERMINANT = 33,
        GLSL450_MATRIX_INVERSE = 33,
        GLSL450_F_MIN = 37,
+       GLSL450_U_MIN = 38,
        GLSL450_S_MIN = 39,
        GLSL450_F_MAX = 40,
+       GLSL450_U_MAX = 41,
        GLSL450_S_MAX = 42,
        GLSL450_F_CLAMP = 43,
+       GLSL450_U_CLAMP = 44,
        GLSL450_S_CLAMP = 45,
        GLSL450_F_MIX = 46,
        GLSL450_F_STEP = 48,
@@ -264,6 +277,7 @@ enum SpirVGlslStd450Opcode
        GLSL450_REFRACT = 72,
        GLSL450_FIND_I_LSB = 73,
        GLSL450_FIND_S_MSB = 74,
+       GLSL450_FIND_U_MSB = 75,
        GLSL450_INTERPOLATE_AT_CENTROID = 76,
        GLSL450_INTERPOLATE_AT_SAMPLE = 77,
        GLSL450_INTERPOLATE_AT_OFFSET = 78
index 947b310ef5e528e026dd53dcbd642de96f4923b3..4526bf2bd986075f6bfe50e50dae1eabf2ebd204 100644 (file)
@@ -271,6 +271,7 @@ void InterfaceLayout::visit(NodeVisitor &visitor)
 BasicTypeDeclaration::BasicTypeDeclaration():
        kind(ALIAS),
        size(0),
+       sign(true),
        base_type(0)
 { }
 
@@ -278,6 +279,7 @@ BasicTypeDeclaration::BasicTypeDeclaration(const BasicTypeDeclaration &other):
        TypeDeclaration(other),
        kind(other.kind),
        size(other.size),
+       sign(other.sign),
        base(other.base),
        base_type(0)
 { }
index f22ef1ec1a9700744edd08f89d119e06a97d490d..4d30ee04c24684557eade28e639f70b4fdee6295 100644 (file)
@@ -357,6 +357,7 @@ struct BasicTypeDeclaration: TypeDeclaration
 
        Kind kind;
        unsigned size;
+       bool sign;
        std::string base;
 
        TypeDeclaration *base_type;
index 2fa1b64ae960be301874c872c60c67c70f23cd13..bd455e3cb200408128534b6e9a235198e6d08807 100644 (file)
@@ -157,7 +157,7 @@ string Tokenizer::parse_number()
                if(!require_digit && iter!=source_end && *iter=='f')
                        number += *iter++;
        }
-       else if(*iter=='f')
+       else if(*iter=='u' || *iter=='f')
                number += *iter++;
 
        if(require_digit)
diff --git a/tests/glsl/unsigned_int.glsl b/tests/glsl/unsigned_int.glsl
new file mode 100644 (file)
index 0000000..b83f5e3
--- /dev/null
@@ -0,0 +1,51 @@
+uniform sampler2D tex;
+vec2 hammersley(uint i, uint count)
+{
+       float y = bitfieldReverse(i)*2.3283064e-10;
+       return vec2(float(i)/count, y);
+}
+const uint sample_count = 128;
+
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+void main()
+{
+       gl_Position = position;
+       out vec2 texcoord = position.xy*0.5+0.5;
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out vec4 frag_color;
+void main()
+{
+       vec4 sum = vec4(0.0);
+       for(int i=0; i<sample_count; ++i)
+               sum += texture(tex, texcoord+pow(hammersley(i, sample_count), vec2(2.0)));
+       frag_color = sum/sample_count;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+layout(location=0) out vec2 texcoord;
+void main()
+{
+       gl_Position = position;
+       texcoord = position.xy*0.5+0.5;
+}
+*/
+
+/* Expected output: fragment
+layout(location=0, binding=71) uniform sampler2D tex;
+layout(location=0) out vec4 frag_color;
+layout(location=0) in vec2 texcoord;
+void main()
+{
+       vec4 sum = vec4(0.0);
+       for(int i=0; uint(i)<128u; ++i)
+       {
+               uint i_1 = uint(i);
+               sum += texture(tex, texcoord+pow(vec2(float(i_1)/128.0, float(bitfieldReverse(i_1))*2.3283064e-10), vec2(2.0)));
+       }
+       frag_color = sum/128.0;
+}
+*/