From da5cf478c6be06c9e6c20917a7d472cbdcb624e3 Mon Sep 17 00:00:00 2001 From: Gangzheng Tong Date: Fri, 30 May 2025 17:16:59 -0700 Subject: Add check for the variable requirement (#6677) * Add check for the variable requirement This change adds the capability check for the variables requirement. With this check, the shader ``` [require(cpp_cuda_glsl_hlsl_metal_spirv)] Buffer InputTyped; [require(cpp_cuda_glsl_hlsl_metal_spirv)] RWBuffer OutputTyped; ``` will issue error if targeting to WSGL e.g. `.\build\Debug\bin\slangc .\tests\wgsl_no_buffer.slang -o wgsl_no_buffer.txt -target wgsl -entry Main -stage compute` .\tests\wgsl_no_buffer.slang(2): error 36108: 'InputTyped' has dependencies that are not compatible on the required target 'wgsl'. Buffer InputTyped; ^~~~~~~~~~ .\tests\wgsl_no_buffer.slang(4): error 36108: 'OutputTyped' has dependencies that are not compatible on the required target 'wgsl'. RWBuffer OutputTyped; ^~~~~~~~~~~ Fixes #6304 * Add var capability tests * Do capability checks for global var only * Add inferredCapabilityRequirements to var capability check * Add requirement to the intrinsic types Buffer/RWBuffer * format code * Update capabliity test * use DefaultDataLayout as default data layout * Use visitMemberExpr to check the capabilities * Update the cap tests to match the error messages * update test to use the ScalarDataLayout for hlsl target * Update tests check condition to use error number only * Add default push_constant data layout type --------- Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> --- source/slang/slang-check-decl.cpp | 45 ++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'source/slang/slang-check-decl.cpp') diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index cc65edd2f..081ccbb0b 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -720,6 +720,13 @@ struct SemanticsDeclReferenceVisitor : public SemanticsDeclVisitorBase, // Pass down the callee location processDeclModifiers(expr->declRef.getDecl(), expr->loc); } + + void visitMemberExpr(MemberExpr* expr) + { + dispatchIfNotNull(expr->baseExpression); + visitDeclRefExpr(expr); + } + void visitStaticMemberExpr(StaticMemberExpr* expr) { dispatchIfNotNull(expr->declRef.declRefBase); @@ -2009,7 +2016,7 @@ void SemanticsDeclHeaderVisitor::checkPushConstantBufferType(VarDeclBase* varDec { varDecl->type.type = getConstantBufferType( cbufferType->getElementType(), - m_astBuilder->getStd430LayoutType()); + m_astBuilder->getDefaultPushConstantLayoutType()); } } else if (isGlobalShaderParameter(varDecl)) @@ -2017,8 +2024,9 @@ void SemanticsDeclHeaderVisitor::checkPushConstantBufferType(VarDeclBase* varDec // 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()); + varDecl->type.type = getConstantBufferType( + varDecl->type, + m_astBuilder->getDefaultPushConstantLayoutType()); } } } @@ -13660,8 +13668,12 @@ CapabilitySet SemanticsDeclCapabilityVisitor::getDeclaredCapabilitySet(Decl* dec // For every existing target, we want to join their requirements together. // If the the parent defines additional targets, we want to add them to the disjunction set. // For example: - // [require(glsl)] struct Parent { [require(glsl, glsl_ext_1)] [require(spirv)] void - // foo(); } + // [require(glsl)] + // struct Parent { + // [require(glsl, glsl_ext_1)] + // [require(spirv)] + // void foo(); + // } // The requirement for `foo` should be glsl+glsl_ext_1 | spirv. // CapabilitySet declaredCaps; @@ -14197,19 +14209,18 @@ void SemanticsDeclCapabilityVisitor::diagnoseUndeclaredCapability( } } - //// The second scenario is when the callee is using a capability that is not provided by - /// the - /// requirement. / For example: / [require(hlsl,b,c)] / void caller() / { / - /// useD(); - ///// require capability (hlsl,d) / } / In this case we should report that useD() is - /// using a - /// capability that is not declared by caller. - //// - - //// If we reach here, we are case 2. + // The second scenario is when the callee is using a capability that is not provided by the + // requirement. For example: + // [require(hlsl,b,c)] + // void caller() + // { + // useD(); // requires capability (hlsl,d) + // } + // In this case we should report that useD() is using a capability that is not declared by + // caller. If we reach here, we are case 2. We will produce all failed atoms. This is important + // since provenance of multiple atoms can come from multiple referenced items in a function + // body. - // We will produce all failed atoms. This is important since provenance of multiple atoms - // can come from multiple referenced items in a function body. HashSet printedDecls; auto simplifiedFailedAtomsSet = failedAtomsInsideAvailableSet.newSetWithoutImpliedAtoms(); for (auto i : simplifiedFailedAtomsSet) -- cgit v1.2.3