Skip to content

Commit 0f55649

Browse files
author
Tim Foley
authoredDec 8, 2017
Cleanups to ParameterBlock<T> behavior. (shader-slang#304)
* Cleanups to `ParameterBlock<T>` behavior. These add some more realistic tests using the `ParameterBlock<T>` support, and show that it can work with the "rewriter" mode. Unfortunately, this code does *not* currently work with the rewriter + the IR at once. That will need to be fixed in a follow-on change, because I now see that the root problem is pretty ugly. * cleanup
1 parent 301cdf5 commit 0f55649

19 files changed

+510
-67
lines changed
 

‎slang.h

+2
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,7 @@ extern "C"
522522
SLANG_TYPE_KIND_SAMPLER_STATE,
523523
SLANG_TYPE_KIND_TEXTURE_BUFFER,
524524
SLANG_TYPE_KIND_SHADER_STORAGE_BUFFER,
525+
SLANG_TYPE_KIND_PARAMETER_BLOCK,
525526

526527
SLANG_TYPE_KIND_COUNT,
527528
};
@@ -759,6 +760,7 @@ namespace slang
759760
SamplerState = SLANG_TYPE_KIND_SAMPLER_STATE,
760761
TextureBuffer = SLANG_TYPE_KIND_TEXTURE_BUFFER,
761762
ShaderStorageBuffer = SLANG_TYPE_KIND_SHADER_STORAGE_BUFFER,
763+
ParameterBlock = SLANG_TYPE_KIND_PARAMETER_BLOCK,
762764
};
763765

764766
enum ScalarType : SlangScalarType

‎source/slang/ast-legalize.cpp

+101-23
Original file line numberDiff line numberDiff line change
@@ -797,24 +797,9 @@ struct LoweringVisitor
797797
lowerTypeEx(type->valueType));
798798
}
799799

800-
RefPtr<Type> visitParameterBlockType(ParameterBlockType* type)
801-
{
802-
// TODO: When doing AST-to-AST lowering, we want to lower
803-
// a `ParameterBlock<T>` just like a `ConstantBuffer<T>`.
804-
//
805-
// HACK: for now we will try to simply lower the type
806-
// directly to its stated element type, and see how
807-
// that works.
808-
809-
return lowerTypeEx(type->getElementType());
810-
// return getSession()->getConstantBufferType(
811-
// lowerType(type->getElementType());
812-
}
813-
814800
RefPtr<Type> transformSyntaxField(Type* type)
815801
{
816-
// TODO: how to handle this...
817-
return type;
802+
return lowerAndLegalizeSimpleType(type);
818803
}
819804

820805
RefPtr<Val> visitIRProxyVal(IRProxyVal* val)
@@ -1807,15 +1792,73 @@ struct LoweringVisitor
18071792

18081793
static LegalExpr maybeReifyTuple(
18091794
LegalExpr legalExpr,
1810-
LegalType expectedType)
1795+
LegalType expectedLegalType)
18111796
{
1812-
if (expectedType.flavor != LegalType::Flavor::simple)
1797+
if (expectedLegalType.flavor != LegalType::Flavor::simple)
18131798
return legalExpr;
18141799

1800+
RefPtr<Type> expectedType = expectedLegalType.getSimple();
1801+
if(auto errorType = expectedType->As<ErrorType>())
1802+
{
1803+
return legalExpr;
1804+
}
1805+
18151806
if (legalExpr.getFlavor() == LegalExpr::Flavor::simple)
18161807
return legalExpr;
18171808

1818-
return LegalExpr(reifyTuple(legalExpr, expectedType.getSimple()));
1809+
return LegalExpr(reifyTuple(legalExpr, expectedLegalType.getSimple()));
1810+
}
1811+
1812+
// This function exists to work around cases where `addArgs` gets called
1813+
// and the structure of the type expected in context (the legalized parameter
1814+
// type) differs from the structure of the actual argument.
1815+
//
1816+
// This function ignores type information and just adds things based on
1817+
// what is present in the actual expression.
1818+
void addArgsWorkaround(
1819+
ExprWithArgsBase* callExpr,
1820+
LegalExpr argExpr)
1821+
{
1822+
1823+
switch (argExpr.getFlavor())
1824+
{
1825+
case LegalExpr::Flavor::none:
1826+
break;
1827+
1828+
case LegalExpr::Flavor::simple:
1829+
addArg(callExpr, argExpr.getSimple());
1830+
break;
1831+
1832+
case LegalExpr::Flavor::tuple:
1833+
{
1834+
auto aa = argExpr.getTuple();
1835+
auto elementCount = aa->elements.Count();
1836+
for (UInt ee = 0; ee < elementCount; ++ee)
1837+
{
1838+
addArgsWorkaround(callExpr, aa->elements[ee].expr);
1839+
}
1840+
}
1841+
break;
1842+
1843+
case LegalExpr::Flavor::pair:
1844+
{
1845+
auto aa = argExpr.getPair();
1846+
addArgsWorkaround(callExpr, aa->ordinary);
1847+
addArgsWorkaround(callExpr, aa->special);
1848+
}
1849+
break;
1850+
1851+
case LegalExpr::Flavor::implicitDeref:
1852+
{
1853+
auto aa = argExpr.getImplicitDeref();
1854+
addArgsWorkaround(callExpr, aa->valueExpr);
1855+
}
1856+
break;
1857+
1858+
default:
1859+
SLANG_UNEXPECTED("unhandled case");
1860+
break;
1861+
}
18191862
}
18201863

18211864
void addArgs(
@@ -1827,7 +1870,10 @@ struct LoweringVisitor
18271870

18281871
if (argExpr.getFlavor() != argType.flavor)
18291872
{
1830-
SLANG_UNEXPECTED("expression and type do not match");
1873+
// A mismatch may also arise if we are in the `-no-checking` mode,
1874+
// so that we are making a call that didn't type-check.
1875+
addArgsWorkaround(callExpr, argExpr);
1876+
return;
18311877
}
18321878

18331879
switch (argExpr.getFlavor())
@@ -1900,6 +1946,29 @@ struct LoweringVisitor
19001946
return LegalExpr(lowerCallExpr(loweredExpr, expr));
19011947
}
19021948

1949+
LegalExpr visitHiddenImplicitCastExpr(
1950+
HiddenImplicitCastExpr* expr)
1951+
{
1952+
LegalExpr legalArg = legalizeExpr(expr->Arguments[0]);
1953+
if(legalArg.getFlavor() == LegalExpr::Flavor::simple)
1954+
{
1955+
InvokeExpr* loweredExpr = (InvokeExpr*) expr->getClass().createInstance();
1956+
lowerExprCommon(loweredExpr, expr);
1957+
loweredExpr->FunctionExpr = legalizeSimpleExpr(expr->FunctionExpr);
1958+
addArg(loweredExpr, legalArg.getSimple());
1959+
return LegalExpr(loweredExpr);
1960+
}
1961+
else
1962+
{
1963+
// If we hit this case, then there seems to have been a type-checking
1964+
// error around a type that needed to be desugared. We want to use
1965+
// the original expression rather than hide it behind a cast, because
1966+
// it might need to be unpacked into multiple arguments for a call, etc.
1967+
//
1968+
return legalArg;
1969+
}
1970+
}
1971+
19031972
LegalExpr visitSelectExpr(
19041973
SelectExpr* expr)
19051974
{
@@ -2476,6 +2545,7 @@ struct LoweringVisitor
24762545
RefPtr<Type> type)
24772546
{
24782547
auto typeType = new TypeType();
2548+
typeType->setSession(getSession());
24792549
typeType->type = type;
24802550

24812551
auto result = new SharedTypeExpr();
@@ -3320,7 +3390,6 @@ struct LoweringVisitor
33203390
typeLayout,
33213391
legalInit,
33223392
legalTypeExpr);
3323-
33243393
}
33253394
break;
33263395

@@ -3329,8 +3398,17 @@ struct LoweringVisitor
33293398
auto implicitDerefType = legalType.getImplicitDeref();
33303399

33313400
auto valueType = implicitDerefType->valueType;
3332-
auto valueTypeLayout = getDerefTypeLayout(typeLayout);
3333-
SLANG_ASSERT(valueTypeLayout || !typeLayout);
3401+
3402+
// Don't apply dereferencing to the type layout, because
3403+
// other steps will also implicitly remove wrappers (like
3404+
// parameter groups) and this could mess up the final
3405+
// type layout for a variable.
3406+
//
3407+
// Instead, any other "unwrapping" that needs to occur
3408+
// when declaring variables should be handled in the
3409+
// case for the specific type (e.g., when extracting
3410+
// fields for a tuple, we should auto-dereference).
3411+
auto valueTypeLayout = typeLayout;
33343412
auto valueInit = deref(legalInit);
33353413

33363414
LegalExpr valueExpr = declareVars(

‎source/slang/check.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,40 @@ namespace Slang
10051005
}
10061006

10071007
}
1008+
1009+
// Are we converting from a parameter group type to its element type?
1010+
if(auto fromParameterGroupType = fromType->As<ParameterGroupType>())
1011+
{
1012+
auto fromElementType = fromParameterGroupType->getElementType();
1013+
1014+
// If we have, e.g., `ConstantBuffer<A>` and we want to convert
1015+
// to `B`, where conversion from `A` to `B` is possible, then
1016+
// we will do so here.
1017+
1018+
ConversionCost subCost = 0;
1019+
if(CanCoerce(toType, fromElementType, &subCost))
1020+
{
1021+
if(outCost)
1022+
*outCost = subCost + kConversionCost_ImplicitDereference;
1023+
1024+
if(outToExpr)
1025+
{
1026+
auto derefExpr = new DerefExpr();
1027+
derefExpr->base = fromExpr;
1028+
derefExpr->type = QualType(fromElementType);
1029+
1030+
return TryCoerceImpl(
1031+
toType,
1032+
outToExpr,
1033+
fromElementType,
1034+
derefExpr,
1035+
nullptr);
1036+
}
1037+
return true;
1038+
}
1039+
}
1040+
1041+
10081042
// Look for an initializer/constructor declaration in the target type,
10091043
// which is marked as usable for implicit conversion, and which takes
10101044
// the source type as an argument.
@@ -1171,6 +1205,7 @@ namespace Slang
11711205
RefPtr<TypeCastExpr> castExpr = createImplicitCastExpr();
11721206

11731207
auto typeType = new TypeType();
1208+
typeType->setSession(getSession());
11741209
typeType->type = toType;
11751210

11761211
auto typeExpr = new SharedTypeExpr();

0 commit comments

Comments
 (0)