From 738bcb82d0327c463625ee6fcdf14b52e766cedc Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Thu, 20 Sep 2018 08:14:25 -0700 Subject: 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) --- source/slang/type-layout.cpp | 68 ++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 46 deletions(-) (limited to 'source/slang/type-layout.cpp') 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, -- cgit v1.2.3