diff --git a/include/dxc/Support/HLSLOptions.td b/include/dxc/Support/HLSLOptions.td index cd7dfb2f0c..85b64ffe55 100644 --- a/include/dxc/Support/HLSLOptions.td +++ b/include/dxc/Support/HLSLOptions.td @@ -601,3 +601,6 @@ def rw_decl_global_cb : Flag<["-", "/"], "decl-global-cb">, Group; // Also removed: compress, decompress, /Gch (child effect), /Gpp (partial precision) // /Op - no support for preshaders. + +def fvk_disable_hlsl_intrinsics : Flag<["-"], "fvk-disable-hlsl-intrinsics">, Group, Flags<[CoreOption, DriverOption]>, + HelpText<"Disable HLSL intrinsics">; diff --git a/include/dxc/Support/SPIRVOptions.h b/include/dxc/Support/SPIRVOptions.h index 352cf6c2ec..bd9a19b94f 100644 --- a/include/dxc/Support/SPIRVOptions.h +++ b/include/dxc/Support/SPIRVOptions.h @@ -38,6 +38,7 @@ enum class SpirvLayoutRule { }; struct SpirvCodeGenOptions { + bool disableHLSLIntrinsics; /// Disable legalization and optimization and emit raw SPIR-V bool codeGenHighLevel; bool debugInfoFile; diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index 0c9330b1d1..a214dba7e6 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -1074,6 +1074,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude, // SPIRV Change Starts #ifdef ENABLE_SPIRV_CODEGEN + opts.SpirvOptions.disableHLSLIntrinsics = + Args.hasFlag(OPT_fvk_disable_hlsl_intrinsics, OPT_INVALID, false); opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false); opts.SpirvOptions.invertY = Args.hasFlag(OPT_fvk_invert_y, OPT_INVALID, false); diff --git a/tools/clang/include/clang/AST/ASTContext.h b/tools/clang/include/clang/AST/ASTContext.h index ab0e33513b..59403fa73f 100644 --- a/tools/clang/include/clang/AST/ASTContext.h +++ b/tools/clang/include/clang/AST/ASTContext.h @@ -2408,7 +2408,7 @@ class ASTContext : public RefCountedBase { /// It is normally invoked after ASTContext construction. /// /// \param Target The target - void InitBuiltinTypes(const TargetInfo &Target); + void InitBuiltinTypes(const TargetInfo &Target, bool ignoreHLSLIntrinsics); private: void InitBuiltinType(CanQualType &R, BuiltinType::Kind K); diff --git a/tools/clang/include/clang/AST/HlslTypes.h b/tools/clang/include/clang/AST/HlslTypes.h index 43c1effdb8..d9b2ca35de 100644 --- a/tools/clang/include/clang/AST/HlslTypes.h +++ b/tools/clang/include/clang/AST/HlslTypes.h @@ -51,7 +51,8 @@ namespace hlsl { /// Initializes the specified context to support HLSL /// compilation. -void InitializeASTContextForHLSL(clang::ASTContext &context); +void InitializeASTContextForHLSL(clang::ASTContext &context, + bool ignoreHLSLIntrinsics); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Type system enumerations. diff --git a/tools/clang/include/clang/Frontend/CompilerInstance.h b/tools/clang/include/clang/Frontend/CompilerInstance.h index 3c8270f9a0..ac087458f3 100644 --- a/tools/clang/include/clang/Frontend/CompilerInstance.h +++ b/tools/clang/include/clang/Frontend/CompilerInstance.h @@ -669,7 +669,7 @@ class CompilerInstance : public ModuleLoader { std::string getSpecificModuleCachePath(); /// Create the AST context. - void createASTContext(); + void createASTContext(bool ignoreHLSLIntrinsics = false); /// Create an external AST source to read a PCH file and attach it to the AST /// context. diff --git a/tools/clang/include/clang/Frontend/FrontendAction.h b/tools/clang/include/clang/Frontend/FrontendAction.h index c407ff80ac..83e065de6d 100644 --- a/tools/clang/include/clang/Frontend/FrontendAction.h +++ b/tools/clang/include/clang/Frontend/FrontendAction.h @@ -208,7 +208,8 @@ class FrontendAction { /// /// \return True on success; on failure the compilation of this file should /// be aborted and neither Execute() nor EndSourceFile() should be called. - bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input); + bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input, + bool ignoreHLSLIntrinsics = false); /// \brief Set the source manager's main input file, and run the action. bool Execute(); diff --git a/tools/clang/lib/AST/ASTContext.cpp b/tools/clang/lib/AST/ASTContext.cpp index 2445a421fe..e2c50027d9 100644 --- a/tools/clang/lib/AST/ASTContext.cpp +++ b/tools/clang/lib/AST/ASTContext.cpp @@ -958,7 +958,7 @@ void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) { Types.push_back(Ty); } -void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { +void ASTContext::InitBuiltinTypes(const TargetInfo &Target, bool ignoreHLSLIntrinsics) { assert((!this->Target || this->Target == &Target) && "Incorrect target reinitialization"); assert(VoidTy.isNull() && "Context reinitialized?"); @@ -1108,7 +1108,7 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { HLSLStringTy = this->getPointerType(CharTy); - hlsl::InitializeASTContextForHLSL(*this); // Previously in constructor, guarded by !DelayInitialization + hlsl::InitializeASTContextForHLSL(*this, ignoreHLSLIntrinsics); // Previously in constructor, guarded by !DelayInitialization } // HLSL Change Ends } diff --git a/tools/clang/lib/Frontend/CompilerInstance.cpp b/tools/clang/lib/Frontend/CompilerInstance.cpp index c39ff51b1d..f26b157a45 100644 --- a/tools/clang/lib/Frontend/CompilerInstance.cpp +++ b/tools/clang/lib/Frontend/CompilerInstance.cpp @@ -409,12 +409,12 @@ std::string CompilerInstance::getSpecificModuleCachePath() { // ASTContext -void CompilerInstance::createASTContext() { +void CompilerInstance::createASTContext(bool ignoreHLSLIntrinsics) { Preprocessor &PP = getPreprocessor(); Context = new ASTContext(getLangOpts(), PP.getSourceManager(), PP.getIdentifierTable(), PP.getSelectorTable(), PP.getBuiltinInfo()); - Context->InitBuiltinTypes(getTarget()); + Context->InitBuiltinTypes(getTarget(), ignoreHLSLIntrinsics); } // ExternalASTSource diff --git a/tools/clang/lib/Frontend/FrontendAction.cpp b/tools/clang/lib/Frontend/FrontendAction.cpp index 54ce6f154b..ae2589f07d 100644 --- a/tools/clang/lib/Frontend/FrontendAction.cpp +++ b/tools/clang/lib/Frontend/FrontendAction.cpp @@ -173,7 +173,8 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, } bool FrontendAction::BeginSourceFile(CompilerInstance &CI, - const FrontendInputFile &Input) { + const FrontendInputFile &Input, + bool ignoreHLSLIntrinsics) { assert(!Instance && "Already processing a source file!"); assert(!Input.isEmpty() && "Unexpected empty filename!"); setCurrentInput(Input); @@ -323,7 +324,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (!usesPreprocessorOnly()) { // Parsing a model file should reuse the existing ASTContext. if (!isModelParsingAction()) - CI.createASTContext(); + CI.createASTContext(ignoreHLSLIntrinsics); std::unique_ptr Consumer = CreateWrappedASTConsumer(CI, InputFile); diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index e9c8c90a2d..c5c3542642 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -2994,6 +2994,9 @@ static TypedefDecl *CreateGlobalTypedef(ASTContext *context, const char *ident, class HLSLExternalSource : public ExternalSemaSource { private: + + const bool m_disableHLSLIntrinsics; + // Inner types. struct FindStructBasicTypeResult { ArBasicKind Kind; // Kind of struct (eg, AR_OBJECT_TEXTURE2D) @@ -4113,13 +4116,14 @@ class HLSLExternalSource : public ExternalSemaSource { } public: - HLSLExternalSource() + HLSLExternalSource(bool disableHLSLIntrinsics) : m_matrixTemplateDecl(nullptr), m_vectorTemplateDecl(nullptr), m_vkIntegralConstantTemplateDecl(nullptr), m_vkLiteralTemplateDecl(nullptr), m_vkBufferPointerTemplateDecl(nullptr), m_hlslNSDecl(nullptr), m_vkNSDecl(nullptr), m_dxNSDecl(nullptr), m_context(nullptr), - m_sema(nullptr), m_hlslStringTypedef(nullptr) { + m_sema(nullptr), m_hlslStringTypedef(nullptr), + m_disableHLSLIntrinsics(disableHLSLIntrinsics) { memset(m_matrixTypes, 0, sizeof(m_matrixTypes)); memset(m_matrixShorthandTypes, 0, sizeof(m_matrixShorthandTypes)); memset(m_vectorTypes, 0, sizeof(m_vectorTypes)); @@ -5131,12 +5135,118 @@ class HLSLExternalSource : public ExternalSemaSource { bool IsValidObjectElement(LPCSTR tableName, IntrinsicOp op, QualType objectElement); + bool checkIfIntrinsicIsAllowed(StringRef intrinsicNameIdentifier) + { + if (!m_disableHLSLIntrinsics) + return true; + + static const std::unordered_set allowedHLSLIntrinsics = { + "Abort", + "AcceptHitAndEndSearch", + "AllocateRayQuery", + "CallShader", + "CommitNonOpaqueTriangleHit", + "CommitProceduralPrimitiveHit", + "CommittedGeometryIndex", + "CommittedInstanceContributionToHitGroupIndex", + "CommittedInstanceID", + "CommittedInstanceIndex", + "CommittedObjectRayDirection", + "CommittedObjectRayOrigin", + "CommittedObjectToWorld3x4", + "CommittedObjectToWorld4x3", + "CommittedPrimitiveIndex", + "CommittedRayT", + "CommittedStatus", + "CommittedTriangleBarycentrics", + "CommittedTriangleFrontFace", + "CommittedWorldToObject3x4", + "CommittedWorldToObject4x3", + "CandidateGeometryIndex", + "CandidateInstanceContributionToHitGroupIndex", + "CandidateInstanceID", + "CandidateInstanceIndex", + "CandidateObjectRayDirection", + "CandidateObjectRayOrigin", + "CandidateObjectToWorld3x4", + "CandidateObjectToWorld4x3", + "CandidatePrimitiveIndex", + "CandidateProceduralPrimitiveNonOpaque", + "CandidateTriangleBarycentrics", + "CandidateTriangleFrontFace", + "CandidateTriangleRayT", + "CandidateType", + "CandidateWorldToObject3x4", + "CandidateWorldToObject4x3", + "DispatchRaysDimensions", + "DispatchRaysIndex", + "FromRayQuery", + "GeometryIndex", + "GetGeometryIndex", + "GetHitKind", + "GetInstanceID", + "GetInstanceIndex", + "GetObjectRayDirection", + "GetObjectRayOrigin", + "GetObjectToWorld3x4", + "GetObjectToWorld4x3", + "GetPrimitiveIndex", + "GetRayFlags", + "GetRayTCurrent", + "GetRayTMin", + "GetShaderTableIndex", + "GetWorldRayDirection", + "GetWorldRayOrigin", + "GetWorldToObject3x4", + "GetWorldToObject4x3", + "HitKind", + "IgnoreHit", + "InstanceID", + "InstanceIndex", + "Invoke", + "IsHit", + "IsMiss", + "IsNop", + "LoadLocalRootTableConstant", + "MakeMiss", + "MakeNop", + "MaybeReorderThread", + "ObjectRayDirection", + "ObjectRayOrigin", + "ObjectToWorld", + "ObjectToWorld3x4", + "ObjectToWorld4x3", + "PrimitiveIndex", + "Proceed", + "RayFlags", + "RayTCurrent", + "RayTMin", + "ReportHit", + "TraceRay", + "TraceRayInline", + "WorldRayDirection", + "WorldRayOrigin" + }; + + auto it = allowedHLSLIntrinsics.find(std::string(intrinsicNameIdentifier)); + return it != allowedHLSLIntrinsics.end(); + } + // Returns the iterator with the first entry that matches the requirement IntrinsicDefIter FindIntrinsicByNameAndArgCount(const HLSL_INTRINSIC *table, size_t tableSize, StringRef typeName, StringRef nameIdentifier, size_t argumentCount) { + // TODO: only check if the flag "devsh-disable-hlsl-intrinsics" is enabled + if (!checkIfIntrinsicIsAllowed(nameIdentifier)) + { + return IntrinsicDefIter::CreateStart( + table, tableSize, table + tableSize, + IntrinsicTableDefIter::CreateStart(m_intrinsicTables, typeName, + nameIdentifier, argumentCount)); + } + // This is implemented by a linear scan for now. // We tested binary search on tables, and there was no performance gain on // samples probably for the following reasons. @@ -13452,8 +13562,8 @@ hlsl::TrySubscriptIndexInitialization(clang::Sema *self, clang::Expr *SrcExpr, /// Performs HLSL-specific initialization on the specified /// context. -void hlsl::InitializeASTContextForHLSL(ASTContext &context) { - HLSLExternalSource *hlslSource = new HLSLExternalSource(); +void hlsl::InitializeASTContextForHLSL(ASTContext &context, bool ignoreHLSLIntrinsics) { + HLSLExternalSource *hlslSource = new HLSLExternalSource(ignoreHLSLIntrinsics); IntrusiveRefCntPtr externalSource(hlslSource); if (hlslSource->Initialize(context)) { context.setExternalSource(externalSource); diff --git a/tools/clang/tools/dxcompiler/dxcompilerobj.cpp b/tools/clang/tools/dxcompiler/dxcompilerobj.cpp index 133e40c5bd..11f68f28b8 100644 --- a/tools/clang/tools/dxcompiler/dxcompilerobj.cpp +++ b/tools/clang/tools/dxcompiler/dxcompilerobj.cpp @@ -9,6 +9,8 @@ // // /////////////////////////////////////////////////////////////////////////////// +#include "clang/Sema/SemaHLSL.h" + #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" @@ -964,7 +966,8 @@ class DxcCompiler : public IDxcCompiler3, compiler.getCodeGenOpts().SpirvOptions = opts.SpirvOptions; clang::EmitSpirvAction action; FrontendInputFile file(pUtf8SourceName, IK_HLSL); - action.BeginSourceFile(compiler, file); + action.BeginSourceFile( + compiler, file, opts.SpirvOptions.disableHLSLIntrinsics); action.Execute(); action.EndSourceFile(); outStream.flush();