diff options
Diffstat (limited to 'source')
28 files changed, 351 insertions, 77 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 249a084b1..817e3c39d 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -1871,7 +1871,7 @@ for (int tt = 0; tt < kBaseTypeCount; ++tt) //@ public: -__generic<T> +__generic<T, L:IBufferDataLayout = DefaultDataLayout> __intrinsic_type($(kIROp_ConstantBufferType)) __magic_type(ConstantBufferType) struct ConstantBuffer {} diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index 7eb4af135..84beb3b4b 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -10,12 +10,14 @@ void __requireGLSLExtension(String extensionName); /// Represents an interface for buffer data layout. /// This interface is used as a base for defining specific data layouts for buffers. [sealed] +__magic_type(IBufferDataLayoutType) interface IBufferDataLayout { } /// @category misc_types __intrinsic_type($(kIROp_DefaultBufferLayoutType)) +__magic_type(DefaultDataLayoutType) struct DefaultDataLayout : IBufferDataLayout {}; @@ -23,6 +25,7 @@ struct DefaultDataLayout : IBufferDataLayout __intrinsic_type($(kIROp_Std140BufferLayoutType)) [require(spirv)] [require(glsl)] +__magic_type(Std140DataLayoutType) struct Std140DataLayout : IBufferDataLayout {}; @@ -30,11 +33,13 @@ struct Std140DataLayout : IBufferDataLayout __intrinsic_type($(kIROp_Std430BufferLayoutType)) [require(spirv)] [require(glsl)] +__magic_type(Std430DataLayoutType) struct Std430DataLayout : IBufferDataLayout {}; /// @category misc_types __intrinsic_type($(kIROp_ScalarBufferLayoutType)) +__magic_type(ScalarDataLayoutType) struct ScalarDataLayout : IBufferDataLayout {}; @@ -20588,7 +20593,7 @@ const char* kDynamicResourceCastableTypes[] = { "SamplerState", "SamplerComparisonState", - "ConstantBuffer<T>", "TextureBuffer<T>", + "ConstantBuffer<T, L>", "TextureBuffer<T>", }; for (auto typeName : kDynamicResourceCastableTypes) { @@ -20596,6 +20601,8 @@ for (auto typeName : kDynamicResourceCastableTypes) { if (strstr(typeName, "StructuredBuffer<T, L>")) sb << "__generic<T, L : IBufferDataLayout = DefaultDataLayout>\n"; + else if (strstr(typeName, "ConstantBuffer<T, L>")) + sb << "__generic<T, L : IBufferDataLayout = DefaultDataLayout>\n"; else if (strstr(typeName, "Buffer<T>")) sb << "__generic<T>\n"; }}}} diff --git a/source/slang/slang-ast-builder.cpp b/source/slang/slang-ast-builder.cpp index 575c7268b..6ffaee7db 100644 --- a/source/slang/slang-ast-builder.cpp +++ b/source/slang/slang-ast-builder.cpp @@ -146,6 +146,16 @@ Type* SharedASTBuilder::getDiffInterfaceType() return m_diffInterfaceType; } +Type* SharedASTBuilder::getIBufferDataLayoutType() +{ + if (!m_IBufferDataLayoutType) + { + auto decl = findMagicDecl("IBufferDataLayoutType"); + m_IBufferDataLayoutType = DeclRefType::create(m_astBuilder, makeDeclRef<Decl>(decl)); + } + return m_IBufferDataLayoutType; +} + Type* SharedASTBuilder::getErrorType() { if (!m_errorType) @@ -296,6 +306,23 @@ PtrType* ASTBuilder::getPtrType(Type* valueType, AddressSpace addrSpace) return dynamicCast<PtrType>(getPtrType(valueType, addrSpace, "PtrType")); } +Type* ASTBuilder::getDefaultLayoutType() +{ + return getSpecializedBuiltinType({}, "DefaultDataLayoutType"); +} +Type* ASTBuilder::getStd140LayoutType() +{ + return getSpecializedBuiltinType({}, "Std140DataLayoutType"); +} +Type* ASTBuilder::getStd430LayoutType() +{ + return getSpecializedBuiltinType({}, "Std430DataLayoutType"); +} +Type* ASTBuilder::getScalarLayoutType() +{ + return getSpecializedBuiltinType({}, "ScalarDataLayoutType"); +} + // Construct the type `Out<valueType>` OutType* ASTBuilder::getOutType(Type* valueType) { @@ -358,9 +385,15 @@ ArrayExpressionType* ASTBuilder::getArrayType(Type* elementType, IntVal* element getSpecializedBuiltinType(makeArrayView(args), "ArrayExpressionType")); } -ConstantBufferType* ASTBuilder::getConstantBufferType(Type* elementType) +ConstantBufferType* ASTBuilder::getConstantBufferType( + Type* elementType, + Type* layoutType, + Val* layoutWitness) { - return as<ConstantBufferType>(getSpecializedBuiltinType(elementType, "ConstantBufferType")); + Val* args[] = {elementType, layoutType, layoutWitness}; + + return as<ConstantBufferType>( + getSpecializedBuiltinType(makeArrayView(args), "ConstantBufferType")); } ParameterBlockType* ASTBuilder::getParameterBlockType(Type* elementType) diff --git a/source/slang/slang-ast-builder.h b/source/slang/slang-ast-builder.h index 22f6bb91e..bd5c9b4e3 100644 --- a/source/slang/slang-ast-builder.h +++ b/source/slang/slang-ast-builder.h @@ -39,6 +39,8 @@ public: /// Get the `IDifferentiable` type Type* getDiffInterfaceType(); + Type* getIBufferDataLayoutType(); + Type* getErrorType(); Type* getBottomType(); Type* getInitializerListType(); @@ -89,6 +91,7 @@ protected: Type* m_bottomType = nullptr; Type* m_initializerListType = nullptr; Type* m_overloadedType = nullptr; + Type* m_IBufferDataLayoutType = nullptr; // The following types are created lazily, such that part of their definition // can be in the core module. @@ -482,6 +485,11 @@ public: Type* getSpecializedBuiltinType(Type* typeParam, const char* magicTypeName); Type* getSpecializedBuiltinType(ArrayView<Val*> genericArgs, const char* magicTypeName); + Type* getDefaultLayoutType(); + Type* getStd140LayoutType(); + Type* getStd430LayoutType(); + Type* getScalarLayoutType(); + Type* getInitializerListType() { return m_sharedASTBuilder->getInitializerListType(); } Type* getOverloadedType() { return m_sharedASTBuilder->getOverloadedType(); } Type* getErrorType() { return m_sharedASTBuilder->getErrorType(); } @@ -525,7 +533,10 @@ public: IntVal* colCount, IntVal* layout); - ConstantBufferType* getConstantBufferType(Type* elementType); + ConstantBufferType* getConstantBufferType( + Type* elementType, + Type* layoutType, + Val* layoutIsILayout); ParameterBlockType* getParameterBlockType(Type* elementType); diff --git a/source/slang/slang-ast-type.h b/source/slang/slang-ast-type.h index c55e0011f..c5c5de5d2 100644 --- a/source/slang/slang-ast-type.h +++ b/source/slang/slang-ast-type.h @@ -113,6 +113,36 @@ class BuiltinType : public DeclRefType SLANG_ABSTRACT_AST_CLASS(BuiltinType) }; +class DataLayoutType : public BuiltinType +{ + SLANG_ABSTRACT_AST_CLASS(DataLayoutType) +}; + +class IBufferDataLayoutType : public BuiltinType +{ + SLANG_AST_CLASS(IBufferDataLayoutType) +}; + +class DefaultDataLayoutType : public DataLayoutType +{ + SLANG_AST_CLASS(DefaultDataLayoutType) +}; + +class Std430DataLayoutType : public DataLayoutType +{ + SLANG_AST_CLASS(Std430DataLayoutType) +}; + +class Std140DataLayoutType : public DataLayoutType +{ + SLANG_AST_CLASS(Std140DataLayoutType) +}; + +class ScalarDataLayoutType : public DataLayoutType +{ + SLANG_AST_CLASS(ScalarDataLayoutType) +}; + class FeedbackType : public BuiltinType { SLANG_AST_CLASS(FeedbackType) @@ -374,6 +404,7 @@ class ParameterGroupType : public PointerLikeType class UniformParameterGroupType : public ParameterGroupType { SLANG_AST_CLASS(UniformParameterGroupType) + Type* getLayoutType(); }; class VaryingParameterGroupType : public ParameterGroupType diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 07d5dd1fa..251ce6a69 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -110,6 +110,7 @@ struct SemanticsDeclHeaderVisitor : public SemanticsDeclVisitorBase, void checkMeshOutputDecl(VarDeclBase* varDecl); void maybeApplyLayoutModifier(VarDeclBase* varDecl); void checkVarDeclCommon(VarDeclBase* varDecl); + void checkPushConstantBufferType(VarDeclBase* varDecl); void visitVarDecl(VarDecl* varDecl) { checkVarDeclCommon(varDecl); } @@ -1707,6 +1708,10 @@ void SemanticsDeclHeaderVisitor::maybeApplyLayoutModifier(VarDeclBase* varDecl) addModifier(varDecl, formatAttrib); } } + else + { + checkPushConstantBufferType(varDecl); + } } bool isSpecializationConstant(VarDeclBase* varDecl) @@ -1721,6 +1726,32 @@ bool isSpecializationConstant(VarDeclBase* varDecl) return false; } +void SemanticsDeclHeaderVisitor::checkPushConstantBufferType(VarDeclBase* varDecl) +{ + if (varDecl->findModifier<PushConstantAttribute>()) + { + // If we see a ConstantBuffer<T, DefaultLayout> parameter marked as "push_constant", we need + // to set its type to ConstantBuffer<T, Std430>. + if (auto cbufferType = as<ConstantBufferType>(varDecl->type)) + { + if (cbufferType->getLayoutType() == m_astBuilder->getDefaultLayoutType()) + { + varDecl->type.type = getConstantBufferType( + cbufferType->getElementType(), + m_astBuilder->getStd430LayoutType()); + } + } + else if (isGlobalShaderParameter(varDecl)) + { + // If this is a global variable with [vk::push_constant] attribute, + // we need to make sure to wrap it in a `ConstantBuffer`. + // + varDecl->type.type = + getConstantBufferType(varDecl->type, m_astBuilder->getStd430LayoutType()); + } + } +} + void SemanticsDeclHeaderVisitor::checkVarDeclCommon(VarDeclBase* varDecl) { // A variable that didn't have an explicit type written must @@ -1935,20 +1966,8 @@ void SemanticsDeclHeaderVisitor::checkVarDeclCommon(VarDeclBase* varDecl) } } - if (as<NamespaceDeclBase>(varDecl->parentDecl)) { - // If this is a global variable with [vk::push_constant] attribute, - // we need to make sure to wrap it in a `ConstantBuffer`. - - if (!as<ConstantBufferType>(varDecl->type)) - { - if (varDecl->findModifier<PushConstantAttribute>()) - { - varDecl->type.type = m_astBuilder->getConstantBufferType(varDecl->type); - } - } - if (getModuleDecl(varDecl)->hasModifier<GLSLModuleModifier>()) { // If we are in GLSL compatiblity mode, we want to treat all global variables diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h index 95a6d00cc..95ec872a5 100644 --- a/source/slang/slang-check-impl.h +++ b/source/slang/slang-check-impl.h @@ -1149,6 +1149,8 @@ public: TypeExp TranslateTypeNodeForced(TypeExp const& typeExp); TypeExp TranslateTypeNode(TypeExp const& typeExp); Type* getRemovedModifierType(ModifiedType* type, ModifierVal* modifier); + Type* getConstantBufferType(Type* elementType, Type* layoutType); + DeclRefType* getExprDeclRefType(Expr* expr); /// Is `decl` usable as a static member? diff --git a/source/slang/slang-check-shader.cpp b/source/slang/slang-check-shader.cpp index 80c950c17..52a70034a 100644 --- a/source/slang/slang-check-shader.cpp +++ b/source/slang/slang-check-shader.cpp @@ -280,6 +280,8 @@ bool isUniformParameterType(Type* type) return true; if (as<SamplerStateType>(type)) return true; + if (as<PtrType>(type)) + return true; if (auto arrayType = as<ArrayExpressionType>(type)) return isUniformParameterType(arrayType->getElementType()); if (auto modType = as<ModifiedType>(type)) diff --git a/source/slang/slang-check-type.cpp b/source/slang/slang-check-type.cpp index 34f16751b..d9691a828 100644 --- a/source/slang/slang-check-type.cpp +++ b/source/slang/slang-check-type.cpp @@ -101,6 +101,13 @@ Type* SemanticsVisitor::getRemovedModifierType(ModifiedType* modifiedType, Modif return m_astBuilder->getModifiedType(modifiedType->getBase(), newModifiers); } +Type* SemanticsVisitor::getConstantBufferType(Type* elementType, Type* layoutType) +{ + auto iBufferDataLayoutType = m_astBuilder->getSharedASTBuilder()->getIBufferDataLayoutType(); + auto witness = isSubtype(layoutType, iBufferDataLayoutType, IsSubTypeOptions()); + return m_astBuilder->getConstantBufferType(elementType, layoutType, witness); +} + Expr* SemanticsVisitor::ExpectATypeRepr(Expr* expr) { if (auto overloadedExpr = as<OverloadedExpr>(expr)) diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp index 43ab7b74e..6c525d064 100644 --- a/source/slang/slang-emit-glsl.cpp +++ b/source/slang/slang-emit-glsl.cpp @@ -478,8 +478,31 @@ void GLSLSourceEmitter::_emitGLSLParameterGroup( { // uniform is implicitly read only m_writer->emit("layout("); - m_writer->emit( - getTargetProgram()->getOptionSet().shouldUseScalarLayout() ? "scalar" : "std140"); + if (getTargetProgram()->getOptionSet().shouldUseScalarLayout()) + m_writer->emit("scalar"); + else if (auto cbufferType = as<IRConstantBufferType>(type)) + { + switch (cbufferType->getDataLayout()->getOp()) + { + case kIROp_Std140BufferLayoutType: + m_writer->emit("std140"); + break; + case kIROp_Std430BufferLayoutType: + m_writer->emit("std430"); + break; + case kIROp_ScalarBufferLayoutType: + _requireGLSLExtension(toSlice("GL_EXT_scalar_block_layout")); + m_writer->emit("scalar"); + break; + default: + m_writer->emit("std140"); + break; + } + } + else + { + m_writer->emit("std140"); + } m_writer->emit(") uniform "); } diff --git a/source/slang/slang-emit-hlsl.cpp b/source/slang/slang-emit-hlsl.cpp index 26d37d1f5..824680b72 100644 --- a/source/slang/slang-emit-hlsl.cpp +++ b/source/slang/slang-emit-hlsl.cpp @@ -1310,6 +1310,13 @@ void HLSLSourceEmitter::emitSimpleTypeImpl(IRType* type) _emitHLSLSubpassInputType(subpassType); return; } + else if (auto cbufferType = as<IRConstantBufferType>(type)) + { + m_writer->emit("ConstantBuffer<"); + emitType(cbufferType->getElementType()); + m_writer->emit(" >"); + return; + } else if (auto structuredBufferType = as<IRHLSLStructuredBufferTypeBase>(type)) { switch (structuredBufferType->getOp()) diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 010b4bc92..326fc702d 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -642,6 +642,7 @@ Result linkAndOptimizeIR( // { CollectEntryPointUniformParamsOptions passOptions; + passOptions.targetReq = targetRequest; switch (target) { case CodeGenTarget::HostCPPSource: diff --git a/source/slang/slang-ir-collect-global-uniforms.cpp b/source/slang/slang-ir-collect-global-uniforms.cpp index cd03a61ef..1c833a294 100644 --- a/source/slang/slang-ir-collect-global-uniforms.cpp +++ b/source/slang/slang-ir-collect-global-uniforms.cpp @@ -155,7 +155,9 @@ struct CollectGlobalUniformParametersContext IRType* wrapperParamType = wrapperStructType; if (globalParameterGroupTypeLayout) { - auto wrapperParamGroupType = builder->getConstantBufferType(wrapperStructType); + auto wrapperParamGroupType = builder->getConstantBufferType( + wrapperStructType, + builder->getType(kIROp_DefaultBufferLayoutType)); wrapperParamType = wrapperParamGroupType; } diff --git a/source/slang/slang-ir-entry-point-uniforms.cpp b/source/slang/slang-ir-entry-point-uniforms.cpp index 0dfdc2d8e..b3073a97d 100644 --- a/source/slang/slang-ir-entry-point-uniforms.cpp +++ b/source/slang/slang-ir-entry-point-uniforms.cpp @@ -403,7 +403,16 @@ struct CollectEntryPointUniformParams : PerEntryPointPass // If we need a constant buffer, then the global // shader parameter will be a `ConstantBuffer<paramStructType>` // - auto constantBufferType = builder.getConstantBufferType(paramStructType); + IRType* layoutType = nullptr; + + if (m_options.targetReq->getOptionSet().getBoolOption( + CompilerOptionName::GLSLForceScalarLayout)) + layoutType = builder.getType(kIROp_ScalarBufferLayoutType); + else if (isKhronosTarget(m_options.targetReq)) + layoutType = builder.getType(kIROp_Std430BufferLayoutType); + else + layoutType = builder.getType(kIROp_DefaultBufferLayoutType); + auto constantBufferType = builder.getConstantBufferType(paramStructType, layoutType); collectedParam = builder.createParam(constantBufferType); } else diff --git a/source/slang/slang-ir-entry-point-uniforms.h b/source/slang/slang-ir-entry-point-uniforms.h index 80bc0a781..21cee3c4e 100644 --- a/source/slang/slang-ir-entry-point-uniforms.h +++ b/source/slang/slang-ir-entry-point-uniforms.h @@ -12,6 +12,7 @@ struct CollectEntryPointUniformParamsOptions // TODO(JS): Not sure if it makes sense to initialize to true or false. Go with false as // seems to fit usage. bool alwaysCreateCollectedParam = false; + TargetRequest* targetReq = nullptr; }; /// Collect entry point uniform parameters into a wrapper `struct` and/or buffer diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 97989e9ce..fb06863d4 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -3719,7 +3719,7 @@ public: return getFuncType(paramTypes.getCount(), paramTypes.getBuffer(), resultType); } - IRConstantBufferType* getConstantBufferType(IRType* elementType); + IRConstantBufferType* getConstantBufferType(IRType* elementType, IRType* layout); IRGLSLOutputParameterGroupType* getGLSLOutputParameterGroupType(IRType* valueType); diff --git a/source/slang/slang-ir-legalize-types.cpp b/source/slang/slang-ir-legalize-types.cpp index 2af3c4c09..9154277f5 100644 --- a/source/slang/slang-ir-legalize-types.cpp +++ b/source/slang/slang-ir-legalize-types.cpp @@ -4016,12 +4016,15 @@ struct IRResourceTypeLegalizationContext : IRTypeLegalizationContext bool isSimpleType(IRType*) override { return false; } - LegalType createLegalUniformBufferType(IROp op, LegalType legalElementType) override + LegalType createLegalUniformBufferType( + IROp op, + LegalType legalElementType, + IRInst* layoutOperand) override { // The appropriate strategy for legalizing uniform buffers // with resources inside already exists, so we can delegate to it. // - return createLegalUniformBufferTypeForResources(this, op, legalElementType); + return createLegalUniformBufferTypeForResources(this, op, legalElementType, layoutOperand); } }; @@ -4045,7 +4048,10 @@ struct IRExistentialTypeLegalizationContext : IRTypeLegalizationContext bool isSimpleType(IRType*) override { return false; } - LegalType createLegalUniformBufferType(IROp op, LegalType legalElementType) override + LegalType createLegalUniformBufferType( + IROp op, + LegalType legalElementType, + IRInst* layoutOperand) override { // We'll delegate the logic for creating uniform buffers // over a mix of ordinary and existential-box types to @@ -4054,7 +4060,11 @@ struct IRExistentialTypeLegalizationContext : IRTypeLegalizationContext // TODO: We should eventually try to refactor this code // so that related functionality is grouped together. // - return createLegalUniformBufferTypeForExistentials(this, op, legalElementType); + return createLegalUniformBufferTypeForExistentials( + this, + op, + legalElementType, + layoutOperand); } }; @@ -4090,7 +4100,10 @@ struct IREmptyTypeLegalizationContext : IRTypeLegalizationContext return false; } - LegalType createLegalUniformBufferType(IROp, LegalType) override { return LegalType(); } + LegalType createLegalUniformBufferType(IROp, LegalType, IRInst*) override + { + return LegalType(); + } }; // The main entry points that are used when transforming IR code diff --git a/source/slang/slang-ir-lower-buffer-element-type.cpp b/source/slang/slang-ir-lower-buffer-element-type.cpp index 2f8631e18..bd3e350bc 100644 --- a/source/slang/slang-ir-lower-buffer-element-type.cpp +++ b/source/slang/slang-ir-lower-buffer-element-type.cpp @@ -1376,7 +1376,25 @@ IRTypeLayoutRules* getTypeLayoutRuleForBuffer(TargetProgram* target, IRType* buf } case kIROp_ConstantBufferType: case kIROp_ParameterBlockType: - return IRTypeLayoutRules::getStd140(); + { + auto parameterGroupType = as<IRUniformParameterGroupType>(bufferType); + + auto layoutTypeOp = parameterGroupType->getDataLayout() + ? parameterGroupType->getDataLayout()->getOp() + : kIROp_DefaultBufferLayoutType; + switch (layoutTypeOp) + { + case kIROp_DefaultBufferLayoutType: + return IRTypeLayoutRules::getStd140(); + case kIROp_Std140BufferLayoutType: + return IRTypeLayoutRules::getStd140(); + case kIROp_Std430BufferLayoutType: + return IRTypeLayoutRules::getStd430(); + case kIROp_ScalarBufferLayoutType: + return IRTypeLayoutRules::getNatural(); + } + return IRTypeLayoutRules::getStd140(); + } case kIROp_PtrType: return IRTypeLayoutRules::getNatural(); } diff --git a/source/slang/slang-ir-optix-entry-point-uniforms.cpp b/source/slang/slang-ir-optix-entry-point-uniforms.cpp index f29cbe222..dfa07ca67 100644 --- a/source/slang/slang-ir-optix-entry-point-uniforms.cpp +++ b/source/slang/slang-ir-optix-entry-point-uniforms.cpp @@ -253,7 +253,9 @@ struct CollectOptixEntryPointUniformParams : PerEntryPointPass // TODO: reconcile this with OptiX, as the current logic works, but is still focused on // VK/DXR.. // - auto constantBufferType = builder.getConstantBufferType(paramStructType); + auto constantBufferType = builder.getConstantBufferType( + paramStructType, + builder.getType(kIROp_DefaultBufferLayoutType)); collectedParam = builder.createParam(constantBufferType); // The global shader parameter should have the layout diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index e7f82f5ad..f6c662a98 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -3046,10 +3046,10 @@ IRWitnessTableIDType* IRBuilder::getWitnessTableIDType(IRType* baseType) createIntrinsicInst(nullptr, kIROp_WitnessTableIDType, 1, (IRInst* const*)&baseType); } -IRConstantBufferType* IRBuilder::getConstantBufferType(IRType* elementType) +IRConstantBufferType* IRBuilder::getConstantBufferType(IRType* elementType, IRType* layoutType) { - IRInst* operands[] = {elementType}; - return (IRConstantBufferType*)getType(kIROp_ConstantBufferType, 1, operands); + IRInst* operands[] = {elementType, layoutType}; + return (IRConstantBufferType*)getType(kIROp_ConstantBufferType, 2, operands); } IRGLSLOutputParameterGroupType* IRBuilder::getGLSLOutputParameterGroupType(IRType* elementType) diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h index 05a6fa55c..d24c2d12b 100644 --- a/source/slang/slang-ir.h +++ b/source/slang/slang-ir.h @@ -1574,7 +1574,14 @@ SIMPLE_IR_TYPE(MetalMeshGridPropertiesType, Type) SIMPLE_IR_TYPE(GLSLInputAttachmentType, Type) SIMPLE_IR_PARENT_TYPE(ParameterGroupType, PointerLikeType) -SIMPLE_IR_PARENT_TYPE(UniformParameterGroupType, ParameterGroupType) + +struct IRUniformParameterGroupType : IRParameterGroupType +{ + IR_PARENT_ISA(UniformParameterGroupType) + + IRType* getDataLayout() { return getOperandCount() > 1 ? (IRType*)getOperand(1) : nullptr; } +}; + SIMPLE_IR_PARENT_TYPE(VaryingParameterGroupType, ParameterGroupType) SIMPLE_IR_TYPE(ConstantBufferType, UniformParameterGroupType) SIMPLE_IR_TYPE(TextureBufferType, UniformParameterGroupType) diff --git a/source/slang/slang-legalize-types.cpp b/source/slang/slang-legalize-types.cpp index 6d827a412..7695ba385 100644 --- a/source/slang/slang-legalize-types.cpp +++ b/source/slang/slang-legalize-types.cpp @@ -527,12 +527,25 @@ static IRType* createBuiltinGenericType( return context->getBuilder()->getType(op, 1, operands); } +static IRType* createBuiltinGenericType( + TypeLegalizationContext* context, + IROp op, + IRType* elementType, + IRInst* layoutOperand) +{ + if (!layoutOperand) + return createBuiltinGenericType(context, op, elementType); + IRInst* operands[] = {elementType, layoutOperand}; + return context->getBuilder()->getType(op, 2, operands); +} + // Create a uniform buffer type with a given legalized // element type. static LegalType createLegalUniformBufferType( TypeLegalizationContext* context, IROp op, - LegalType legalElementType) + LegalType legalElementType, + IRInst* layoutOperand) { // We will handle some of the easy/non-interesting // cases here in the main routine, but for all @@ -543,7 +556,7 @@ static LegalType createLegalUniformBufferType( switch (legalElementType.flavor) { default: - return context->createLegalUniformBufferType(op, legalElementType); + return context->createLegalUniformBufferType(op, legalElementType, layoutOperand); case LegalType::Flavor::none: return LegalType(); @@ -558,7 +571,7 @@ static LegalType createLegalUniformBufferType( // an unlikely case in practice. // return LegalType::simple( - createBuiltinGenericType(context, op, legalElementType.getSimple())); + createBuiltinGenericType(context, op, legalElementType.getSimple(), layoutOperand)); } break; @@ -581,7 +594,8 @@ static LegalType createLegalUniformBufferType( return LegalType::implicitDeref(createLegalUniformBufferType( context, op, - legalElementType.getImplicitDeref()->valueType)); + legalElementType.getImplicitDeref()->valueType, + layoutOperand)); } break; } @@ -593,7 +607,8 @@ static LegalType createLegalUniformBufferType( LegalType createLegalUniformBufferTypeForResources( TypeLegalizationContext* context, IROp op, - LegalType legalElementType) + LegalType legalElementType, + IRInst* layoutOperand) { switch (legalElementType.flavor) { @@ -627,7 +642,8 @@ LegalType createLegalUniformBufferTypeForResources( // buffer with the appropriate `op`, so that case // is easy: // - auto ordinaryType = createLegalUniformBufferType(context, op, pairType->ordinaryType); + auto ordinaryType = + createLegalUniformBufferType(context, op, pairType->ordinaryType, layoutOperand); // For the special side, we really just want to turn // a special field of type `R` into a value of type @@ -824,7 +840,8 @@ LegalElementWrapping declareStructFields( LegalType createLegalUniformBufferTypeForExistentials( TypeLegalizationContext* context, IROp op, - LegalType legalElementType) + LegalType legalElementType, + IRInst* layoutOperand) { auto builder = context->getBuilder(); @@ -840,7 +857,7 @@ LegalType createLegalUniformBufferTypeForExistentials( // (not a `LegalType`) we can go ahead and create an // IR uniform buffer type that wraps it. // - auto bufferType = createBuiltinGenericType(context, op, structType); + auto bufferType = createBuiltinGenericType(context, op, structType, layoutOperand); // The `elementWrapping` computed when we declared all // the `struct` fields tells us how to get from the @@ -859,7 +876,11 @@ static LegalType createLegalUniformBufferType( IRUniformParameterGroupType* uniformBufferType, LegalType legalElementType) { - return createLegalUniformBufferType(context, uniformBufferType->getOp(), legalElementType); + return createLegalUniformBufferType( + context, + uniformBufferType->getOp(), + legalElementType, + uniformBufferType->getDataLayout()); } // Create a pointer type with a given legalized value type. @@ -1141,7 +1162,8 @@ LegalType legalizeTypeImpl(TypeLegalizationContext* context, IRType* type) // return context->createLegalUniformBufferType( uniformBufferType->getOp(), - legalElementType); + legalElementType, + uniformBufferType->getDataLayout()); } } diff --git a/source/slang/slang-legalize-types.h b/source/slang/slang-legalize-types.h index f70ac7757..eaee373b2 100644 --- a/source/slang/slang-legalize-types.h +++ b/source/slang/slang-legalize-types.h @@ -654,7 +654,10 @@ struct IRTypeLegalizationContext /// This function will only be called if `legalElementType` is /// somehow non-trivial. /// - virtual LegalType createLegalUniformBufferType(IROp op, LegalType legalElementType) = 0; + virtual LegalType createLegalUniformBufferType( + IROp op, + LegalType legalElementType, + IRInst* layoutOperand) = 0; }; // This typedef exists to support pre-existing code from when @@ -675,7 +678,8 @@ ModuleDecl* findModuleForDecl(Decl* decl); LegalType createLegalUniformBufferTypeForResources( TypeLegalizationContext* context, IROp op, - LegalType legalElementType); + LegalType legalElementType, + IRInst* layoutOperand); /// Create a uniform buffer type suitable for existential legalization. /// @@ -686,7 +690,8 @@ LegalType createLegalUniformBufferTypeForResources( LegalType createLegalUniformBufferTypeForExistentials( TypeLegalizationContext* context, IROp op, - LegalType legalElementType); + LegalType legalElementType, + IRInst* layoutOperand); void legalizeExistentialTypeLayout(TargetProgram* target, IRModule* module, DiagnosticSink* sink); diff --git a/source/slang/slang-parameter-binding.cpp b/source/slang/slang-parameter-binding.cpp index 3621c6c00..e45eb4652 100644 --- a/source/slang/slang-parameter-binding.cpp +++ b/source/slang/slang-parameter-binding.cpp @@ -707,7 +707,7 @@ RefPtr<TypeLayout> getTypeLayoutForGlobalShaderParameter( // If the target doesn't support specialization constants, then we will // layout them as ordinary uniform data. specializationConstantRule = - rules->getConstantBufferRules(context->getTargetRequest()->getOptionSet()); + rules->getConstantBufferRules(context->getTargetRequest()->getOptionSet(), type); } return createTypeLayoutWith(layoutContext, specializationConstantRule, type); } @@ -718,7 +718,7 @@ RefPtr<TypeLayout> getTypeLayoutForGlobalShaderParameter( // shader parameter. return createTypeLayoutWith( layoutContext, - rules->getConstantBufferRules(context->getTargetRequest()->getOptionSet()), + rules->getConstantBufferRules(context->getTargetRequest()->getOptionSet(), type), type); } @@ -2421,11 +2421,21 @@ static RefPtr<TypeLayout> computeEntryPointParameterTypeLayout( // a uniform shader parameter passed via the implicitly-defined // constant buffer (e.g., the `$Params` constant buffer seen in fxc/dxc output). // - return createTypeLayoutWith( - context->layoutContext, - context->getRulesFamily()->getConstantBufferRules( - context->getTargetRequest()->getOptionSet()), - paramType); + LayoutRulesImpl* layoutRules = nullptr; + if (isKhronosTarget(context->getTargetRequest())) + { + // For Vulkan, entry point uniform parameters are laid out using push constant buffer + // rules (defaults to std430). + layoutRules = context->getRulesFamily()->getShaderStorageBufferRules( + context->getTargetProgram()->getOptionSet()); + } + else + { + layoutRules = context->getRulesFamily()->getConstantBufferRules( + context->getTargetRequest()->getOptionSet(), + paramType); + } + return createTypeLayoutWith(context->layoutContext, layoutRules, paramType); } else { @@ -2783,12 +2793,13 @@ static ParameterBindingAndKindInfo _allocateConstantBufferBinding(ParameterBindi UInt space = context->shared->defaultSpace; auto usedRangeSet = _getOrCreateUsedRangeSetForSpace(context, space); - auto layoutInfo = context->getRulesFamily() - ->getConstantBufferRules(context->getTargetRequest()->getOptionSet()) - ->GetObjectLayout( - ShaderParameterKind::ConstantBuffer, - context->layoutContext.objectLayoutOptions) - .getSimple(); + auto layoutInfo = + context->getRulesFamily() + ->getConstantBufferRules(context->getTargetRequest()->getOptionSet(), nullptr) + ->GetObjectLayout( + ShaderParameterKind::ConstantBuffer, + context->layoutContext.objectLayoutOptions) + .getSimple(); ParameterBindingAndKindInfo info; info.kind = layoutInfo.kind; @@ -2809,7 +2820,9 @@ static ParameterBindingAndKindInfo _assignConstantBufferBinding( auto usedRangeSet = _getOrCreateUsedRangeSetForSpace(context, space); auto layoutInfo = context->getRulesFamily() - ->getConstantBufferRules(context->getTargetRequest()->getOptionSet()) + ->getConstantBufferRules( + context->getTargetRequest()->getOptionSet(), + varLayout->typeLayout ? varLayout->typeLayout->getType() : nullptr) ->GetObjectLayout( ShaderParameterKind::ConstantBuffer, context->layoutContext.objectLayoutOptions) @@ -3786,6 +3799,7 @@ static bool _calcNeedsDefaultSpace(SharedParameterBindingContext& sharedContext) case LayoutResourceKind::RegisterSpace: case LayoutResourceKind::SubElementRegisterSpace: case LayoutResourceKind::PushConstantBuffer: + case LayoutResourceKind::SpecializationConstant: continue; case LayoutResourceKind::Uniform: { diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp index 589a170fa..9e448a5fa 100644 --- a/source/slang/slang-syntax.cpp +++ b/source/slang/slang-syntax.cpp @@ -985,6 +985,11 @@ Val* _tryLookupConcreteAssociatedTypeFromThisTypeSubst(ASTBuilder* builder, Decl return nullptr; } +Type* UniformParameterGroupType::getLayoutType() +{ + return as<Type>(getGenericArg(getDeclRef(), 1)); +} + ModuleDecl* getModuleDecl(Decl* decl) { for (auto dd = decl; dd; dd = dd->parentDecl) diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp index 62caecf72..da4cd458b 100644 --- a/source/slang/slang-type-layout.cpp +++ b/source/slang/slang-type-layout.cpp @@ -1022,7 +1022,9 @@ MetalVaryingLayoutRulesImpl kMetalVaryingOutputLayoutRulesImpl(LayoutResourceKin struct GLSLLayoutRulesFamilyImpl : LayoutRulesFamilyImpl { virtual LayoutRulesImpl* getAnyValueRules() override; - virtual LayoutRulesImpl* getConstantBufferRules(CompilerOptionSet& compilerOptions) override; + virtual LayoutRulesImpl* getConstantBufferRules( + CompilerOptionSet& compilerOptions, + Type* containerType) override; virtual LayoutRulesImpl* getPushConstantBufferRules() override; virtual LayoutRulesImpl* getTextureBufferRules(CompilerOptionSet& compilerOptions) override; virtual LayoutRulesImpl* getVaryingInputRules() override; @@ -1044,7 +1046,9 @@ struct GLSLLayoutRulesFamilyImpl : LayoutRulesFamilyImpl struct HLSLLayoutRulesFamilyImpl : LayoutRulesFamilyImpl { virtual LayoutRulesImpl* getAnyValueRules() override; - virtual LayoutRulesImpl* getConstantBufferRules(CompilerOptionSet& compilerOptions) override; + virtual LayoutRulesImpl* getConstantBufferRules( + CompilerOptionSet& compilerOptions, + Type* containerType) override; virtual LayoutRulesImpl* getPushConstantBufferRules() override; virtual LayoutRulesImpl* getTextureBufferRules(CompilerOptionSet& compilerOptions) override; virtual LayoutRulesImpl* getVaryingInputRules() override; @@ -1066,7 +1070,9 @@ struct HLSLLayoutRulesFamilyImpl : LayoutRulesFamilyImpl struct CPULayoutRulesFamilyImpl : LayoutRulesFamilyImpl { virtual LayoutRulesImpl* getAnyValueRules() override; - virtual LayoutRulesImpl* getConstantBufferRules(CompilerOptionSet& compilerOptions) override; + virtual LayoutRulesImpl* getConstantBufferRules( + CompilerOptionSet& compilerOptions, + Type* containerType) override; virtual LayoutRulesImpl* getPushConstantBufferRules() override; virtual LayoutRulesImpl* getTextureBufferRules(CompilerOptionSet& compilerOptions) override; virtual LayoutRulesImpl* getVaryingInputRules() override; @@ -1087,7 +1093,9 @@ struct CPULayoutRulesFamilyImpl : LayoutRulesFamilyImpl struct CUDALayoutRulesFamilyImpl : LayoutRulesFamilyImpl { virtual LayoutRulesImpl* getAnyValueRules() override; - virtual LayoutRulesImpl* getConstantBufferRules(CompilerOptionSet& compilerOptions) override; + virtual LayoutRulesImpl* getConstantBufferRules( + CompilerOptionSet& compilerOptions, + Type* containerType) override; virtual LayoutRulesImpl* getPushConstantBufferRules() override; virtual LayoutRulesImpl* getTextureBufferRules(CompilerOptionSet& compilerOptions) override; virtual LayoutRulesImpl* getVaryingInputRules() override; @@ -1108,7 +1116,9 @@ struct CUDALayoutRulesFamilyImpl : LayoutRulesFamilyImpl struct MetalLayoutRulesFamilyImpl : LayoutRulesFamilyImpl { virtual LayoutRulesImpl* getAnyValueRules() override; - virtual LayoutRulesImpl* getConstantBufferRules(CompilerOptionSet& compilerOptions) override; + virtual LayoutRulesImpl* getConstantBufferRules( + CompilerOptionSet& compilerOptions, + Type* containerType) override; virtual LayoutRulesImpl* getPushConstantBufferRules() override; virtual LayoutRulesImpl* getTextureBufferRules(CompilerOptionSet& compilerOptions) override; virtual LayoutRulesImpl* getVaryingInputRules() override; @@ -1129,7 +1139,9 @@ struct MetalLayoutRulesFamilyImpl : LayoutRulesFamilyImpl struct WGSLLayoutRulesFamilyImpl : LayoutRulesFamilyImpl { virtual LayoutRulesImpl* getAnyValueRules() override; - virtual LayoutRulesImpl* getConstantBufferRules(CompilerOptionSet& compilerOptions) override; + virtual LayoutRulesImpl* getConstantBufferRules( + CompilerOptionSet& compilerOptions, + Type* containerType) override; virtual LayoutRulesImpl* getPushConstantBufferRules() override; virtual LayoutRulesImpl* getTextureBufferRules(CompilerOptionSet& compilerOptions) override; virtual LayoutRulesImpl* getVaryingInputRules() override; @@ -1514,13 +1526,28 @@ LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getAnyValueRules() } LayoutRulesImpl* GLSLLayoutRulesFamilyImpl::getConstantBufferRules( - CompilerOptionSet& compilerOptions) + CompilerOptionSet& compilerOptions, + Type* containerType) { if (compilerOptions.shouldUseScalarLayout()) return &kScalarLayoutRulesImpl_; else if (compilerOptions.shouldUseDXLayout()) return &kFXCConstantBufferLayoutRulesFamilyImpl; - + if (auto cbufferType = as<ConstantBufferType>(containerType)) + { + switch (cbufferType->getLayoutType()->astNodeType) + { + case ASTNodeType::DefaultDataLayoutType: + case ASTNodeType::Std140DataLayoutType: + return &kStd140LayoutRulesImpl_; + case ASTNodeType::Std430DataLayoutType: + return &kStd430LayoutRulesImpl_; + case ASTNodeType::ScalarDataLayoutType: + return &kScalarLayoutRulesImpl_; + default: + break; + } + } return &kStd140LayoutRulesImpl_; } @@ -1615,7 +1642,7 @@ LayoutRulesImpl* HLSLLayoutRulesFamilyImpl::getAnyValueRules() return &kHLSLAnyValueLayoutRulesImpl_; } -LayoutRulesImpl* HLSLLayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptionSet&) +LayoutRulesImpl* HLSLLayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptionSet&, Type*) { return &kHLSLConstantBufferLayoutRulesImpl_; } @@ -1689,7 +1716,7 @@ LayoutRulesImpl* CPULayoutRulesFamilyImpl::getAnyValueRules() return &kCPUAnyValueLayoutRulesImpl_; } -LayoutRulesImpl* CPULayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptionSet&) +LayoutRulesImpl* CPULayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptionSet&, Type*) { return &kCPULayoutRulesImpl_; } @@ -1755,7 +1782,7 @@ LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getAnyValueRules() return &kCUDAAnyValueLayoutRulesImpl_; } -LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptionSet&) +LayoutRulesImpl* CUDALayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptionSet&, Type*) { return &kCUDALayoutRulesImpl_; } @@ -1944,7 +1971,7 @@ LayoutRulesImpl* MetalLayoutRulesFamilyImpl::getAnyValueRules() return &kHLSLAnyValueLayoutRulesImpl_; } -LayoutRulesImpl* MetalLayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptionSet&) +LayoutRulesImpl* MetalLayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptionSet&, Type*) { return &kMetalConstantBufferLayoutRulesImpl_; } @@ -2022,7 +2049,7 @@ LayoutRulesImpl* WGSLLayoutRulesFamilyImpl::getAnyValueRules() return &kGLSLAnyValueLayoutRulesImpl_; } -LayoutRulesImpl* WGSLLayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptionSet&) +LayoutRulesImpl* WGSLLayoutRulesFamilyImpl::getConstantBufferRules(CompilerOptionSet&, Type*) { return &kWGSLConstantBufferLayoutRulesImpl_; } @@ -2178,7 +2205,7 @@ TypeLayoutContext getInitialLayoutContextForTarget( if (rulesFamily) { - context.rules = rulesFamily->getConstantBufferRules(targetReq->getOptionSet()); + context.rules = rulesFamily->getConstantBufferRules(targetReq->getOptionSet(), nullptr); } return context; @@ -3438,7 +3465,9 @@ LayoutRulesImpl* getParameterBufferElementTypeLayoutRules( { if (as<ConstantBufferType>(parameterGroupType)) { - return rules->getLayoutRulesFamily()->getConstantBufferRules(compilerOptions); + return rules->getLayoutRulesFamily()->getConstantBufferRules( + compilerOptions, + parameterGroupType); } else if (as<TextureBufferType>(parameterGroupType)) { diff --git a/source/slang/slang-type-layout.h b/source/slang/slang-type-layout.h index 87d9123ff..2cdb4b386 100644 --- a/source/slang/slang-type-layout.h +++ b/source/slang/slang-type-layout.h @@ -1105,7 +1105,9 @@ struct LayoutRulesImpl struct LayoutRulesFamilyImpl { virtual LayoutRulesImpl* getAnyValueRules() = 0; - virtual LayoutRulesImpl* getConstantBufferRules(CompilerOptionSet& compilerOptions) = 0; + virtual LayoutRulesImpl* getConstantBufferRules( + CompilerOptionSet& compilerOptions, + Type* containerType) = 0; virtual LayoutRulesImpl* getPushConstantBufferRules() = 0; virtual LayoutRulesImpl* getTextureBufferRules(CompilerOptionSet& compilerOptions) = 0; virtual LayoutRulesImpl* getVaryingInputRules() = 0; diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 854d90df5..e4de61276 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -1608,7 +1608,9 @@ SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL Linkage::getContainerType( { case slang::ContainerType::ConstantBuffer: { - ConstantBufferType* cbType = getASTBuilder()->getConstantBufferType(type); + SemanticsVisitor visitor(getSemanticsForReflection()); + auto layoutType = getASTBuilder()->getDefaultLayoutType(); + Type* cbType = visitor.getConstantBufferType(type, layoutType); containerTypeReflection = cbType; } break; |
