summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-09-20 08:14:25 -0700
committerGitHub <noreply@github.com>2018-09-20 08:14:25 -0700
commit738bcb82d0327c463625ee6fcdf14b52e766cedc (patch)
tree2651348121b6550fba8b312382416f435f3027ef /source/slang
parent653fe976af88fcf86162ca5bb1b46d4378864572 (diff)
Improve support for non-32-bit types. (#643)
The main change here is to fill out the `BaseType` enumeration so that it covers the full range of 8/16/32/64-bit signed and unsigned integers, as well as 16/32/64-bit floating-point numbers, and then propagate that completion through various places in the code. More details: * The current `half`, `float`, `double`, `int`, and `uint` types are still the default names for their types, so things like `float16_t` and `int32_t` were added as `typedef`s. * We still need to generate the full gamut of vector/matrix `typedef`s for the new types, so that things like `float16_t4x3` will work (yes, I know that is ugly as sin, but that's the HLSL syntax...). * A few pieces of dead code from earlier in the compiler's life got removed, since I did a find-in-files for `BaseType::` and tried to either update or delete every site. * A few call sites that were enumerating integer base types in an ad-hoc fashion were changed to use a single `isIntegerBaseType()` function that I added in `check.cpp` * When compiling with dxc for shader model 6.2 and up, we enable the compiler's support for native 16-bit types via a flag. * The public API enumeration for reflection of scalar types added cases for 8- and 16-bit integers (it already exposed the other cases we need) * The lexer was updated to be extremely liberal in what kinds of suffixes it allows on literals. I also removed the logic that was treating, e.g., `0f` as a floating-point literal (it doesn't seem to be the right behavior). That would now be an integer literal with an invalid suffix. * The logic in the parser that applies types to literals was updated to handle a few more cases: `LL` and `ULL` for 64-bit integers, and `H` for 16-bit floats. * The mangling logic needed to be updated to handle the new cases, and I consolidated the handling of those types in their front-end and IR forms. * Removed the explicit `BasicExpressionType::ToString` logic, since all basic types are `DeclRefType`s in the front end, and we can just print them out as such. * As a bit of a gross hack, fudged the conversion costs so that `int` to `int64_t` conversion is a bit more costly. The problem there is that given an operation like `int(0) + uint(0)`, the best applicable candidates ended up being `+(uint,uint)` and `+(int64_t,int64_t)` because the cost of a single `int`-to-`uint` conversion was the same as the sum of the cost of an `int`-to-`int64_t` and a `uint`-to-`int64_t`. A better long-term fix here is to completely change our overload resolution strategy, but that is obviously way too big to squeeze into this change. * Type layout computation was updated to handle all the new types and give them their natural size/alignment. Note that this does *not* work for down-level HLSL where `half` is treated as a synonym for `float`. It also doesn't deal with the fact that many of these types aren't actually allowed in constant buffers for certain shader models. A future change should work to add error messages for unsupported stuff during type layout (or just make the types themselves require support for certain capabilities)
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/check.cpp121
-rw-r--r--source/slang/compiler.h3
-rw-r--r--source/slang/core.meta.slang40
-rw-r--r--source/slang/core.meta.slang.h40
-rw-r--r--source/slang/dxc-support.cpp15
-rw-r--r--source/slang/emit.cpp29
-rw-r--r--source/slang/lexer.cpp59
-rw-r--r--source/slang/mangle.cpp59
-rw-r--r--source/slang/parser.cpp25
-rw-r--r--source/slang/reflection.cpp19
-rw-r--r--source/slang/slang-stdlib.cpp12
-rw-r--r--source/slang/syntax.cpp51
-rw-r--r--source/slang/syntax.h2
-rw-r--r--source/slang/type-defs.h1
-rw-r--r--source/slang/type-layout.cpp68
-rw-r--r--source/slang/type-layout.h6
-rw-r--r--source/slang/type-system-shared.h5
17 files changed, 272 insertions, 283 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp
index 7f91ac0c3..bddf813f2 100644
--- a/source/slang/check.cpp
+++ b/source/slang/check.cpp
@@ -205,41 +205,6 @@ namespace Slang
typeCheckingCache = nullptr;
}
- bool IsNumeric(BaseType t)
- {
- return t == BaseType::Int || t == BaseType::Float || t == BaseType::UInt;
- }
-
- String TranslateHLSLTypeNames(String name)
- {
- if (name == "float2" || name == "half2")
- return "vec2";
- else if (name == "float3" || name == "half3")
- return "vec3";
- else if (name == "float4" || name == "half4")
- return "vec4";
- else if (name == "half")
- return "float";
- else if (name == "int2")
- return "ivec2";
- else if (name == "int3")
- return "ivec3";
- else if (name == "int4")
- return "ivec4";
- else if (name == "uint2")
- return "uvec2";
- else if (name == "uint3")
- return "uvec3";
- else if (name == "uint4")
- return "uvec4";
- else if (name == "float3x3" || name == "half3x3")
- return "mat3";
- else if (name == "float4x4" || name == "half4x4")
- return "mat4";
- else
- return name;
- }
-
enum class CheckingPhase
{
Header, Body
@@ -2916,25 +2881,37 @@ namespace Slang
decl->SetCheckState(getCheckedState());
}
+ bool isIntegerBaseType(BaseType baseType)
+ {
+ switch(baseType)
+ {
+ default:
+ return false;
+
+ case BaseType::Int8:
+ case BaseType::Int16:
+ case BaseType::Int:
+ case BaseType::Int64:
+ case BaseType::UInt8:
+ case BaseType::UInt16:
+ case BaseType::UInt:
+ case BaseType::UInt64:
+ return true;
+ }
+ }
+
// Validate that `type` is a suitable type to use
// as the tag type for an `enum`
void validateEnumTagType(Type* type, SourceLoc const& loc)
{
if(auto basicType = type->As<BasicExpressionType>())
{
- switch(basicType->baseType)
- {
- default:
- // By default, don't allow a type to be used
- // as an `enum` tag type.
- break;
-
- case BaseType::Int:
- case BaseType::UInt:
- case BaseType::UInt64:
- // These are all allowed.
+ // Allow the built-in intteger types.
+ if(isIntegerBaseType(basicType->baseType))
return;
- }
+
+ // By default, don't allow other types to be used
+ // as an `enum` tag type.
}
getSink()->diagnose(loc, Diagnostics::invalidEnumTagType, type);
@@ -4420,16 +4397,8 @@ namespace Slang
// Check if type is acceptable for an integer constant expression
if(auto basicType = exp->type.type->As<BasicExpressionType>())
{
- switch(basicType->baseType)
- {
- default:
+ if(!isIntegerBaseType(basicType->baseType))
return nullptr;
-
- case BaseType::Int:
- case BaseType::UInt:
- case BaseType::UInt64:
- break;
- }
}
else
{
@@ -7724,46 +7693,6 @@ namespace Slang
// Now process this like any other explicit call (so casts
// and constructor calls are semantically equivalent).
return CheckInvokeExprWithCheckedOperands(expr);
-
-#if 0
- expr->Expression = CheckTerm(expr->Expression);
- auto targetType = CheckProperType(expr->TargetType);
- expr->TargetType = targetType;
-
- // The way to perform casting depends on the types involved
- if (expr->Expression->type->Equals(getSession()->getErrorType()))
- {
- // If the expression being casted has an error type, then just silently succeed
- expr->type = targetType.Ptr();
- return expr;
- }
- else if (auto targetArithType = targetType->AsArithmeticType())
- {
- if (auto exprArithType = expr->Expression->type->AsArithmeticType())
- {
- // Both source and destination types are arithmetic, so we might
- // have a valid cast
- auto targetScalarType = targetArithType->GetScalarType();
- auto exprScalarType = exprArithType->GetScalarType();
-
- if (!IsNumeric(exprScalarType->baseType)) goto fail;
- if (!IsNumeric(targetScalarType->baseType)) goto fail;
-
- // TODO(tfoley): this checking is incomplete here, and could
- // lead to downstream compilation failures
- expr->type = targetType.Ptr();
- return expr;
- }
- }
- // TODO: other cases? Should we allow a cast to succeeed whenever
- // a single-argument constructor for the target type would work?
-
- fail:
- // Default: in no other case succeds, then the cast failed and we emit a diagnostic.
- getSink()->diagnose(expr, Diagnostics::invalidTypeCast, expr->Expression->type, targetType->ToString());
- expr->type = QualType(getSession()->getErrorType());
- return expr;
-#endif
}
// Get the type to use when referencing a declaration
diff --git a/source/slang/compiler.h b/source/slang/compiler.h
index c6a114d7d..bf71dd217 100644
--- a/source/slang/compiler.h
+++ b/source/slang/compiler.h
@@ -550,10 +550,13 @@ namespace Slang
void initializeTypes();
Type* getBoolType();
+ Type* getHalfType();
Type* getFloatType();
Type* getDoubleType();
Type* getIntType();
+ Type* getInt64Type();
Type* getUIntType();
+ Type* getUInt64Type();
Type* getVoidType();
Type* getBuiltinType(BaseType flavor);
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 31da44f3c..b5b78c2e5 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -1,5 +1,14 @@
// Slang `core` library
+// Aliases for base types
+typedef half float16_t;
+typedef float float32_t;
+typedef double float64_t;
+
+typedef int int32_t;
+typedef uint uint32_t;
+
+
// Modifier for variables that must resolve to compile-time constants
// as part of translation.
syntax constexpr : ConstExprModifier;
@@ -72,9 +81,14 @@ for (int tt = 0; tt < kBaseTypeCount; ++tt)
sb << "\n , __BuiltinFloatingPointType\n";
sb << "\n , __BuiltinRealType\n";
// fall through to:
+ case BaseType::Int8:
+ case BaseType::Int16:
case BaseType::Int:
+ case BaseType::Int64:
sb << "\n , __BuiltinSignedArithmeticType\n";
// fall through to:
+ case BaseType::UInt8:
+ case BaseType::UInt16:
case BaseType::UInt:
case BaseType::UInt64:
sb << "\n , __BuiltinArithmeticType\n";
@@ -121,6 +135,7 @@ for (int tt = 0; tt < kBaseTypeCount; ++tt)
//
switch (kBaseTypes[tt].tag)
{
+ // TODO: should this cover the full gamut of integer types?
case BaseType::Int:
case BaseType::UInt:
}}}}
@@ -196,10 +211,27 @@ static const struct {
char const* glslPrefix;
} kTypes[] =
{
- {"float", ""},
- {"int", "i"},
- {"uint", "u"},
- {"bool", "b"},
+ {"half", "f16"},
+ {"float", ""},
+ {"double", "d"},
+
+ {"float16_t", "f16"},
+ {"float32_t", "f32"},
+ {"float64_t", "f64"},
+
+ {"int8_t", "i8"},
+ {"int16_t", "i16"},
+ {"int32_t", "i32"},
+ {"int", "i"},
+ {"int64_t", "i64"},
+
+ {"uint8_t", "u8"},
+ {"uint16_t", "u16"},
+ {"uint32_t", "u32"},
+ {"uint", "u"},
+ {"uint64_t", "u64"},
+
+ {"bool", "b"},
};
static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]);
diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h
index 12c76d213..c69878112 100644
--- a/source/slang/core.meta.slang.h
+++ b/source/slang/core.meta.slang.h
@@ -1,5 +1,14 @@
SLANG_RAW("// Slang `core` library\n")
SLANG_RAW("\n")
+SLANG_RAW("// Aliases for base types\n")
+SLANG_RAW("typedef half float16_t;\n")
+SLANG_RAW("typedef float float32_t;\n")
+SLANG_RAW("typedef double float64_t;\n")
+SLANG_RAW("\n")
+SLANG_RAW("typedef int int32_t;\n")
+SLANG_RAW("typedef uint uint32_t;\n")
+SLANG_RAW("\n")
+SLANG_RAW("\n")
SLANG_RAW("// Modifier for variables that must resolve to compile-time constants\n")
SLANG_RAW("// as part of translation.\n")
SLANG_RAW("syntax constexpr : ConstExprModifier;\n")
@@ -72,9 +81,14 @@ for (int tt = 0; tt < kBaseTypeCount; ++tt)
sb << "\n , __BuiltinFloatingPointType\n";
sb << "\n , __BuiltinRealType\n";
// fall through to:
+ case BaseType::Int8:
+ case BaseType::Int16:
case BaseType::Int:
+ case BaseType::Int64:
sb << "\n , __BuiltinSignedArithmeticType\n";
// fall through to:
+ case BaseType::UInt8:
+ case BaseType::UInt16:
case BaseType::UInt:
case BaseType::UInt64:
sb << "\n , __BuiltinArithmeticType\n";
@@ -121,6 +135,7 @@ for (int tt = 0; tt < kBaseTypeCount; ++tt)
//
switch (kBaseTypes[tt].tag)
{
+ // TODO: should this cover the full gamut of integer types?
case BaseType::Int:
case BaseType::UInt:
SLANG_RAW("\n")
@@ -211,10 +226,27 @@ static const struct {
char const* glslPrefix;
} kTypes[] =
{
- {"float", ""},
- {"int", "i"},
- {"uint", "u"},
- {"bool", "b"},
+ {"half", "f16"},
+ {"float", ""},
+ {"double", "d"},
+
+ {"float16_t", "f16"},
+ {"float32_t", "f32"},
+ {"float64_t", "f64"},
+
+ {"int8_t", "i8"},
+ {"int16_t", "i16"},
+ {"int32_t", "i32"},
+ {"int", "i"},
+ {"int64_t", "i64"},
+
+ {"uint8_t", "u8"},
+ {"uint16_t", "u16"},
+ {"uint32_t", "u32"},
+ {"uint", "u"},
+ {"uint64_t", "u64"},
+
+ {"bool", "b"},
};
static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]);
diff --git a/source/slang/dxc-support.cpp b/source/slang/dxc-support.cpp
index 68b46f1b9..30817d31c 100644
--- a/source/slang/dxc-support.cpp
+++ b/source/slang/dxc-support.cpp
@@ -129,6 +129,21 @@ namespace Slang
String profileName = GetHLSLProfileName(profile);
OSString wideProfileName = profileName.ToWString();
+ // We will enable the flag to generate proper code for 16-bit types
+ // by default, as long as the user is requesting a sufficiently
+ // high shader model.
+ //
+ // TODO: Need to check that this is safe to enable in all cases,
+ // or if it will make a shader demand hardware features that
+ // aren't always present.
+ //
+ // TODO: Ideally the dxc back-end should be passed some information
+ // on the "capabilities" that were used and/or requested in the code.
+ //
+ if( profile.GetVersion() >= ProfileVersion::DX_6_2 )
+ {
+ args[argCount++] = L"-enable-16bit-types";
+ }
IDxcOperationResult* dxcResult = nullptr;
if (FAILED(dxcCompiler->Compile(dxcSourceBlob,
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 74678ef94..1e833838c 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -786,10 +786,20 @@ struct EmitVisitor
// no prefix
break;
- case kIROp_IntType: Emit("i"); break;
- case kIROp_UIntType: Emit("u"); break;
- case kIROp_BoolType: Emit("b"); break;
- case kIROp_DoubleType: Emit("d"); break;
+ case kIROp_Int8Type: Emit("i8"); break;
+ case kIROp_Int16Type: Emit("i16"); break;
+ case kIROp_IntType: Emit("i"); break;
+ case kIROp_Int64Type: Emit("i64"); break;
+
+ case kIROp_UInt8Type: Emit("u8"); break;
+ case kIROp_UInt16Type: Emit("u16"); break;
+ case kIROp_UIntType: Emit("u"); break;
+ case kIROp_UInt64Type: Emit("u64"); break;
+
+ case kIROp_BoolType: Emit("b"); break;
+
+ case kIROp_HalfType: Emit("f16"); break;
+ case kIROp_DoubleType: Emit("d"); break;
case kIROp_VectorType:
emitGLSLTypePrefix(cast<IRVectorType>(type)->getElementType());
@@ -1179,9 +1189,18 @@ struct EmitVisitor
break;
case kIROp_VoidType: Emit("void"); return;
+ case kIROp_BoolType: Emit("bool"); return;
+
+ case kIROp_Int8Type: Emit("int8_t"); return;
+ case kIROp_Int16Type: Emit("int16_t"); return;
case kIROp_IntType: Emit("int"); return;
+ case kIROp_Int64Type: Emit("int64_t"); return;
+
+ case kIROp_UInt8Type: Emit("uint8_t"); return;
+ case kIROp_UInt16Type: Emit("uint16_t"); return;
case kIROp_UIntType: Emit("uint"); return;
- case kIROp_BoolType: Emit("bool"); return;
+ case kIROp_UInt64Type: Emit("uint64_t"); return;
+
case kIROp_HalfType: Emit("half"); return;
case kIROp_FloatType: Emit("float"); return;
case kIROp_DoubleType: Emit("double"); return;
diff --git a/source/slang/lexer.cpp b/source/slang/lexer.cpp
index 5e6d15384..9ea86cc82 100644
--- a/source/slang/lexer.cpp
+++ b/source/slang/lexer.cpp
@@ -393,55 +393,28 @@ namespace Slang
static TokenType maybeLexNumberSuffix(Lexer* lexer, TokenType tokenType)
{
- // First check for suffixes that
- // indicate a floating-point number
- switch(peek(lexer))
- {
- case 'f': case 'F':
- advance(lexer);
- return TokenType::FloatingPointLiteral;
-
- default:
- break;
- }
-
- // Once we've ruled out floating-point
- // suffixes, we can check for the inter cases
-
- // TODO: allow integer suffixes in any order...
-
- // Leading `u` or `U` for unsigned
- switch(peek(lexer))
- {
- default:
- break;
-
- case 'u': case 'U':
- advance(lexer);
- break;
- }
-
- // Optional `l`, `L`, `ll`, or `LL`
- switch(peek(lexer))
+ // Be liberal in what we accept here, so that figuring out
+ // the semantics of a numeric suffix is left up to the parser
+ // and semantic checking logic.
+ //
+ for( ;;)
{
- default:
- break;
+ int c = peek(lexer);
- case 'l': case 'L':
- advance(lexer);
- switch(peek(lexer))
+ // Accept any alphanumeric character, plus underscores.
+ if(('a' <= c ) && (c <= 'z')
+ || ('A' <= c) && (c <= 'Z')
+ || ('0' <= c) && (c <= '9')
+ || (c == '_'))
{
- default:
- break;
-
- case 'l': case 'L':
advance(lexer);
- break;
+ continue;
}
- break;
- }
- return tokenType;
+ // Stop at the first character that isn't
+ // alphanumeric.
+ return tokenType;
+ }
}
static bool isNumberExponent(int c, int base)
diff --git a/source/slang/mangle.cpp b/source/slang/mangle.cpp
index dc2738d8f..c35ad1e14 100644
--- a/source/slang/mangle.cpp
+++ b/source/slang/mangle.cpp
@@ -78,6 +78,33 @@ namespace Slang
emitVal(context, val);
}
+ void emitBaseType(
+ ManglingContext* context,
+ BaseType baseType)
+ {
+ switch( baseType )
+ {
+ case BaseType::Void: emitRaw(context, "V"); break;
+ case BaseType::Bool: emitRaw(context, "b"); break;
+ case BaseType::Int8: emitRaw(context, "c"); break;
+ case BaseType::Int16: emitRaw(context, "s"); break;
+ case BaseType::Int: emitRaw(context, "i"); break;
+ case BaseType::Int64: emitRaw(context, "I"); break;
+ case BaseType::UInt8: emitRaw(context, "C"); break;
+ case BaseType::UInt16: emitRaw(context, "S"); break;
+ case BaseType::UInt: emitRaw(context, "u"); break;
+ case BaseType::UInt64: emitRaw(context, "U"); break;
+ case BaseType::Half: emitRaw(context, "h"); break;
+ case BaseType::Float: emitRaw(context, "f"); break;
+ case BaseType::Double: emitRaw(context, "d"); break;
+ break;
+
+ default:
+ SLANG_UNEXPECTED("unimplemented case in mangling");
+ break;
+ }
+ }
+
void emitType(
ManglingContext* context,
Type* type)
@@ -86,22 +113,7 @@ namespace Slang
if( auto basicType = dynamic_cast<BasicExpressionType*>(type) )
{
- switch( basicType->baseType )
- {
- case BaseType::Void: emitRaw(context, "V"); break;
- case BaseType::Bool: emitRaw(context, "b"); break;
- case BaseType::Int: emitRaw(context, "i"); break;
- case BaseType::UInt: emitRaw(context, "u"); break;
- case BaseType::UInt64: emitRaw(context, "U"); break;
- case BaseType::Half: emitRaw(context, "h"); break;
- case BaseType::Float: emitRaw(context, "f"); break;
- case BaseType::Double: emitRaw(context, "d"); break;
- break;
-
- default:
- SLANG_UNEXPECTED("unimplemented case in mangling");
- break;
- }
+ emitBaseType(context, basicType->baseType);
}
else if( auto vecType = dynamic_cast<VectorExpressionType*>(type) )
{
@@ -212,19 +224,10 @@ namespace Slang
ManglingContext* context,
IRInst* inst)
{
- switch (inst->op)
+ if(auto basicType = as<IRBasicType>(inst) )
{
- case kIROp_VoidType: emitRaw(context, "V"); return;
- case kIROp_BoolType: emitRaw(context, "b"); return;
- case kIROp_IntType: emitRaw(context, "i"); return;
- case kIROp_UIntType: emitRaw(context, "u"); return;
- case kIROp_UInt64Type: emitRaw(context, "U"); return;
- case kIROp_HalfType: emitRaw(context, "h"); return;
- case kIROp_FloatType: emitRaw(context, "f"); return;
- case kIROp_DoubleType: emitRaw(context, "d"); return;
-
- default:
- break;
+ emitBaseType(context, basicType->getBaseType());
+ return;
}
if (auto globalVal = as<IRGlobalValue>(inst))
diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp
index e3982aee4..37cc24459 100644
--- a/source/slang/parser.cpp
+++ b/source/slang/parser.cpp
@@ -4035,8 +4035,17 @@ namespace Slang
{
suffixType = parser->getSession()->getIntType();
}
- // TODO: probably need `ll` and `ull`
- // TODO: are there other suffixes we need to handle?
+ // `ull` suffix -> `uint64_t`
+ else if(uCount == 1 && lCount == 2)
+ {
+ suffixType = parser->getSession()->getUInt64Type();
+ }
+ // `ll` suffix -> `int64_t`
+ else if(uCount == 0 && lCount == 2)
+ {
+ suffixType = parser->getSession()->getInt64Type();
+ }
+ // TODO: do we need suffixes for smaller integer types?
else
{
parser->sink->diagnose(token, Diagnostics::invalidIntegerLiteralSuffix, suffix);
@@ -4070,6 +4079,7 @@ namespace Slang
{
int fCount = 0;
int lCount = 0;
+ int hCount = 0;
int unknownCount = 0;
while(*suffixCursor)
{
@@ -4083,6 +4093,10 @@ namespace Slang
lCount++;
break;
+ case 'h': case 'H':
+ hCount++;
+ break;
+
default:
unknownCount++;
break;
@@ -4099,11 +4113,16 @@ namespace Slang
{
suffixType = parser->getSession()->getFloatType();
}
- // `l` or `lf` suffix on float -> `double`
+ // `l` or `lf` suffix on floating-point literal -> `double`
else if(lCount == 1 && (fCount <= 1))
{
suffixType = parser->getSession()->getDoubleType();
}
+ // `h` or `hf` suffix on floating-point literal -> `half`
+ else if(lCount == 1 && (fCount <= 1))
+ {
+ suffixType = parser->getSession()->getHalfType();
+ }
// TODO: are there other suffixes we need to handle?
else
{
diff --git a/source/slang/reflection.cpp b/source/slang/reflection.cpp
index 9a593d18b..6e635a8ce 100644
--- a/source/slang/reflection.cpp
+++ b/source/slang/reflection.cpp
@@ -326,12 +326,19 @@ SLANG_API SlangScalarType spReflectionType_GetScalarType(SlangReflectionType* in
#define CASE(BASE, TAG) \
case BaseType::BASE: return SLANG_SCALAR_TYPE_##TAG
- CASE(Void, VOID);
- CASE(Int, INT32);
- CASE(Float, FLOAT32);
- CASE(UInt, UINT32);
- CASE(Bool, BOOL);
- CASE(UInt64, UINT64);
+ CASE(Void, VOID);
+ CASE(Bool, BOOL);
+ CASE(Int8, INT8);
+ CASE(Int16, INT16);
+ CASE(Int, INT32);
+ CASE(Int64, INT64);
+ CASE(UInt8, UINT8);
+ CASE(UInt16, UINT16);
+ CASE(UInt, UINT32);
+ CASE(UInt64, UINT64);
+ CASE(Half, FLOAT16);
+ CASE(Float, FLOAT32);
+ CASE(Double, FLOAT64);
#undef CASE
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index bd2ce2561..5a4718af4 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -102,15 +102,19 @@ namespace Slang
{ "bool", BaseType::Bool, BOOL_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Bool },
- // TODO: should declare explicit types for 8-, 16-, 32- and 64-bit integers
- { "int", BaseType::Int, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int32},
+ { "int8_t", BaseType::Int8, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int8},
+ { "int16_t", BaseType::Int16, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int16},
+ { "int", BaseType::Int, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int32},
+ { "int64_t", BaseType::Int64, SINT_MASK, kBaseTypeConversionKind_Signed, kBaseTypeConversionRank_Int64},
{ "half", BaseType::Half, FLOAT_MASK, kBaseTypeConversionKind_Float, kBaseTypeConversionRank_Int16},
{ "float", BaseType::Float, FLOAT_MASK, kBaseTypeConversionKind_Float, kBaseTypeConversionRank_Int32},
{ "double", BaseType::Double, FLOAT_MASK, kBaseTypeConversionKind_Float, kBaseTypeConversionRank_Int64},
- { "uint", BaseType::UInt, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int32},
- { "uint64_t", BaseType::UInt64, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int64},
+ { "uint8_t", BaseType::UInt8, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int8},
+ { "uint16_t", BaseType::UInt16, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int16},
+ { "uint", BaseType::UInt, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int32},
+ { "uint64_t", BaseType::UInt64, UINT_MASK, kBaseTypeConversionKind_Unsigned, kBaseTypeConversionRank_Int64},
};
// Given two base types, we need to be able to compute the cost of converting between them.
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
index bb6d6a575..c1585a51a 100644
--- a/source/slang/syntax.cpp
+++ b/source/slang/syntax.cpp
@@ -24,42 +24,6 @@ namespace Slang
return this;
}
- Slang::String BasicExpressionType::ToString()
- {
- Slang::StringBuilder res;
-
- switch (this->baseType)
- {
- case Slang::BaseType::Int:
- res.Append("int");
- break;
- case Slang::BaseType::UInt:
- res.Append("uint");
- break;
- case Slang::BaseType::UInt64:
- res.Append("uint64_t");
- break;
- case Slang::BaseType::Bool:
- res.Append("bool");
- break;
- case Slang::BaseType::Float:
- res.Append("float");
- break;
- case Slang::BaseType::Double:
- res.Append("double");
- break;
- case Slang::BaseType::Half:
- res.Append("half");
- break;
- case Slang::BaseType::Void:
- res.Append("void");
- break;
- default:
- break;
- }
- return res.ProduceString();
- }
-
// Generate dispatch logic and other definitions for all syntax classes
#define SYNTAX_CLASS(NAME, BASE) /* empty */
#include "object-meta-begin.h"
@@ -235,6 +199,11 @@ void Type::accept(IValVisitor* visitor, void* extra)
return getBuiltinType(BaseType::Bool);
}
+ Type* Session::getHalfType()
+ {
+ return getBuiltinType(BaseType::Half);
+ }
+
Type* Session::getFloatType()
{
return getBuiltinType(BaseType::Float);
@@ -250,11 +219,21 @@ void Type::accept(IValVisitor* visitor, void* extra)
return getBuiltinType(BaseType::Int);
}
+ Type* Session::getInt64Type()
+ {
+ return getBuiltinType(BaseType::Int64);
+ }
+
Type* Session::getUIntType()
{
return getBuiltinType(BaseType::UInt);
}
+ Type* Session::getUInt64Type()
+ {
+ return getBuiltinType(BaseType::UInt64);
+ }
+
Type* Session::getVoidType()
{
return getBuiltinType(BaseType::Void);
diff --git a/source/slang/syntax.h b/source/slang/syntax.h
index 00f7eb95b..24660b7fd 100644
--- a/source/slang/syntax.h
+++ b/source/slang/syntax.h
@@ -49,7 +49,7 @@ namespace Slang
kConversionCost_CastToInterface = 50,
// Conversion that is lossless and keeps the "kind" of the value the same
- kConversionCost_RankPromotion = 100,
+ kConversionCost_RankPromotion = 150,
// Conversions that are lossless, but change "kind"
kConversionCost_UnsignedToSignedPromotion = 200,
diff --git a/source/slang/type-defs.h b/source/slang/type-defs.h
index cfb928e13..bce8edcd3 100644
--- a/source/slang/type-defs.h
+++ b/source/slang/type-defs.h
@@ -85,7 +85,6 @@ RAW(
Slang::BaseType baseType)
: baseType(baseType)
{}
- virtual Slang::String ToString() override;
protected:
virtual BasicExpressionType* GetScalarType() override;
virtual bool EqualsImpl(Type * type) override;
diff --git a/source/slang/type-layout.cpp b/source/slang/type-layout.cpp
index d7a4e68bc..3fbb9b31b 100644
--- a/source/slang/type-layout.cpp
+++ b/source/slang/type-layout.cpp
@@ -34,43 +34,35 @@ struct DefaultLayoutRulesImpl : SimpleLayoutRulesImpl
{
switch (baseType)
{
- case BaseType::Int:
- case BaseType::UInt:
- case BaseType::Float:
- case BaseType::Bool:
- return SimpleLayoutInfo( LayoutResourceKind::Uniform, 4, 4 );
+ case BaseType::Void: return SimpleLayoutInfo();
- case BaseType::Double:
- return SimpleLayoutInfo( LayoutResourceKind::Uniform, 8, 8 );
+ // Note: By convention, a `bool` in a constant buffer is stored as an `int.
+ // This default may eventually change, at which point this logic will need
+ // to be updated.
+ //
+ // TODO: We should probably warn in this case, since storing a `bool` in
+ // a constant buffer seems like a Bad Idea anyway.
+ //
+ case BaseType::Bool: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 4, 4 );
- default:
- SLANG_UNEXPECTED("uhandled scalar type");
- UNREACHABLE_RETURN(SimpleLayoutInfo( LayoutResourceKind::Uniform, 0, 1 ));
- }
- }
- virtual SimpleLayoutInfo GetScalarLayout(slang::TypeReflection::ScalarType scalarType)
- {
- switch( scalarType )
- {
- case slang::TypeReflection::ScalarType::Void: return SimpleLayoutInfo();
- case slang::TypeReflection::ScalarType::None: return SimpleLayoutInfo();
+ case BaseType::Int8: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 1,1);
+ case BaseType::Int16: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 2,2);
+ case BaseType::Int: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 4,4);
+ case BaseType::Int64: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 8,8);
- // TODO(tfoley): At some point we don't want to lay out `bool` as 4 bytes by default...
- case slang::TypeReflection::ScalarType::Bool: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 4,4);
- case slang::TypeReflection::ScalarType::Int32: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 4,4);
- case slang::TypeReflection::ScalarType::UInt32: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 4,4);
- case slang::TypeReflection::ScalarType::Int64: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 8,8);
- case slang::TypeReflection::ScalarType::UInt64: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 8,8);
+ case BaseType::UInt8: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 1,1);
+ case BaseType::UInt16: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 2,2);
+ case BaseType::UInt: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 4,4);
+ case BaseType::UInt64: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 8,8);
- // TODO(tfoley): What actually happens if you use `half` in a constant buffer?
- case slang::TypeReflection::ScalarType::Float16: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 2,2);
- case slang::TypeReflection::ScalarType::Float32: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 4,4);
- case slang::TypeReflection::ScalarType::Float64: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 8,8);
+ case BaseType::Half: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 2,2);
+ case BaseType::Float: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 4,4);
+ case BaseType::Double: return SimpleLayoutInfo( LayoutResourceKind::Uniform, 8,8);
default:
- SLANG_UNEXPECTED("unhandled scalar type");
- UNREACHABLE_RETURN(SimpleLayoutInfo());
+ SLANG_UNEXPECTED("uhandled scalar type");
+ UNREACHABLE_RETURN(SimpleLayoutInfo( LayoutResourceKind::Uniform, 0, 1 ));
}
}
@@ -267,14 +259,6 @@ struct DefaultVaryingLayoutRulesImpl : DefaultLayoutRulesImpl
1);
}
- virtual SimpleLayoutInfo GetScalarLayout(slang::TypeReflection::ScalarType)
- {
- // Assume that all scalars take up one "slot"
- return SimpleLayoutInfo(
- getKind(),
- 1);
- }
-
SimpleLayoutInfo GetVectorLayout(SimpleLayoutInfo, size_t) override
{
// Vectors take up one slot by default
@@ -318,14 +302,6 @@ struct GLSLSpecializationConstantLayoutRulesImpl : DefaultLayoutRulesImpl
1);
}
- virtual SimpleLayoutInfo GetScalarLayout(slang::TypeReflection::ScalarType)
- {
- // Assume that all scalars take up one "slot"
- return SimpleLayoutInfo(
- getKind(),
- 1);
- }
-
SimpleLayoutInfo GetVectorLayout(SimpleLayoutInfo, size_t elementCount) override
{
// GLSL doesn't support vectors of specialization constants,
diff --git a/source/slang/type-layout.h b/source/slang/type-layout.h
index c3f6f2679..f151a498a 100644
--- a/source/slang/type-layout.h
+++ b/source/slang/type-layout.h
@@ -510,7 +510,6 @@ struct SimpleLayoutRulesImpl
{
// Get size and alignment for a single value of base type.
virtual SimpleLayoutInfo GetScalarLayout(BaseType baseType) = 0;
- virtual SimpleLayoutInfo GetScalarLayout(slang::TypeReflection::ScalarType scalarType) = 0;
// Get size and alignment for an array of elements
virtual SimpleArrayLayoutInfo GetArrayLayout(SimpleLayoutInfo elementInfo, size_t elementCount) = 0;
@@ -548,11 +547,6 @@ struct LayoutRulesImpl
return simpleRules->GetScalarLayout(baseType);
}
- SimpleLayoutInfo GetScalarLayout(slang::TypeReflection::ScalarType scalarType)
- {
- return simpleRules->GetScalarLayout(scalarType);
- }
-
SimpleArrayLayoutInfo GetArrayLayout(SimpleLayoutInfo elementInfo, size_t elementCount)
{
return simpleRules->GetArrayLayout(elementInfo, elementCount);
diff --git a/source/slang/type-system-shared.h b/source/slang/type-system-shared.h
index dd06026c5..183cacb4b 100644
--- a/source/slang/type-system-shared.h
+++ b/source/slang/type-system-shared.h
@@ -8,7 +8,12 @@ namespace Slang
#define FOREACH_BASE_TYPE(X) \
X(Void) \
X(Bool) \
+ X(Int8) \
+ X(Int16) \
X(Int) \
+ X(Int64) \
+ X(UInt8) \
+ X(UInt16) \
X(UInt) \
X(UInt64) \
X(Half) \