summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-05-02 20:29:38 -0700
committerGitHub <noreply@github.com>2023-05-02 20:29:38 -0700
commitd52376a65f37fcbbb67428b917fd3819436b6dfb (patch)
treeda25b3c9a00bd003b1970b4a6c4eb38eccf62aa1 /source
parent55291b0bf6d729fcbaf75a01926da7da8975b8e9 (diff)
Various dxc/fxc compatibility fixes. (#2863)
* Various dxc/fxc compatibility fixes. * Cleanup. * Fix test cases. * Fix comments. --------- Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang14
-rw-r--r--source/slang/slang-api.cpp1
-rw-r--r--source/slang/slang-ast-modifier.h14
-rw-r--r--source/slang/slang-check-modifier.cpp34
-rwxr-xr-xsource/slang/slang-compiler.h12
-rw-r--r--source/slang/slang-diagnostic-defs.h4
-rw-r--r--source/slang/slang-emit-c-like.cpp69
-rw-r--r--source/slang/slang-emit-c-like.h11
-rw-r--r--source/slang/slang-emit-cuda.cpp4
-rw-r--r--source/slang/slang-emit-cuda.h2
-rw-r--r--source/slang/slang-emit-glsl.cpp40
-rw-r--r--source/slang/slang-emit-glsl.h2
-rw-r--r--source/slang/slang-emit-hlsl.cpp49
-rw-r--r--source/slang/slang-emit-hlsl.h4
-rw-r--r--source/slang/slang-emit.cpp6
-rw-r--r--source/slang/slang-ir-inst-defs.h2
-rw-r--r--source/slang/slang-ir-insts.h12
-rw-r--r--source/slang/slang-ir-legalize-uniform-buffer-load.cpp50
-rw-r--r--source/slang/slang-ir-legalize-uniform-buffer-load.h12
-rw-r--r--source/slang/slang-ir-use-uninitialized-out-param.cpp1
-rw-r--r--source/slang/slang-ir-util.cpp5
-rw-r--r--source/slang/slang-lower-to-ir.cpp35
-rw-r--r--source/slang/slang-options.cpp25
-rw-r--r--source/slang/slang-parameter-binding.cpp6
-rw-r--r--source/slang/slang-parser.cpp65
-rw-r--r--source/slang/slang-type-layout.cpp50
-rw-r--r--source/slang/slang-type-layout.h4
-rw-r--r--source/slang/slang.cpp11
28 files changed, 483 insertions, 61 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 6a35f496b..a2ed1d1df 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -762,6 +762,8 @@ struct String
}
};
+typedef String string;
+
__magic_type(NativeStringType)
__intrinsic_type($(kIROp_NativeStringType))
struct NativeString
@@ -1334,8 +1336,8 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
}
// `GetDimensions`
-
- for(int isFloat = 0; isFloat < 2; ++isFloat)
+ const char* dimParamTypes[] = {"out float ", "out int ", "out uint "};
+ for(auto t : dimParamTypes)
for(int includeMipInfo = 0; includeMipInfo < 2; ++includeMipInfo)
{
{
@@ -1417,8 +1419,6 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
sb << ")\")\n";
}
- char const* t = isFloat ? "out float " : "out uint ";
-
sb << "[__readNone]\n";
sb << "void GetDimensions(";
if(includeMipInfo)
@@ -2967,6 +2967,12 @@ attribute_syntax [vk_index(index : int)] : GLSLIndexAttribute;
__attributeTarget(FuncDecl)
attribute_syntax [vk_spirv_instruction(op : int, set : String = "")] : SPIRVInstructionOpAttribute;
+__attributeTarget(FuncDecl)
+attribute_syntax [spv_target_env_1_3] : SPIRVTargetEnv13Attribute;
+
+__attributeTarget(VarDeclBase)
+attribute_syntax [disable_array_flattening] : DisableArrayFlatteningAttribute;
+
// Statement Attributes
__attributeTarget(LoopStmt)
diff --git a/source/slang/slang-api.cpp b/source/slang/slang-api.cpp
index a03aa9071..864bc8b7d 100644
--- a/source/slang/slang-api.cpp
+++ b/source/slang/slang-api.cpp
@@ -284,7 +284,6 @@ SLANG_API void spSetLineDirectiveMode(
request->setLineDirectiveMode(mode);
}
-
SLANG_API void spSetTargetForceGLSLScalarBufferLayout(
slang::ICompileRequest* request, int targetIndex, bool forceScalarLayout)
{
diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h
index 1083afae4..ab66febb9 100644
--- a/source/slang/slang-ast-modifier.h
+++ b/source/slang/slang-ast-modifier.h
@@ -304,6 +304,8 @@ class HLSLRegisterSemantic : public HLSLLayoutSemantic
class HLSLPackOffsetSemantic : public HLSLLayoutSemantic
{
SLANG_AST_CLASS(HLSLPackOffsetSemantic)
+
+ Index uniformOffset = 0;
};
@@ -731,6 +733,18 @@ class SPIRVInstructionOpAttribute : public Attribute
SLANG_AST_CLASS(SPIRVInstructionOpAttribute)
};
+// [[spv_target_env_1_3]]
+class SPIRVTargetEnv13Attribute : public Attribute
+{
+ SLANG_AST_CLASS(SPIRVTargetEnv13Attribute);
+};
+
+// [[disable_array_flattening]]
+class DisableArrayFlatteningAttribute : public Attribute
+{
+ SLANG_AST_CLASS(DisableArrayFlatteningAttribute);
+};
+
// TODO: for attributes that take arguments, the syntax node
// classes should provide accessors for the values of those arguments.
diff --git a/source/slang/slang-check-modifier.cpp b/source/slang/slang-check-modifier.cpp
index 61f3f1196..2d5f6aad7 100644
--- a/source/slang/slang-check-modifier.cpp
+++ b/source/slang/slang-check-modifier.cpp
@@ -918,6 +918,40 @@ namespace Slang
// See SemanticsDeclHeaderVisitor::checkExtensionExternVarAttribute.
}
}
+
+ if (auto packOffsetModifier = as<HLSLPackOffsetSemantic>(m))
+ {
+ if (!packOffsetModifier->registerName.getContent().startsWith("c"))
+ {
+ getSink()->diagnose(packOffsetModifier, Diagnostics::unknownRegisterClass, packOffsetModifier->registerName);
+ return m;
+ }
+ auto uniformOffset = stringToInt(packOffsetModifier->registerName.getContent().tail(1)) * 16;
+ if (packOffsetModifier->componentMask.getContentLength())
+ {
+ switch (packOffsetModifier->componentMask.getContent()[0])
+ {
+ case 'x':
+ uniformOffset += 0;
+ break;
+ case 'y':
+ uniformOffset += 4;
+ break;
+ case 'z':
+ uniformOffset += 8;
+ break;
+ case 'w':
+ uniformOffset += 12;
+ break;
+ default:
+ getSink()->diagnose(packOffsetModifier, Diagnostics::invalidComponentMask, packOffsetModifier->componentMask);
+ break;
+ }
+ }
+ packOffsetModifier->uniformOffset = uniformOffset;
+ return packOffsetModifier;
+ }
+
// Default behavior is to leave things as they are,
// and assume that modifiers are mostly already checked.
//
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index fc46b25b6..117c3f037 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -1589,7 +1589,6 @@ namespace Slang
SlangTargetFlags getTargetFlags() { return targetFlags; }
CapabilitySet getTargetCaps();
bool getForceGLSLScalarBufferLayout() { return forceGLSLScalarBufferLayout; }
-
Session* getSession();
MatrixLayoutMode getDefaultMatrixLayoutMode();
@@ -1756,6 +1755,15 @@ namespace Slang
/// Get the parent session for this linkage
Session* getSessionImpl() { return m_session; }
+ bool getEnableEffectAnnotations()
+ {
+ return m_enableEffectAnnotations;
+ }
+ void setEnableEffectAnnotations(bool value)
+ {
+ m_enableEffectAnnotations = value;
+ }
+
// Information on the targets we are being asked to
// generate code for.
List<RefPtr<TargetRequest>> targets;
@@ -1914,6 +1922,7 @@ namespace Slang
bool m_requireCacheFileSystem = false;
bool m_useFalcorCustomSharedKeywordSemantics = false;
+ bool m_enableEffectAnnotations = false;
// Modules that have been read in with the -r option
List<ComPtr<IArtifact>> m_libModules;
@@ -2550,6 +2559,7 @@ namespace Slang
virtual SLANG_NO_THROW SlangCompileFlags SLANG_MCALL getCompileFlags() SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setDumpIntermediates(int enable) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setDumpIntermediatePrefix(const char* prefix) SLANG_OVERRIDE;
+ virtual SLANG_NO_THROW void SLANG_MCALL setEnableEffectAnnotations(bool value) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setLineDirectiveMode(SlangLineDirectiveMode mode) SLANG_OVERRIDE;
virtual SLANG_NO_THROW void SLANG_MCALL setCodeGenTarget(SlangCompileTarget target) SLANG_OVERRIDE;
virtual SLANG_NO_THROW int SLANG_MCALL addCodeGenTarget(SlangCompileTarget target) SLANG_OVERRIDE;
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 0b6494ad5..a35c48a6a 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -544,8 +544,8 @@ DIAGNOSTIC(39007, Error, unknownRegisterClass, "unknown register class: '$0'")
DIAGNOSTIC(39008, Error, expectedARegisterIndex, "expected a register index after '$0'")
DIAGNOSTIC(39009, Error, expectedSpace, "expected 'space', got '$0'")
DIAGNOSTIC(39010, Error, expectedSpaceIndex, "expected a register space index after 'space'")
-DIAGNOSTIC(39011, Error, componentMaskNotSupported, "explicit register component masks are not yet supported in Slang")
-DIAGNOSTIC(39012, Error, packOffsetNotSupported, "explicit 'packoffset' bindings are not yet supported in Slang")
+DIAGNOSTIC(39011, Error, invalidComponentMask, "invalid register component mask '$0'.")
+
DIAGNOSTIC(39013, Warning, registerModifierButNoVulkanLayout, "shader parameter '$0' has a 'register' specified for D3D, but no '[[vk::binding(...)]]` specified for Vulkan")
DIAGNOSTIC(39014, Error, unexpectedSpecifierAfterSpace, "unexpected specifier after register space: '$0'")
DIAGNOSTIC(39015, Error, wholeSpaceParameterRequiresZeroBinding, "shader parameter '$0' consumes whole descriptor sets, so the binding must be in the form '[[vk::binding(0, ...)]]'; the non-zero binding '$1' is not allowed")
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 5a40b51ef..2b5323e3f 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -1797,6 +1797,37 @@ void CLikeSourceEmitter::diagnoseUnhandledInst(IRInst* inst)
getSink()->diagnose(inst, Diagnostics::unimplemented, "unexpected IR opcode during code emit");
}
+bool CLikeSourceEmitter::hasExplicitConstantBufferOffset(IRInst* cbufferType)
+{
+ auto type = as<IRUniformParameterGroupType>(cbufferType);
+ if (!type)
+ return false;
+ if (as<IRGLSLShaderStorageBufferType>(cbufferType))
+ return false;
+ auto structType = as<IRStructType>(type->getElementType());
+ if (!structType)
+ return false;
+ for (auto ff : structType->getFields())
+ {
+ if (ff->getKey()->findDecoration<IRPackOffsetDecoration>())
+ return true;
+ }
+ return false;
+}
+
+bool CLikeSourceEmitter::isSingleElementConstantBuffer(IRInst* cbufferType)
+{
+ auto type = as<IRUniformParameterGroupType>(cbufferType);
+ if (!type)
+ return false;
+ if (as<IRGLSLShaderStorageBufferType>(cbufferType))
+ return false;
+ auto structType = as<IRStructType>(type->getElementType());
+ if (structType)
+ return false;
+ return true;
+}
+
void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inOuterPrec)
{
EmitOpInfo outerPrec = inOuterPrec;
@@ -1895,11 +1926,6 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
m_writer->emit("->");
else
m_writer->emit(".");
- if(getSourceLanguage() == SourceLanguage::GLSL
- && as<IRUniformParameterGroupType>(base->getDataType()))
- {
- m_writer->emit("_data.");
- }
m_writer->emit(getName(fieldExtract->getField()));
break;
}
@@ -1930,14 +1956,13 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
{
auto prec = getInfo(EmitOp::Postfix);
needClose = maybeEmitParens(outerPrec, prec);
-
- auto base = ii->getBase();
- emitOperand(base, leftSide(outerPrec, prec));
- m_writer->emit(".");
- if(getSourceLanguage() == SourceLanguage::GLSL
- && as<IRUniformParameterGroupType>(base->getDataType()))
+ auto skipBase = isD3DTarget(getTargetReq()) &&
+ hasExplicitConstantBufferOffset(ii->getBase()->getDataType());
+ if (!skipBase)
{
- m_writer->emit("_data.");
+ auto base = ii->getBase();
+ emitOperand(base, leftSide(outerPrec, prec));
+ m_writer->emit(".");
}
m_writer->emit(getName(ii->getField()));
}
@@ -2032,8 +2057,7 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
{
auto base = inst->getOperand(0);
emitDereferenceOperand(base, outerPrec);
- if(getSourceLanguage() == SourceLanguage::GLSL
- && as<IRUniformParameterGroupType>(base->getDataType()))
+ if (isKhronosTarget(getTargetReq()) && isSingleElementConstantBuffer(base->getDataType()))
{
m_writer->emit("._data");
}
@@ -2628,9 +2652,9 @@ void CLikeSourceEmitter::emitSemanticsUsingVarLayout(IRVarLayout* varLayout)
}
}
-void CLikeSourceEmitter::emitSemantics(IRInst* inst)
+void CLikeSourceEmitter::emitSemantics(IRInst* inst, bool allowOffsetLayout)
{
- emitSemanticsImpl(inst);
+ emitSemanticsImpl(inst, allowOffsetLayout);
}
void CLikeSourceEmitter::emitLayoutSemantics(IRInst* inst, char const* uniformSemanticSpelling)
@@ -3105,11 +3129,11 @@ void CLikeSourceEmitter::emitStruct(IRStructType* structType)
m_writer->emit(getName(structType));
- emitStructDeclarationsBlock(structType);
+ emitStructDeclarationsBlock(structType, false);
m_writer->emit(";\n\n");
}
-void CLikeSourceEmitter::emitStructDeclarationsBlock(IRStructType* structType)
+void CLikeSourceEmitter::emitStructDeclarationsBlock(IRStructType* structType, bool allowOffsetLayout)
{
m_writer->emit("\n{\n");
m_writer->indent();
@@ -3130,8 +3154,15 @@ void CLikeSourceEmitter::emitStructDeclarationsBlock(IRStructType* structType)
emitInterpolationModifiers(fieldKey, fieldType, nullptr);
}
+ if (allowOffsetLayout)
+ {
+ if (auto packOffsetDecoration = fieldKey->findDecoration<IRPackOffsetDecoration>())
+ {
+ emitPackOffsetModifier(fieldKey, fieldType, packOffsetDecoration);
+ }
+ }
emitType(fieldType, getName(fieldKey));
- emitSemantics(fieldKey);
+ emitSemantics(fieldKey, allowOffsetLayout);
m_writer->emit(";\n");
}
diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h
index bfe3dcc4e..393ab602c 100644
--- a/source/slang/slang-emit-c-like.h
+++ b/source/slang/slang-emit-c-like.h
@@ -292,6 +292,8 @@ public:
void emitType(IRType* type);
void emitType(IRType* type, Name* name, SourceLoc const& nameLoc);
void emitType(IRType* type, NameLoc const& nameAndLoc);
+ bool hasExplicitConstantBufferOffset(IRInst* cbufferType);
+ bool isSingleElementConstantBuffer(IRInst* cbufferType);
//
// Expressions
@@ -363,7 +365,7 @@ public:
void diagnoseUnhandledInst(IRInst* inst);
void emitInst(IRInst* inst);
- void emitSemantics(IRInst* inst);
+ void emitSemantics(IRInst* inst, bool allowOffsets = false);
void emitSemanticsUsingVarLayout(IRVarLayout* varLayout);
void emitLayoutSemantics(IRInst* inst, char const* uniformSemanticSpelling = "register");
@@ -405,7 +407,7 @@ public:
void emitStruct(IRStructType* structType);
// This is used independently of `emitStruct` by some GLSL parameter group
// output functionality
- void emitStructDeclarationsBlock(IRStructType* structType);
+ void emitStructDeclarationsBlock(IRStructType* structType, bool allowOffsetLayout);
void emitClass(IRClassType* structType);
/// Emit type attributes that should appear after, e.g., a `struct` keyword
@@ -413,7 +415,7 @@ public:
void emitInterpolationModifiers(IRInst* varInst, IRType* valueType, IRVarLayout* layout);
void emitMeshOutputModifiers(IRInst* varInst);
-
+ virtual void emitPackOffsetModifier(IRInst* /*varInst*/, IRType* /*valueType*/, IRPackOffsetDecoration* /*decoration*/) {};
/// Emit modifiers that should apply even for a declaration of an SSA temporary.
@@ -494,10 +496,11 @@ public:
virtual void emitPreModuleImpl() {}
virtual void emitRateQualifiersImpl(IRRate* rate) { SLANG_UNUSED(rate); }
- virtual void emitSemanticsImpl(IRInst* inst) { SLANG_UNUSED(inst); }
+ virtual void emitSemanticsImpl(IRInst* inst, bool allowOffsetLayout) { SLANG_UNUSED(inst); SLANG_UNUSED(allowOffsetLayout); }
virtual void emitSimpleFuncParamImpl(IRParam* param);
virtual void emitSimpleFuncParamsImpl(IRFunc* func);
virtual void emitInterpolationModifiersImpl(IRInst* varInst, IRType* valueType, IRVarLayout* layout) { SLANG_UNUSED(varInst); SLANG_UNUSED(valueType); SLANG_UNUSED(layout); }
+
virtual void emitMeshOutputModifiersImpl(IRInst* varInst) { SLANG_UNUSED(varInst) }
virtual void emitSimpleTypeImpl(IRType* type) = 0;
virtual void emitVarDecorationsImpl(IRInst* varDecl) { SLANG_UNUSED(varDecl); }
diff --git a/source/slang/slang-emit-cuda.cpp b/source/slang/slang-emit-cuda.cpp
index a1e21f626..a6501b5be 100644
--- a/source/slang/slang-emit-cuda.cpp
+++ b/source/slang/slang-emit-cuda.cpp
@@ -745,9 +745,9 @@ void CUDASourceEmitter::emitSimpleValueImpl(IRInst* inst)
}
-void CUDASourceEmitter::emitSemanticsImpl(IRInst* inst)
+void CUDASourceEmitter::emitSemanticsImpl(IRInst* inst, bool allowOffsetLayout)
{
- Super::emitSemanticsImpl(inst);
+ Super::emitSemanticsImpl(inst, allowOffsetLayout);
}
void CUDASourceEmitter::emitInterpolationModifiersImpl(IRInst* varInst, IRType* valueType, IRVarLayout* layout)
diff --git a/source/slang/slang-emit-cuda.h b/source/slang/slang-emit-cuda.h
index 2ba7dd6a3..47f6eea06 100644
--- a/source/slang/slang-emit-cuda.h
+++ b/source/slang/slang-emit-cuda.h
@@ -69,7 +69,7 @@ protected:
virtual void emitPreModuleImpl() SLANG_OVERRIDE;
virtual void emitRateQualifiersImpl(IRRate* rate) SLANG_OVERRIDE;
- virtual void emitSemanticsImpl(IRInst* inst) SLANG_OVERRIDE;
+ virtual void emitSemanticsImpl(IRInst* inst, bool allowOffsetLayout) SLANG_OVERRIDE;
virtual void emitSimpleFuncImpl(IRFunc* func) SLANG_OVERRIDE;
virtual void emitSimpleFuncParamsImpl(IRFunc* func) SLANG_OVERRIDE;
virtual void emitInterpolationModifiersImpl(IRInst* varInst, IRType* valueType, IRVarLayout* layout) SLANG_OVERRIDE;
diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp
index 0abd78137..bc170dadc 100644
--- a/source/slang/slang-emit-glsl.cpp
+++ b/source/slang/slang-emit-glsl.cpp
@@ -339,16 +339,25 @@ void GLSLSourceEmitter::_emitGLSLParameterGroup(IRGlobalParam* varDecl, IRUnifor
m_writer->emit("_S");
m_writer->emit(m_uniqueIDCounter++);
- m_writer->emit("\n{\n");
- m_writer->indent();
auto elementType = type->getElementType();
-
- emitType(elementType, "_data");
- m_writer->emit(";\n");
-
- m_writer->dedent();
- m_writer->emit("} ");
+ auto structType = as<IRStructType>(elementType);
+ if (!as<IRGLSLShaderStorageBufferType>(type) && structType)
+ {
+ // We need to emit the fields of the struct as individual variables
+ // in the constant buffer.
+ //
+ emitStructDeclarationsBlock(structType, true);
+ }
+ else
+ {
+ m_writer->emit("\n{\n");
+ m_writer->indent();
+ emitType(elementType, "_data");
+ m_writer->emit(";\n");
+ m_writer->dedent();
+ m_writer->emit("} ");
+ }
m_writer->emit(getName(varDecl));
@@ -794,7 +803,7 @@ void GLSLSourceEmitter::_maybeEmitGLSLBuiltin(IRGlobalParam* var, UnownedStringS
m_writer->emit("out");
m_writer->emit(" ");
m_writer->emit(elementTypeName);
- emitStructDeclarationsBlock(elementType);
+ emitStructDeclarationsBlock(elementType, false);
m_writer->emit(" ");
m_writer->emit(name);
emitArrayBrackets(arrayType);
@@ -1157,7 +1166,7 @@ void GLSLSourceEmitter::_emitGLSLPerVertexVaryingFragmentInput(IRGlobalParam* pa
//
_emitType(type, &arrayDeclarator);
- emitSemantics(param);
+ emitSemantics(param, false);
emitLayoutSemantics(param);
@@ -2372,6 +2381,17 @@ void GLSLSourceEmitter::emitInterpolationModifiersImpl(IRInst* varInst, IRType*
}
}
+void GLSLSourceEmitter::emitPackOffsetModifier(IRInst* varInst, IRType* valueType, IRPackOffsetDecoration* decoration)
+{
+ SLANG_UNUSED(varInst);
+ SLANG_UNUSED(valueType);
+
+ _requireGLSLExtension(UnownedStringSlice::fromLiteral("GL_ARB_enhanced_layouts"));
+ m_writer->emit("layout(offset = ");
+ m_writer->emit(decoration->getRegisterOffset()->getValue() * 16 + decoration->getComponentOffset()->getValue() * 4);
+ m_writer->emit(")\n");
+}
+
void GLSLSourceEmitter::emitMeshOutputModifiersImpl(IRInst* varInst)
{
if(varInst->findDecoration<IRGLSLPrimitivesRateDecoration>())
diff --git a/source/slang/slang-emit-glsl.h b/source/slang/slang-emit-glsl.h
index 99259463b..48c6971aa 100644
--- a/source/slang/slang-emit-glsl.h
+++ b/source/slang/slang-emit-glsl.h
@@ -33,6 +33,8 @@ protected:
virtual void emitRateQualifiersImpl(IRRate* rate) SLANG_OVERRIDE;
virtual void emitInterpolationModifiersImpl(IRInst* varInst, IRType* valueType, IRVarLayout* layout) SLANG_OVERRIDE;
+ virtual void emitPackOffsetModifier(IRInst* varInst, IRType* valueType, IRPackOffsetDecoration* decoration) SLANG_OVERRIDE;
+
virtual void emitMeshOutputModifiersImpl(IRInst* varInst) SLANG_OVERRIDE;
virtual void emitSimpleTypeImpl(IRType* type) SLANG_OVERRIDE;
virtual void emitVectorTypeNameImpl(IRType* elementType, IRIntegerValue elementCount) SLANG_OVERRIDE;
diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp
index e07d9facc..434f0803e 100644
--- a/source/slang/slang-emit-hlsl.cpp
+++ b/source/slang/slang-emit-hlsl.cpp
@@ -208,10 +208,20 @@ void HLSLSourceEmitter::_emitHLSLParameterGroup(IRGlobalParam* varDecl, IRUnifor
_emitHLSLRegisterSemantic(LayoutResourceKind::ConstantBuffer, &containerChain);
+ auto elementType = type->getElementType();
+ if (hasExplicitConstantBufferOffset(type))
+ {
+ // If the user has provided any explicit `packoffset` modifiers,
+ // we have to unwrap the struct and emit the fields directly.
+ emitStructDeclarationsBlock(as<IRStructType>(elementType), true);
+ m_writer->emit("\n");
+ return;
+ }
+
+
m_writer->emit("\n{\n");
m_writer->indent();
- auto elementType = type->getElementType();
emitType(elementType, getName(varDecl));
m_writer->emit(";\n");
@@ -989,7 +999,7 @@ void HLSLSourceEmitter::emitRateQualifiersImpl(IRRate* rate)
}
}
-void HLSLSourceEmitter::emitSemanticsImpl(IRInst* inst)
+void HLSLSourceEmitter::emitSemanticsImpl(IRInst* inst, bool allowOffsets)
{
if (auto semanticDecoration = inst->findDecoration<IRSemanticDecoration>())
{
@@ -997,6 +1007,33 @@ void HLSLSourceEmitter::emitSemanticsImpl(IRInst* inst)
m_writer->emit(semanticDecoration->getSemanticName());
return;
}
+ else if (auto packOffsetDecoration = inst->findDecoration<IRPackOffsetDecoration>())
+ {
+ if (allowOffsets)
+ {
+ m_writer->emit(" : packoffset(c");
+ m_writer->emit(packOffsetDecoration->getRegisterOffset()->getValue());
+ if (packOffsetDecoration->getComponentOffset())
+ {
+ switch (packOffsetDecoration->getComponentOffset()->getValue())
+ {
+ case 0:
+ break;
+ case 1:
+ m_writer->emit(".y");
+ break;
+ case 2:
+ m_writer->emit(".z");
+ break;
+ case 3:
+ m_writer->emit(".w");
+ break;
+ }
+ }
+ m_writer->emit(")");
+ return;
+ }
+ }
if( auto readAccessSemantic = inst->findDecoration<IRStageReadAccessDecoration>())
_emitStageAccessSemantic(readAccessSemantic, "read");
@@ -1114,6 +1151,14 @@ void HLSLSourceEmitter::emitInterpolationModifiersImpl(IRInst* varInst, IRType*
}
}
+void HLSLSourceEmitter::emitPackOffsetModifier(IRInst* varInst, IRType* valueType, IRPackOffsetDecoration* layout)
+{
+ SLANG_UNUSED(varInst);
+ SLANG_UNUSED(valueType);
+ SLANG_UNUSED(layout);
+ // We emit packoffset as a semantic in `emitSemantic`, so nothing to do here.
+}
+
void HLSLSourceEmitter::emitMeshOutputModifiersImpl(IRInst* varInst)
{
if(auto modifier = varInst->findDecoration<IRMeshOutputDecoration>())
diff --git a/source/slang/slang-emit-hlsl.h b/source/slang/slang-emit-hlsl.h
index 0a4e7fde8..d69e054b4 100644
--- a/source/slang/slang-emit-hlsl.h
+++ b/source/slang/slang-emit-hlsl.h
@@ -36,9 +36,11 @@ protected:
virtual void emitFrontMatterImpl(TargetRequest* targetReq) SLANG_OVERRIDE;
virtual void emitRateQualifiersImpl(IRRate* rate) SLANG_OVERRIDE;
- virtual void emitSemanticsImpl(IRInst* inst) SLANG_OVERRIDE;
+ virtual void emitSemanticsImpl(IRInst* inst, bool allowOffsets) SLANG_OVERRIDE;
virtual void emitSimpleFuncParamImpl(IRParam* param) SLANG_OVERRIDE;
virtual void emitInterpolationModifiersImpl(IRInst* varInst, IRType* valueType, IRVarLayout* layout) SLANG_OVERRIDE;
+ virtual void emitPackOffsetModifier(IRInst* varInst, IRType* valueType, IRPackOffsetDecoration* decoration) SLANG_OVERRIDE;
+
virtual void emitMeshOutputModifiersImpl(IRInst* varInst) SLANG_OVERRIDE;
virtual void emitSimpleTypeImpl(IRType* type) SLANG_OVERRIDE;
virtual void emitVectorTypeNameImpl(IRType* elementType, IRIntegerValue elementCount) SLANG_OVERRIDE;
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 62a1365c0..88b616996 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -54,6 +54,7 @@
#include "slang-ir-wrap-structured-buffers.h"
#include "slang-ir-liveness.h"
#include "slang-ir-glsl-liveness.h"
+#include "slang-ir-legalize-uniform-buffer-load.h"
#include "slang-ir-string-hash.h"
#include "slang-ir-simplify-for-emit.h"
#include "slang-ir-pytorch-cpp-binding.h"
@@ -846,6 +847,11 @@ Result linkAndOptimizeIR(
// arrays that the emitters can deal with.
legalizeMeshOutputTypes(irModule);
+ if (isKhronosTarget(targetRequest) || target == CodeGenTarget::HLSL)
+ {
+ legalizeUniformBufferLoad(irModule);
+ }
+
// Lower all bit_cast operations on complex types into leaf-level
// bit_cast on basic types.
lowerBitCast(targetRequest, irModule);
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index b00972cce..ffdd2b337 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -661,7 +661,6 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
INST(PublicDecoration, public, 0, 0)
INST(HLSLExportDecoration, hlslExport, 0, 0)
INST(PatchConstantFuncDecoration, patchConstantFunc, 1, 0)
-
INST(OutputControlPointsDecoration, outputControlPoints, 1, 0)
INST(OutputTopologyDecoration, outputTopology, 1, 0)
INST(PartitioningDecoration, partioning, 1, 0)
@@ -782,6 +781,7 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
INST_RANGE(StageAccessDecoration, StageReadAccessDecoration, StageWriteAccessDecoration)
INST(SemanticDecoration, semantic, 2, 0)
+ INST(PackOffsetDecoration, packoffset, 2, 0)
INST(SPIRVOpDecoration, spirvOpDecoration, 1, 0)
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 4495d1a3d..9c31798e0 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -1116,6 +1116,18 @@ struct IRSemanticDecoration : public IRDecoration
int getSemanticIndex() { return int(getIntVal(getSemanticIndexOperand())); }
};
+struct IRPackOffsetDecoration : IRDecoration
+{
+ enum
+ {
+ kOp = kIROp_PackOffsetDecoration
+ };
+ IR_LEAF_ISA(PackOffsetDecoration)
+
+ IRIntLit* getRegisterOffset() { return cast<IRIntLit>(getOperand(0)); }
+ IRIntLit* getComponentOffset() { return cast<IRIntLit>(getOperand(1)); }
+};
+
struct IRStageAccessDecoration : public IRDecoration
{
IR_PARENT_ISA(StageAccessDecoration)
diff --git a/source/slang/slang-ir-legalize-uniform-buffer-load.cpp b/source/slang/slang-ir-legalize-uniform-buffer-load.cpp
new file mode 100644
index 000000000..6acf38ee6
--- /dev/null
+++ b/source/slang/slang-ir-legalize-uniform-buffer-load.cpp
@@ -0,0 +1,50 @@
+#include "slang-ir-legalize-uniform-buffer-load.h"
+
+namespace Slang
+{
+void legalizeUniformBufferLoad(IRModule* module)
+{
+ List<IRLoad*> workList;
+ for (auto globalInst : module->getGlobalInsts())
+ {
+ if (auto func = as<IRGlobalValueWithCode>(globalInst))
+ {
+ for (auto block : func->getBlocks())
+ {
+ for (auto inst : block->getChildren())
+ {
+ if (auto load = as<IRLoad>(inst))
+ {
+ auto uniformBufferType = as<IRConstantBufferType>(load->getPtr()->getDataType());
+ if (!uniformBufferType)
+ continue;
+ workList.add(load);
+ }
+ }
+ }
+ }
+ }
+
+ IRBuilder builder(module);
+ for (auto load : workList)
+ {
+ auto uniformBufferType = as<IRConstantBufferType>(load->getPtr()->getDataType());
+ SLANG_ASSERT(uniformBufferType);
+ auto structType = as<IRStructType>(uniformBufferType->getElementType());
+ if (!structType)
+ continue;
+ builder.setInsertBefore(load);
+ List<IRInst*> fieldLoads;
+ for (auto field : structType->getFields())
+ {
+ auto fieldAddr = builder.emitFieldAddress(
+ builder.getPtrType(field->getFieldType()), load->getPtr(), field->getKey());
+ auto fieldLoad = builder.emitLoad(fieldAddr);
+ fieldLoads.add(fieldLoad);
+ }
+ auto makeStruct = builder.emitMakeStruct(structType, fieldLoads);
+ load->replaceUsesWith(makeStruct);
+ }
+}
+
+}
diff --git a/source/slang/slang-ir-legalize-uniform-buffer-load.h b/source/slang/slang-ir-legalize-uniform-buffer-load.h
new file mode 100644
index 000000000..fff1867b6
--- /dev/null
+++ b/source/slang/slang-ir-legalize-uniform-buffer-load.h
@@ -0,0 +1,12 @@
+// slang-ir-legalize-uniform-buffer-load.h
+#pragma once
+
+#include "slang-ir-insts.h"
+
+namespace Slang
+{
+ struct IRModule;
+
+ // Legalize a load(IRUniformParameterGroupType) into a makeStruct(load(fieldAddr),...) for glsl.
+ void legalizeUniformBufferLoad(IRModule* module);
+}
diff --git a/source/slang/slang-ir-use-uninitialized-out-param.cpp b/source/slang/slang-ir-use-uninitialized-out-param.cpp
index 64f5f8bd3..977876c6b 100644
--- a/source/slang/slang-ir-use-uninitialized-out-param.cpp
+++ b/source/slang/slang-ir-use-uninitialized-out-param.cpp
@@ -63,6 +63,7 @@ namespace Slang
addresses.add(use->getUser());
break;
case kIROp_Store:
+ case kIROp_SwizzledStore:
// If we see a store of this address, add it to stores set.
if (use == use->getUser()->getOperands())
stores.add(StoreSite{ use->getUser(), addr });
diff --git a/source/slang/slang-ir-util.cpp b/source/slang/slang-ir-util.cpp
index 95240a26c..506e96c81 100644
--- a/source/slang/slang-ir-util.cpp
+++ b/source/slang/slang-ir-util.cpp
@@ -430,6 +430,11 @@ bool canInstHaveSideEffectAtAddress(IRGlobalValueWithCode* func, IRInst* inst, I
if (canAddressesPotentiallyAlias(func, as<IRStore>(inst)->getPtr(), addr))
return true;
break;
+ case kIROp_SwizzledStore:
+ // If the target of the swizzled store inst may overlap addr, return true.
+ if (canAddressesPotentiallyAlias(func, as<IRSwizzledStore>(inst)->getDest(), addr))
+ return true;
+ break;
case kIROp_Call:
{
auto call = as<IRCall>(inst);
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 1511615ed..de2d5aff2 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -7648,6 +7648,11 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
irAggType,
fieldKey,
fieldType);
+
+ if (auto packOffsetModifier = fieldDecl->findModifier<HLSLPackOffsetSemantic>())
+ {
+ lowerPackOffsetModifier(fieldKey, packOffsetModifier);
+ }
}
// There may be members not handled by the above logic (e.g.,
@@ -7663,6 +7668,36 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
return LoweredValInfo::simple(finishOuterGenerics(subBuilder, irAggType, outerGeneric));
}
+ void lowerPackOffsetModifier(IRInst* inst, HLSLPackOffsetSemantic* semantic)
+ {
+ auto builder = getBuilder();
+ int registerOffset = stringToInt(semantic->registerName.getName()->text.getUnownedSlice().tail(1));
+ int componentOffset = 0;
+ if (semantic->componentMask.getContentLength() != 0)
+ {
+ switch (semantic->componentMask.getContent()[0])
+ {
+ case 'x':
+ componentOffset = 0;
+ break;
+ case 'y':
+ componentOffset = 1;
+ break;
+ case 'z':
+ componentOffset = 2;
+ break;
+ case 'w':
+ componentOffset = 3;
+ break;
+ }
+ }
+ builder->addDecoration(
+ inst,
+ kIROp_PackOffsetDecoration,
+ builder->getIntValue(builder->getIntType(), registerOffset),
+ builder->getIntValue(builder->getIntType(), componentOffset));
+ }
+
void lowerRayPayloadAccessModifier(IRInst* inst, RayPayloadAccessSemantic* semantic, IROp op)
{
auto builder = getBuilder();
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 8437d9a6c..353c6e57f 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -81,6 +81,8 @@ enum class OptionKind
LineDirectiveMode,
Optimization,
Obfuscate,
+ GLSLForceScalarLayout,
+ EnableEffectAnnotations,
// Downstream
@@ -415,6 +417,13 @@ void initCommandOptions(CommandOptions& options)
"for GLSL output." },
{ OptionKind::Optimization, "-O...", "-O<optimization-level>", "Set the optimization level."},
{ OptionKind::Obfuscate, "-obfuscate", nullptr, "Remove all source file information from outputs." },
+ { OptionKind::GLSLForceScalarLayout,
+ "-force-glsl-scalar-layout",
+ nullptr,
+ "Force using scalar block layout for uniform and shader storage buffers in GLSL output."},
+ { OptionKind::EnableEffectAnnotations,
+ "-enable-effect-annotations",
+ "Enables support for legacy effect annotation syntax."},
};
_addOptions(makeConstArrayView(targetOpts), options);
@@ -656,7 +665,7 @@ struct OptionsParser
SlangTargetFlags targetFlags = 0;
int targetID = -1;
FloatingPointMode floatingPointMode = FloatingPointMode::Default;
-
+ bool forceGLSLScalarLayout = false;
List<CapabilityAtom> capabilityAtoms;
// State for tracking command-line errors
@@ -1831,6 +1840,16 @@ struct OptionsParser
setFloatingPointMode(getCurrentTarget(), FloatingPointMode(value));
break;
}
+ case OptionKind::GLSLForceScalarLayout:
+ {
+ getCurrentTarget()->forceGLSLScalarLayout = true;
+ break;
+ }
+ case OptionKind::EnableEffectAnnotations:
+ {
+ compileRequest->setEnableEffectAnnotations(true);
+ break;
+ }
case OptionKind::Optimization:
{
UnownedStringSlice levelSlice = argValue.getUnownedSlice().tail(2);
@@ -2525,6 +2544,10 @@ struct OptionsParser
{
compileRequest->setTargetFloatingPointMode(targetID, SlangFloatingPointMode(rawTarget.floatingPointMode));
}
+ if (rawTarget.forceGLSLScalarLayout)
+ {
+ compileRequest->setTargetForceGLSLScalarBufferLayout(targetID, true);
+ }
}
if(defaultMatrixLayoutMode != SLANG_MATRIX_LAYOUT_MODE_UNKNOWN)
diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp
index bd33b6f37..721d4204d 100644
--- a/source/slang/slang-parameter-binding.cpp
+++ b/source/slang/slang-parameter-binding.cpp
@@ -594,12 +594,6 @@ LayoutSemanticInfo ExtractLayoutSemanticInfo(
spaceToken->loc,
getSink(context));
- // TODO: handle component mask part of things...
- if( semantic->componentMask.hasContent())
- {
- getSink(context)->diagnose(semantic->componentMask, Diagnostics::componentMaskNotSupported);
- }
-
return info;
}
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index 88cc6fac2..78433a96f 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -77,6 +77,11 @@ namespace Slang
Postfix,
};
+ struct ParserOptions
+ {
+ bool enableEffectAnnotations = false;
+ };
+
// TODO: implement two pass parsing for file reference and struct type recognition
class Parser
@@ -103,6 +108,7 @@ namespace Slang
TokenReader tokenReader;
DiagnosticSink* sink;
SourceLoc lastErrorLoc;
+ ParserOptions options;
int genericDepth = 0;
@@ -150,11 +156,13 @@ namespace Slang
ASTBuilder* inAstBuilder,
TokenSpan const& _tokens,
DiagnosticSink * sink,
- Scope* outerScope)
+ Scope* outerScope,
+ ParserOptions inOptions)
: tokenReader(_tokens)
, astBuilder(inAstBuilder)
, sink(sink)
, outerScope(outerScope)
+ , options(inOptions)
{}
Parser(const Parser & other) = default;
@@ -1750,6 +1758,51 @@ namespace Slang
case TokenType::LParent:
break;
+ case TokenType::OpLess:
+ {
+ if (parser->options.enableEffectAnnotations)
+ {
+ // If we are in a context where effect annotations are allowed,
+ // then we need to disambiguate the content after "<" to see if it
+ // should be parsed as an annotation or generic argument list.
+ // If we can determine the content inside a `<>` is an annotation,
+ // we will skip the tokens inside the angle brackets.
+ //
+ if (parser->tokenReader.peekTokenType() == TokenType::OpLess)
+ {
+ if (parser->LookAheadToken("let", 1))
+ {
+ // If we see `<let` then we are looking at a generic arg list.
+ }
+ else if (parser->LookAheadToken(":", 2))
+ {
+ // If we see a "< xxx :", we can also parse it as a generic arg list.
+ }
+ else
+ {
+ // Otherwise, we may be looking at an effect annotation.
+ // For now we just skip tokens until we see `>`, if we see any `;` in between,
+ // we can conclude that this is an annotation.
+ TokenReader tempReader = parser->tokenReader;
+ bool foundSemicolon = false;
+ while (tempReader.peekTokenType() != TokenType::OpGreater &&
+ tempReader.peekTokenType() != TokenType::EndOfFile)
+ {
+ if (tempReader.peekTokenType() == TokenType::Semicolon)
+ foundSemicolon = true;
+ tempReader.advanceToken();
+ }
+ if (foundSemicolon)
+ {
+ parser->tokenReader = tempReader;
+ parser->ReadToken(TokenType::OpGreater);
+ }
+ }
+ }
+ }
+
+ }
+ break;
default:
break;
}
@@ -2570,7 +2623,6 @@ namespace Slang
&& !initDeclarator.initializer
&& !initDeclarator.semantics.first)
{
- // Looks like a function, so parse it like one.
UnwrapDeclarator(parser->astBuilder, initDeclarator, &declaratorInfo);
return parseTraditionalFuncDecl(parser, declaratorInfo);
}
@@ -2714,8 +2766,6 @@ namespace Slang
parseHLSLRegisterNameAndOptionalComponentMask(parser, semantic);
parser->ReadToken(TokenType::RParent);
-
- parser->sink->diagnose(semantic, Diagnostics::packOffsetNotSupported);
}
static RayPayloadAccessSemantic* _parseRayPayloadAccessSemantic(Parser* parser, RayPayloadAccessSemantic* semantic)
@@ -6155,7 +6205,7 @@ namespace Slang
NamePool* namePool,
SourceLanguage sourceLanguage)
{
- Parser parser(astBuilder, tokens, sink, outerScope);
+ Parser parser(astBuilder, tokens, sink, outerScope, ParserOptions{});
parser.currentScope = outerScope;
parser.namePool = namePool;
parser.sourceLanguage = sourceLanguage;
@@ -6170,7 +6220,10 @@ namespace Slang
DiagnosticSink* sink,
Scope* outerScope)
{
- Parser parser(astBuilder, tokens, sink, outerScope);
+ ParserOptions options = {};
+ options.enableEffectAnnotations = translationUnit->compileRequest->getLinkage()->getEnableEffectAnnotations();
+
+ Parser parser(astBuilder, tokens, sink, outerScope, options);
parser.namePool = translationUnit->getNamePool();
parser.sourceLanguage = translationUnit->sourceLanguage;
diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp
index 0f1341afd..79236fc48 100644
--- a/source/slang/slang-type-layout.cpp
+++ b/source/slang/slang-type-layout.cpp
@@ -3183,6 +3183,35 @@ RefPtr<VarLayout> StructTypeLayoutBuilder::addField(
return fieldLayout;
}
+RefPtr<VarLayout> StructTypeLayoutBuilder::addExplicitUniformField(DeclRef<VarDeclBase> field, TypeLayoutResult fieldResult)
+{
+ auto packoffsetModifier = field.getDecl()->findModifier<HLSLPackOffsetSemantic>();
+ if (!packoffsetModifier)
+ return nullptr;
+
+ RefPtr<VarLayout> fieldLayout = new VarLayout();
+ fieldLayout->varDecl = field;
+ fieldLayout->typeLayout = fieldResult.layout;
+ m_typeLayout->fields.add(fieldLayout);
+ if (field)
+ {
+ m_typeLayout->mapVarToLayout.add(field.getDecl(), fieldLayout);
+ }
+ UInt uniformOffset = packoffsetModifier->uniformOffset;
+ if (fieldResult.layout->FindResourceInfo(LayoutResourceKind::Uniform))
+ {
+ fieldLayout->AddResourceInfo(LayoutResourceKind::Uniform)->index = uniformOffset;
+ }
+ UniformLayoutInfo fieldInfo = fieldResult.info.getUniformLayout();
+ auto uniformInfo = m_info;
+ m_rules->AddStructField(&uniformInfo, fieldInfo);
+ m_info.alignment = uniformInfo.alignment;
+ m_info.size.raw = Math::Max(
+ m_info.size.getFiniteValue(),
+ (size_t)(uniformOffset + fieldResult.layout->FindResourceInfo(LayoutResourceKind::Uniform)->count.getFiniteValue()));
+ return fieldLayout;
+}
+
RefPtr<VarLayout> StructTypeLayoutBuilder::addField(
DeclRef<VarDeclBase> field,
RefPtr<TypeLayout> fieldTypeLayout)
@@ -3684,8 +3713,29 @@ static TypeLayoutResult _createTypeLayout(
typeLayoutBuilder.beginLayout(type, rules);
auto typeLayout = typeLayoutBuilder.getTypeLayout();
+
+ // First, add all fields with explicit offsets.
+ for (auto field : getFields(structDeclRef, MemberFilterStyle::Instance))
+ {
+ // If the field has an explicit offset, then we will
+ // use that to place it.
+ //
+ if (auto packOffsetModifier = field.getDecl()->findModifier<HLSLPackOffsetSemantic>())
+ {
+ TypeLayoutResult fieldResult = _createTypeLayout(
+ context,
+ getType(context.astBuilder, field),
+ field.getDecl());
+ typeLayoutBuilder.addExplicitUniformField(field, fieldResult);
+ continue;
+ }
+
+ }
for (auto field : getFields(structDeclRef, MemberFilterStyle::Instance))
{
+ if (auto packOffsetModifier = field.getDecl()->findModifier<HLSLPackOffsetSemantic>())
+ continue;
+
// The fields of a `struct` type may include existential (interface)
// types (including as nested sub-fields), and any types present
// in those fields will need to be specialized based on the
diff --git a/source/slang/slang-type-layout.h b/source/slang/slang-type-layout.h
index e0b391232..0b6dd42d8 100644
--- a/source/slang/slang-type-layout.h
+++ b/source/slang/slang-type-layout.h
@@ -1138,6 +1138,10 @@ public:
DeclRef<VarDeclBase> field,
TypeLayoutResult fieldResult);
+ RefPtr<VarLayout> addExplicitUniformField(
+ DeclRef<VarDeclBase> field,
+ TypeLayoutResult fieldResult);
+
/// Add a field to the struct type layout.
///
/// One of the `beginLayout*()` functions must have been called previously.
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index 9c75aa63e..ec5a7084e 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -608,6 +608,12 @@ SLANG_NO_THROW SlangResult SLANG_MCALL Session::createSession(
{
linkage->setFileSystem(desc.fileSystem);
}
+
+ if (desc.structureSize >= offsetof(slang::SessionDesc, enableEffectAnnotations))
+ {
+ linkage->setEnableEffectAnnotations(desc.enableEffectAnnotations);
+ }
+
*outSession = asExternal(linkage.detach());
return SLANG_OK;
}
@@ -4804,6 +4810,11 @@ void EndToEndCompileRequest::addPreprocessorDefine(const char* key, const char*
getLinkage()->addPreprocessorDefine(key, value);
}
+void EndToEndCompileRequest::setEnableEffectAnnotations(bool value)
+{
+ getLinkage()->setEnableEffectAnnotations(value);
+}
+
char const* EndToEndCompileRequest::getDiagnosticOutput()
{
return m_diagnosticOutput.begin();