From 6f239b0489602d0c333282a3751d454a166d33f1 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Mon, 17 Jul 2017 11:01:27 -0700 Subject: Map HLSL `linear` to GLSL... nothing The behavior of the `linear` modifier should be the default interpolation behavior in GLSL. --- source/slang/emit.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 0eb371b88..effa9aa97 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -2683,6 +2683,9 @@ struct EmitVisitor #define CASE2(TYPE, HLSL_NAME, GLSL_NAME) \ else if(auto mod_##TYPE = mod.As()) Emit((context->shared->target == CodeGenTarget::GLSL) ? (#GLSL_NAME " ") : (#HLSL_NAME " ")) + #define CASE2_RAW(TYPE, HLSL_NAME, GLSL_NAME) \ + else if(auto mod_##TYPE = mod.As()) Emit((context->shared->target == CodeGenTarget::GLSL) ? (GLSL_NAME) : (HLSL_NAME)) + CASE(RowMajorLayoutModifier, row_major); CASE(ColumnMajorLayoutModifier, column_major); @@ -2703,7 +2706,7 @@ struct EmitVisitor CASE(HLSLLineAdjModifier, lineadj); CASE(HLSLTriangleAdjModifier, triangleadj); - CASE(HLSLLinearModifier, linear); + CASE2_RAW(HLSLLinearModifier, "linear ", ""); CASE(HLSLSampleModifier, sample); CASE(HLSLCentroidModifier, centroid); -- cgit v1.2.3 From 5d5aca4206c77677d9c64c47417302cb2eb2b6c4 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Mon, 17 Jul 2017 11:37:29 -0700 Subject: Improve handling of `SampleCmpLevelZero` - We map `SampleCmpLevelZero` to either `textureLod` or `textureGrad` based on what the GLSL spec seems to allow - We map `SamplerComparisonState` to `samplerShadow` (instead of just `sampler`) --- source/slang/emit.cpp | 21 +++++++++++++++++++-- source/slang/slang-stdlib.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index effa9aa97..c6efa88dc 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -1041,7 +1041,7 @@ struct EmitVisitor default: switch (samplerStateType->flavor) { - case SamplerStateType::Flavor::SamplerState: Emit("SamplerState"); break; + case SamplerStateType::Flavor::SamplerState: Emit("SamplerState"); break; case SamplerStateType::Flavor::SamplerComparisonState: Emit("SamplerComparisonState"); break; default: assert(!"unreachable"); @@ -1050,7 +1050,15 @@ struct EmitVisitor break; case CodeGenTarget::GLSL: - Emit("sampler"); + switch (samplerStateType->flavor) + { + case SamplerStateType::Flavor::SamplerState: Emit("sampler"); break; + case SamplerStateType::Flavor::SamplerComparisonState: Emit("samplerShadow"); break; + default: + assert(!"unreachable"); + break; + } + break; break; } @@ -1847,6 +1855,15 @@ struct EmitVisitor if (auto baseTextureType = base->Type->As()) { emitGLSLTextureOrTextureSamplerType(baseTextureType, "sampler"); + + if (auto samplerType = callExpr->Arguments[0]->Type.type->As()) + { + if (samplerType->flavor == SamplerStateType::Flavor::SamplerComparisonState) + { + Emit("Shadow"); + } + } + Emit("("); EmitExpr(memberExpr->BaseExpression); Emit(","); diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp index 1c1bcceaf..169eac4fb 100644 --- a/source/slang/slang-stdlib.cpp +++ b/source/slang/slang-stdlib.cpp @@ -1612,6 +1612,48 @@ namespace Slang sb << "float compareValue"; sb << ");\n"; + int baseCoordCount = kBaseTextureTypes[tt].coordCount; + int arrCoordCount = baseCoordCount + isArray; + if (arrCoordCount < 3) + { + int extCoordCount = arrCoordCount + 1; + + if (extCoordCount < 3) + extCoordCount = 3; + + sb << "__intrinsic(glsl, \"textureLod($p, "; + + sb << "vec" << extCoordCount << "($1,"; + for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii) + { + sb << " 0.0,"; + } + sb << "$2)"; + + sb << ", 0.0)\")\n"; + } + else if(arrCoordCount <= 3) + { + int extCoordCount = arrCoordCount + 1; + + if (extCoordCount < 3) + extCoordCount = 3; + + sb << "__intrinsic(glsl, \"textureGrad($p, "; + + sb << "vec" << extCoordCount << "($1,"; + for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii) + { + sb << " 0.0,"; + } + sb << "$2)"; + + // Construct gradients + sb << ", vec" << baseCoordCount << "(0.0)"; + sb << ", vec" << baseCoordCount << "(0.0)"; + sb << ")\")\n"; + } + sb << "__intrinsic\n"; sb << "T SampleCmpLevelZero(SamplerComparisonState s, "; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "float compareValue"; -- cgit v1.2.3 From fcf007268b077ee0d46553a62ae1b09528345be6 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Mon, 17 Jul 2017 11:54:58 -0700 Subject: Add hacky GLSL lowering for `GetDimensions` This is hacky for two big reasons: 1. It uses "operator comma" in the output to deal with calling multiple functions in an expression context 2. The way I'm lowering things to GLSL ends up using certain function arguments more than once, which means they get emitted as GLSL more than once, which means their *side effects* get evaluated more than once. Please don't put an expression with side effects in as an argument to `GetDimensions` when cross-compiling. Solving these issues requires the translation of builtins to be more directly handled as part of lowering, rather than a purely textual operation done during emission. I don't have time to fix that right now. --- source/slang/slang-stdlib.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'source') diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp index 169eac4fb..4fcef6639 100644 --- a/source/slang/slang-stdlib.cpp +++ b/source/slang/slang-stdlib.cpp @@ -1440,6 +1440,66 @@ namespace Slang for(int isFloat = 0; isFloat < 2; ++isFloat) for(int includeMipInfo = 0; includeMipInfo < 2; ++includeMipInfo) { + { + sb << "__intrinsic(glsl, \"("; + + int aa = 0; + String lodStr = "0"; + if (includeMipInfo) + { + int mipLevelArg = aa++; + lodStr.append("$"); + lodStr.append(mipLevelArg); + } + + int cc = 0; + switch(baseShape) + { + case TextureType::Shape1D: + sb << "($" << aa++ << " = textureSize($P, " << lodStr << "))"; + cc = 1; + break; + + case TextureType::Shape2D: + case TextureType::ShapeCube: + sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)"; + sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)"; + cc = 2; + break; + + case TextureType::Shape3D: + sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)"; + sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)"; + sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").z)"; + cc = 3; + break; + + default: + assert(!"unexpected"); + break; + } + + if(isArray) + { + sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ")." << kComponentNames[cc] << ")"; + } + + if(isMultisample) + { + sb << ", ($" << aa++ << " = textureSamples($P))"; + } + + if (includeMipInfo) + { + sb << ", ($" << aa++ << " = textureQueryLevels($P))"; + } + + + sb << ")\")\n"; + sb << "__intrinsic\n"; + + } + char const* t = isFloat ? "out float " : "out uint "; sb << "void GetDimensions("; -- cgit v1.2.3 From 77e3c3bfb1f77ec04cd8e63a676bfa3e2ae2f998 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Mon, 17 Jul 2017 12:03:05 -0700 Subject: Map HLSL `SampleGrad` to GLSL `textureGrad[Offset]` - This was an easy case, as far as these things go. --- source/slang/slang-stdlib.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source') diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp index 4fcef6639..3de33f554 100644 --- a/source/slang/slang-stdlib.cpp +++ b/source/slang/slang-stdlib.cpp @@ -1739,6 +1739,9 @@ namespace Slang sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; } + + sb << "__intrinsic(glsl, \"textureGrad($p, $1, $2, $3)\")\n"; + sb << "__intrinsic\n"; sb << "T SampleGrad(SamplerState s, "; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, "; @@ -1747,6 +1750,8 @@ namespace Slang if( baseShape != TextureType::ShapeCube ) { + sb << "__intrinsic(glsl, \"textureGradOffset($p, $1, $2, $3, $4)\")\n"; + sb << "__intrinsic\n"; sb << "T SampleGrad(SamplerState s, "; sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, "; -- cgit v1.2.3 From 453a9ca07417bbc17294267c5e44843d16e93c50 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Mon, 17 Jul 2017 13:32:20 -0700 Subject: Handle arrays when scalarizing "resources in structs" The basic idea is that an array of `struct`s will get scalarized into per-field arrays (for any fields that need to be scalarized). So given: struct Foo { float x; Texture2D t; }; cbuffer C { Foo foo[4]; } We'll get output like: struct Foo { float x; }; cbuffer C { Foo foo[4]; } Texture2D C_foo_t[4]; (Of course the output would also be translated over to GLSL, but I'm only concerned about this one transformation here). --- source/slang/lower.cpp | 240 ++++++++++++++++++++++++++++++++++++++++--------- source/slang/syntax.h | 4 +- 2 files changed, 200 insertions(+), 44 deletions(-) (limited to 'source') diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index 98f6d8273..b6a19ab34 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -616,7 +616,7 @@ struct LoweringVisitor result->tupleElements.Add(elem); } - return result; +return result; } RefPtr visitVarExpressionSyntaxNode( @@ -708,6 +708,84 @@ struct LoweringVisitor return loweredExpr; } + RefPtr getSubscripResultType( + RefPtr type) + { + if (auto arrayType = type->As()) + { + return arrayType->BaseType; + } + return nullptr; + } + + RefPtr createSubscriptExpr( + RefPtr baseExpr, + RefPtr indexExpr) + { + // TODO: This logic ends up duplicating the `indexExpr` + // that was given, without worrying about any side + // effects it might contain. That needs to be fixed. + + if (auto baseTuple = baseExpr.As()) + { + auto loweredExpr = new TupleExpr(); + loweredExpr->Type.type = getSubscripResultType(baseExpr->Type.type); + + if (auto basePrimary = baseTuple->primaryExpr) + { + loweredExpr->primaryExpr = createSubscriptExpr( + basePrimary, + indexExpr); + } + for (auto elem : baseTuple->tupleElements) + { + TupleExpr::Element loweredElem; + loweredElem.tupleFieldDeclRef = elem.tupleFieldDeclRef; + loweredElem.expr = createSubscriptExpr( + elem.expr, + indexExpr); + + loweredExpr->tupleElements.Add(loweredElem); + } + + return loweredExpr; + } + else + { + // Default case: just reconstrut a subscript expr + auto loweredExpr = new IndexExpressionSyntaxNode(); + + loweredExpr->Type.type = getSubscripResultType(baseExpr->Type.type); + + loweredExpr->BaseExpression = baseExpr; + loweredExpr->IndexExpression = indexExpr; + return loweredExpr; + } + } + + RefPtr visitIndexExpressionSyntaxNode( + IndexExpressionSyntaxNode* subscriptExpr) + { + auto baseExpr = lowerExpr(subscriptExpr->BaseExpression); + auto indexExpr = lowerExpr(subscriptExpr->IndexExpression); + + // An attempt to subscript a tuple must be turned into a + // tuple of subscript expressions. + if (auto baseTuple = baseExpr.As()) + { + return createSubscriptExpr(baseExpr, indexExpr); + } + else + { + // Default case: just reconstrut a subscript expr + RefPtr loweredExpr = new IndexExpressionSyntaxNode(); + lowerExprCommon(loweredExpr, subscriptExpr); + loweredExpr->BaseExpression = baseExpr; + loweredExpr->IndexExpression = indexExpr; + return loweredExpr; + } + } + void addArgs( InvokeExpressionSyntaxNode* callExpr, RefPtr argExpr) @@ -1615,6 +1693,21 @@ struct LoweringVisitor return nullptr; } + ExpressionType* unwrapArray(ExpressionType* inType) + { + auto type = inType; + while (auto arrayType = type->As()) + { + type = arrayType->BaseType; + } + return type; + } + + TupleTypeModifier* isTupleTypeOrArrayOfTupleType(ExpressionType* type) + { + return isTupleType(unwrapArray(type)); + } + bool isResourceType(ExpressionType* type) { while (auto arrayType = type->As()) @@ -1692,7 +1785,7 @@ struct LoweringVisitor bool isTupleField = false; bool fieldHasAnyNonTupleFields = false; bool fieldHasTupleType = false; - if (auto fieldTupleTypeMod = isTupleType(loweredFieldType)) + if (auto fieldTupleTypeMod = isTupleTypeOrArrayOfTupleType(loweredFieldType)) { isTupleField = true; fieldHasTupleType = true; @@ -1780,19 +1873,60 @@ struct LoweringVisitor return lowerSimpleVarDeclCommon(loweredDecl, decl, loweredType); } + struct TupleTypeSecondaryVarArraySpec + { + TupleTypeSecondaryVarArraySpec* next; + RefPtr elementCount; + }; + + struct TupleSecondaryVarInfo + { + // Parent tuple decl to add the secondary decl into + RefPtr tupleDecl; + + // Syntax class for declarations to create + SyntaxClass varDeclClass; + + // Name "stem" to use for any actual variables we create + String name; + + // The parent tuple type (or array thereof) we are scalarizing + RefPtr tupleType; + + // The actual declaration of the tuple type (which will give us the fields) + DeclRef tupleTypeDecl; + + // An initializer expression to use for the tuple members + RefPtr initExpr; + + // The original layout given to the top-level variable + RefPtr primaryVarLayout; + + // The computed layout of the tuple type itself + RefPtr tupleTypeLayout; + + TupleTypeSecondaryVarArraySpec* arraySpecs = nullptr; + }; + void createTupleTypeSecondaryVarDecls( - RefPtr tupleDecl, - SyntaxClass varDeclClass, - String const& name, - RefPtr tupleType, - DeclRef tupleTypeDecl, - RefPtr initExpr, - RefPtr primaryVarLayout, - RefPtr tupleTypeLayout) + TupleSecondaryVarInfo const& info) { + if (auto arrayType = info.tupleType->As()) + { + TupleTypeSecondaryVarArraySpec arraySpec; + arraySpec.next = info.arraySpecs; + arraySpec.elementCount = arrayType->ArrayLength; + + TupleSecondaryVarInfo subInfo = info; + subInfo.tupleType = arrayType->BaseType; + subInfo.arraySpecs = &arraySpec; + createTupleTypeSecondaryVarDecls(subInfo); + return; + } + // Next, we need to go through the declarations in the aggregate // type, and deal with all of those that should be tuple-ified. - for (auto dd : getMembersOfType(tupleTypeDecl)) + for (auto dd : getMembersOfType(info.tupleTypeDecl)) { if (dd.getDecl()->HasModifier()) continue; @@ -1802,10 +1936,10 @@ struct LoweringVisitor continue; // TODO: need to extract the initializer for this field - assert(!initExpr); + assert(!info.initExpr); RefPtr fieldInitExpr; - String fieldName = name + "_" + dd.GetName(); + String fieldName = info.name + "_" + dd.GetName(); auto fieldType = GetType(dd); @@ -1814,11 +1948,11 @@ struct LoweringVisitor assert(originalFieldDecl); RefPtr fieldLayout; - if(tupleTypeLayout) + if(info.tupleTypeLayout) { - tupleTypeLayout->mapVarToLayout.TryGetValue(originalFieldDecl, fieldLayout); + info.tupleTypeLayout->mapVarToLayout.TryGetValue(originalFieldDecl, fieldLayout); } - if (fieldLayout && primaryVarLayout) + if (fieldLayout && info.primaryVarLayout) { // The layout for a field may need to be adjusted // based on a base offset stored in the primary @@ -1835,7 +1969,7 @@ struct LoweringVisitor bool needsOffset = false; for (auto rr : fieldLayout->resourceInfos) { - if (auto parentInfo = primaryVarLayout->FindResourceInfo(rr.kind)) + if (auto parentInfo = info.primaryVarLayout->FindResourceInfo(rr.kind)) { if (parentInfo->index != 0 || parentInfo->space != 0) { @@ -1858,7 +1992,7 @@ struct LoweringVisitor auto newResInfo = newFieldLayout->findOrAddResourceInfo(resInfo.kind); newResInfo->index = resInfo.index; newResInfo->space = resInfo.space; - if (auto parentInfo = primaryVarLayout->FindResourceInfo(resInfo.kind)) + if (auto parentInfo = info.primaryVarLayout->FindResourceInfo(resInfo.kind)) { newResInfo->index += parentInfo->index; newResInfo->space += parentInfo->space; @@ -1871,29 +2005,44 @@ struct LoweringVisitor } RefPtr fieldVarOrTupleDecl; - if (auto fieldTupleTypeMod = isTupleType(fieldType)) + if (auto fieldTupleTypeMod = isTupleTypeOrArrayOfTupleType(fieldType)) { // If the field is itself a tuple, then recurse RefPtr fieldTupleDecl = new TupleVarDecl(); + + TupleSecondaryVarInfo fieldInfo; + fieldInfo.tupleDecl = fieldTupleDecl; + fieldInfo.varDeclClass = info.varDeclClass; + fieldInfo.name = fieldName; + fieldInfo.tupleType = fieldType; + fieldInfo.tupleTypeDecl = makeDeclRef(fieldTupleTypeMod->decl); + fieldInfo.initExpr = fieldInitExpr; + fieldInfo.primaryVarLayout = fieldLayout; + fieldInfo.tupleTypeLayout = getBodyStructTypeLayout(fieldLayout ? fieldLayout->typeLayout : nullptr); + fieldInfo.arraySpecs = info.arraySpecs; + fieldTupleDecl->tupleType = fieldTupleTypeMod; - createTupleTypeSecondaryVarDecls( - fieldTupleDecl, - varDeclClass, - fieldName, - fieldType, - makeDeclRef(fieldTupleTypeMod->decl), - fieldInitExpr, - fieldLayout, - getBodyStructTypeLayout(fieldLayout ? fieldLayout->typeLayout : nullptr)); + createTupleTypeSecondaryVarDecls(fieldInfo); fieldVarOrTupleDecl = fieldTupleDecl; } else { // Otherwise the field has a simple type, and we just need to declare the variable here - RefPtr fieldVarDecl = varDeclClass.createInstance(); + + RefPtr fieldVarType = fieldType; + for (auto aa = info.arraySpecs; aa; aa = aa->next) + { + RefPtr arrayType = new ArrayExpressionType(); + arrayType->BaseType = fieldVarType; + arrayType->ArrayLength = aa->elementCount; + + fieldVarType = arrayType; + } + + RefPtr fieldVarDecl = info.varDeclClass.createInstance(); fieldVarDecl->Name.Content = fieldName; - fieldVarDecl->Type.type = fieldType; + fieldVarDecl->Type.type = fieldVarType; addDecl(fieldVarDecl); @@ -1911,7 +2060,7 @@ struct LoweringVisitor fieldTupleVarMod->tupleField = tupleFieldMod; addModifier(fieldVarOrTupleDecl, fieldTupleVarMod); - tupleDecl->tupleDecls.Add(fieldVarOrTupleDecl); + info.tupleDecl->tupleDecls.Add(fieldVarOrTupleDecl); } } @@ -1955,15 +2104,17 @@ struct LoweringVisitor addDecl(primaryVarDecl); } - createTupleTypeSecondaryVarDecls( - tupleDecl, - varDeclClass, - name, - tupleType, - tupleTypeDecl, - initExpr, - primaryVarLayout, - tupleTypeLayout); + TupleSecondaryVarInfo info; + info.tupleDecl = tupleDecl; + info.varDeclClass = varDeclClass; + info.name = name; + info.tupleType = tupleType; + info.tupleTypeDecl = tupleTypeDecl; + info.initExpr = initExpr; + info.primaryVarLayout = primaryVarLayout; + info.tupleTypeLayout = tupleTypeLayout; + + createTupleTypeSecondaryVarDecls(info); return tupleDecl; } @@ -1978,6 +2129,11 @@ struct LoweringVisitor typeLayout = parameterBlockTypeLayout->elementTypeLayout; } + while (auto arrayTypeLayout = typeLayout.As()) + { + typeLayout = arrayTypeLayout->elementTypeLayout; + } + if (auto structTypeLayout = typeLayout.As()) { return structTypeLayout; @@ -2020,7 +2176,7 @@ struct LoweringVisitor { auto loweredType = lowerType(decl->Type); - if (auto tupleTypeMod = isTupleType(loweredType)) + if (auto tupleTypeMod = isTupleTypeOrArrayOfTupleType(loweredType)) { auto varLayout = tryToFindLayout(decl).As(); @@ -2051,7 +2207,7 @@ struct LoweringVisitor auto varLayout = tryToFindLayout(decl).As(); auto elementType = bufferType->elementType; - if (auto elementTupleTypeMod = isTupleType(elementType)) + if (auto elementTupleTypeMod = isTupleTypeOrArrayOfTupleType(elementType)) { auto tupleDecl = createTupleTypeVarDecls( loweredDeclClass, diff --git a/source/slang/syntax.h b/source/slang/syntax.h index 83b2f5801..3f1c47fb9 100644 --- a/source/slang/syntax.h +++ b/source/slang/syntax.h @@ -244,7 +244,7 @@ namespace Slang : createFunc(createFunc) {} - void* createInstanceImpl() + void* createInstanceImpl() const { return createFunc ? createFunc() : nullptr; } @@ -271,7 +271,7 @@ namespace Slang { } - T* createInstance() + T* createInstance() const { return (T*)createInstanceImpl(); } -- cgit v1.2.3