From 91e65bc9e24a6889995081035f6f6f0a78a6c20e Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 20 Apr 2021 19:26:16 +0300 Subject: [PATCH] Add support for uint types in GLSL --- builtin_data/_builtin.glsl | 71 ++++++++++++++++++++++++++++++++++++ scripts/builtin_funcs.py | 18 ++++++--- source/glsl/builtin.cpp | 8 ++++ source/glsl/optimize.cpp | 20 +++++++++- source/glsl/parser.cpp | 5 ++- source/glsl/reflect.cpp | 4 +- source/glsl/resolve.cpp | 8 ++-- source/glsl/resolve.h | 2 +- source/glsl/spirv.cpp | 71 +++++++++++++++++++++++++++++------- source/glsl/spirv.h | 4 +- source/glsl/spirvconstants.h | 14 +++++++ source/glsl/syntax.cpp | 2 + source/glsl/syntax.h | 1 + source/glsl/tokenizer.cpp | 2 +- tests/glsl/unsigned_int.glsl | 51 ++++++++++++++++++++++++++ 15 files changed, 252 insertions(+), 29 deletions(-) create mode 100644 tests/glsl/unsigned_int.glsl diff --git a/builtin_data/_builtin.glsl b/builtin_data/_builtin.glsl index 3bf722cd..94a7ca69 100644 --- a/builtin_data/_builtin.glsl +++ b/builtin_data/_builtin.glsl @@ -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); diff --git a/scripts/builtin_funcs.py b/scripts/builtin_funcs.py index 3825cb2b..ef19d54f 100755 --- a/scripts/builtin_funcs.py +++ b/scripts/builtin_funcs.py @@ -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") diff --git a/source/glsl/builtin.cpp b/source/glsl/builtin.cpp index f60d2a8a..12602707 100644 --- a/source/glsl/builtin.cpp +++ b/source/glsl/builtin.cpp @@ -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"; diff --git a/source/glsl/optimize.cpp b/source/glsl/optimize.cpp index d21512f6..0139ec5f 100644 --- a/source/glsl/optimize.cpp +++ b/source/glsl/optimize.cpp @@ -611,6 +611,8 @@ void ConstantFolder::convert_to_result(const Variant &value) set_result(static_cast(value.value())); else if(value.check_type()) set_result(static_cast(value.value())); + else if(value.check_type()) + set_result(static_cast(value.value())); else if(value.check_type()) set_result(static_cast(value.value())); } @@ -640,6 +642,8 @@ void ConstantFolder::visit(RefPtr &expr) literal->token = (r_constant_value.value() ? "true" : "false"); else if(r_constant_value.check_type()) literal->token = lexical_cast(r_constant_value.value()); + else if(r_constant_value.check_type()) + literal->token = lexical_cast(r_constant_value.value())+"u"; else if(r_constant_value.check_type()) { literal->token = lexical_cast(r_constant_value.value()); @@ -744,11 +748,15 @@ void ConstantFolder::visit(BinaryExpression &binary) set_result(evaluate_logical(oper, left_value.value(), r_constant_value.value())); else if(!oper2 && left_value.check_type()) set_result(evaluate_logical(oper, left_value.value(), r_constant_value.value())); + else if(!oper2 && left_value.check_type()) + set_result(evaluate_logical(oper, left_value.value(), r_constant_value.value())); } else if((oper=='<' || oper=='>') && oper2!=oper) { if(left_value.check_type()) set_result(evaluate_relation(binary.oper->token, left_value.value(), r_constant_value.value())); + else if(left_value.check_type()) + set_result(evaluate_relation(binary.oper->token, left_value.value(), r_constant_value.value())); else if(left_value.check_type()) set_result(evaluate_relation(binary.oper->token, left_value.value(), r_constant_value.value())); } @@ -756,13 +764,17 @@ void ConstantFolder::visit(BinaryExpression &binary) { if(left_value.check_type()) set_result((left_value.value()==r_constant_value.value()) == (oper=='=')); - if(left_value.check_type()) + else if(left_value.check_type()) + set_result((left_value.value()==r_constant_value.value()) == (oper=='=')); + else if(left_value.check_type()) set_result((left_value.value()==r_constant_value.value()) == (oper=='=')); } else if(oper=='+' || oper=='-' || oper=='*' || oper=='/') { if(left_value.check_type()) set_result(evaluate_arithmetic(oper, left_value.value(), r_constant_value.value())); + else if(left_value.check_type()) + set_result(evaluate_arithmetic(oper, left_value.value(), r_constant_value.value())); else if(left_value.check_type()) set_result(evaluate_arithmetic(oper, left_value.value(), r_constant_value.value())); } @@ -770,6 +782,8 @@ void ConstantFolder::visit(BinaryExpression &binary) { if(left_value.check_type()) set_result(evaluate_int_special_op(oper, left_value.value(), r_constant_value.value())); + else if(left_value.check_type()) + set_result(evaluate_int_special_op(oper, left_value.value(), r_constant_value.value())); } } @@ -800,8 +814,10 @@ void ConstantFolder::visit(FunctionCall &call) if(basic->kind==BasicTypeDeclaration::BOOL) convert_to_result(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(r_constant_value); + else if(basic->kind==BasicTypeDeclaration::INT && basic->size==32 && !basic->sign) + convert_to_result(r_constant_value); else if(basic->kind==BasicTypeDeclaration::FLOAT && basic->size==32) convert_to_result(r_constant_value); diff --git a/source/glsl/parser.cpp b/source/glsl/parser.cpp index 72f8ebfa..0512c10b 100644 --- a/source/glsl/parser.cpp +++ b/source/glsl/parser.cpp @@ -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 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(literal->token.substr(0, literal->token.size()-1)); + else if(literal->token.back()=='f') literal->value = lexical_cast(literal->token.substr(0, literal->token.size()-1)); else if(literal->token.find('.')!=string::npos) literal->value = lexical_cast(literal->token); diff --git a/source/glsl/reflect.cpp b/source/glsl/reflect.cpp index c2a913f9..8c10accc 100644 --- a/source/glsl/reflect.cpp +++ b/source/glsl/reflect.cpp @@ -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(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); diff --git a/source/glsl/resolve.cpp b/source/glsl/resolve.cpp index 3f959a7d..f2670b53 100644 --- a/source/glsl/resolve.cpp +++ b/source/glsl/resolve.cpp @@ -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::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()) resolve(literal, find_type(BasicTypeDeclaration::BOOL, 1), false); else if(literal.value.check_type()) - resolve(literal, find_type(BasicTypeDeclaration::INT, 32), false); + resolve(literal, find_type(BasicTypeDeclaration::INT, 32, true), false); + else if(literal.value.check_type()) + resolve(literal, find_type(BasicTypeDeclaration::INT, 32, false), false); else if(literal.value.check_type()) resolve(literal, find_type(BasicTypeDeclaration::FLOAT, 32), false); } diff --git a/source/glsl/resolve.h b/source/glsl/resolve.h index 69c877fc..633ff11d 100644 --- a/source/glsl/resolve.h +++ b/source/glsl/resolve.h @@ -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 &, BasicTypeDeclaration &); bool convert_to_element(RefPtr &, BasicTypeDeclaration &); diff --git a/source/glsl/spirv.cpp b/source/glsl/spirv.cpp index 2220dcc1..52885342 100644 --- a/source/glsl/spirv.cpp +++ b/source/glsl/spirv.cpp @@ -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()); 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 +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(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::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); } @@ -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 &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) diff --git a/source/glsl/spirv.h b/source/glsl/spirv.h index 98aa673e..add5a967 100644 --- a/source/glsl/spirv.h +++ b/source/glsl/spirv.h @@ -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); diff --git a/source/glsl/spirvconstants.h b/source/glsl/spirvconstants.h index 9e21b269..3f780b1b 100644 --- a/source/glsl/spirvconstants.h +++ b/source/glsl/spirvconstants.h @@ -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 diff --git a/source/glsl/syntax.cpp b/source/glsl/syntax.cpp index 947b310e..4526bf2b 100644 --- a/source/glsl/syntax.cpp +++ b/source/glsl/syntax.cpp @@ -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) { } diff --git a/source/glsl/syntax.h b/source/glsl/syntax.h index f22ef1ec..4d30ee04 100644 --- a/source/glsl/syntax.h +++ b/source/glsl/syntax.h @@ -357,6 +357,7 @@ struct BasicTypeDeclaration: TypeDeclaration Kind kind; unsigned size; + bool sign; std::string base; TypeDeclaration *base_type; diff --git a/source/glsl/tokenizer.cpp b/source/glsl/tokenizer.cpp index 2fa1b64a..bd455e3c 100644 --- a/source/glsl/tokenizer.cpp +++ b/source/glsl/tokenizer.cpp @@ -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 index 00000000..b83f5e32 --- /dev/null +++ b/tests/glsl/unsigned_int.glsl @@ -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