Merged PR 74: Add -exports export1[[,export2,...]=internal][;...] for lib target

Add -exports export1[[,export2,...]=internal][;...] for lib target

- Remove IDxcLinker::LinkWithExports, use -exports option instead
- Added renaming/cloning support to linker
- Added validation and tests
- Fix AV in DxilPreparePasses when patch constant function is shared

ID3D12LibraryReflection:
- Fix shader input type for typed buffer and dimension for tbuffer
- Deterministic function order by name
This commit is contained in:
Tex Riddell 2018-05-23 06:48:01 +00:00
Родитель e835567cd2
Коммит 8db08cb21e
28 изменённых файлов: 1643 добавлений и 172 удалений

Просмотреть файл

@ -0,0 +1,107 @@
///////////////////////////////////////////////////////////////////////////////
// //
// DxilExportMap.h //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
// dxilutil::ExportMap for handling -exports option. //
// //
///////////////////////////////////////////////////////////////////////////////
// TODO: Refactor to separate name export verification part from
// llvm/Function part so first part may be have shared use without llvm
#pragma once
#include <vector>
#include <set>
#include <unordered_set>
#include <string>
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DenseMap.h"
namespace llvm {
class Function;
class raw_ostream;
}
namespace hlsl {
namespace dxilutil {
class ExportMap {
public:
typedef std::unordered_set<std::string> StringStore;
typedef std::set<llvm::StringRef> NameSet;
typedef llvm::DenseMap< llvm::Function*, NameSet > RenameMap;
typedef llvm::StringMap< llvm::StringSet<> > ExportMapByString;
typedef ExportMapByString::iterator iterator;
typedef ExportMapByString::const_iterator const_iterator;
ExportMap() {}
void clear();
bool empty() const;
// Iterate export map by string name
iterator begin() { return m_ExportMap.begin(); }
const_iterator begin() const { return m_ExportMap.begin(); }
iterator end() { return m_ExportMap.end(); }
const_iterator end() const { return m_ExportMap.end(); }
// Initialize export map from option strings
bool ParseExports(const std::vector<std::string> &exportOpts, llvm::raw_ostream &errors);
// Add one export to the export map
void Add(llvm::StringRef exportName, llvm::StringRef internalName = llvm::StringRef());
// Return true if export is present, or m_ExportMap is empty
bool IsExported(llvm::StringRef original) const;
// Retrieve export entry by name. If Name is mangled, it will fallback to
// search for unmangled version if exact match fails.
// If result == end(), no matching export was found.
ExportMapByString::const_iterator GetExportsByName(llvm::StringRef Name) const;
// Call before processing functions for renaming and cloning validation
void BeginProcessing();
// Called for each function to be processed
// In order to avoid intermediate name collisions during renaming,
// if collisionAvoidanceRenaming is true:
// non-exported functions will be renamed internal.<name>
// functions exported with a different name will be renamed temp.<name>
// returns true if function is exported
bool ProcessFunction(llvm::Function *F, bool collisionAvoidanceRenaming);
// Add function to exports without checking export map or renaming
// (useful for patch constant functions used by exported HS)
void RegisterExportedFunction(llvm::Function *F);
// Called to mark an internal name as used (remove from unused set)
void UseExport(llvm::StringRef internalName);
// Called to add an exported (full) name (for collision detection)
void ExportName(llvm::StringRef exportName);
// Called after functions are processed.
// Returns true if no name collisions or unused exports are present.
bool EndProcessing() const;
const NameSet& GetNameCollisions() const { return m_NameCollisions; }
const NameSet& GetUnusedExports() const { return m_UnusedExports; }
// GetRenames gets the map of mangled renames by function pointer
const RenameMap &GetFunctionRenames() const { return m_RenameMap; }
private:
// {"internalname": ("export1", "export2", ...), ...}
ExportMapByString m_ExportMap;
StringStore m_StringStorage;
llvm::StringRef StoreString(llvm::StringRef str);
// Renaming/Validation state
RenameMap m_RenameMap;
NameSet m_ExportNames;
NameSet m_NameCollisions;
NameSet m_UnusedExports;
};
}
}

Просмотреть файл

@ -17,6 +17,7 @@
#include "llvm/ADT/StringMap.h"
#include <memory>
#include "llvm/Support/ErrorOr.h"
#include "dxc/HLSL/DxilExportMap.h"
namespace llvm {
class Function;
@ -45,8 +46,7 @@ public:
virtual void DetachAll() = 0;
virtual std::unique_ptr<llvm::Module>
Link(llvm::StringRef entry, llvm::StringRef profile,
llvm::StringMap<llvm::StringRef> &exportMap) = 0;
Link(llvm::StringRef entry, llvm::StringRef profile, dxilutil::ExportMap &exportMap) = 0;
protected:
DxilLinker(llvm::LLVMContext &Ctx, unsigned valMajor, unsigned valMinor) : m_ctx(Ctx), m_valMajor(valMajor), m_valMinor(valMinor) {}

Просмотреть файл

@ -11,6 +11,9 @@
#pragma once
#include <unordered_set>
#include <string>
#include <memory>
#include "llvm/ADT/StringRef.h"
namespace llvm {
class Type;
@ -23,7 +26,7 @@ class DiagnosticInfo;
class Value;
class Instruction;
class BasicBlock;
class StringRef;
class raw_ostream;
}
namespace hlsl {
@ -32,6 +35,9 @@ class DxilFieldAnnotation;
class DxilTypeSystem;
namespace dxilutil {
extern const char ManglingPrefix[];
extern const char EntryPrefix[];
unsigned
GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
llvm::Type *Ty, DxilTypeSystem &typeSys);
@ -54,6 +60,10 @@ namespace dxilutil {
void EmitResMappingError(llvm::Instruction *Res);
// Simple demangle just support case "\01?name@" pattern.
llvm::StringRef DemangleFunctionName(llvm::StringRef name);
// ReplaceFunctionName replaces the undecorated portion of originalName with undecorated newName
std::string ReplaceFunctionName(llvm::StringRef originalName, llvm::StringRef newName);
void PrintEscapedString(llvm::StringRef Name, llvm::raw_ostream &Out);
void PrintUnescapedString(llvm::StringRef Name, llvm::raw_ostream &Out);
// Change select/phi on operands into select/phi on operation.
// phi0 = phi a0, b0, c0
// phi1 = phi a1, b1, c1
@ -78,4 +88,4 @@ namespace dxilutil {
void PrintDiagnosticHandler(const llvm::DiagnosticInfo &DI, void *Context);
}
}
}

Просмотреть файл

@ -109,6 +109,7 @@ public:
llvm::StringRef VerifyRootSignatureSource; //OPT_verifyrootsignature
llvm::StringRef RootSignatureDefine; // OPT_rootsig_define
llvm::StringRef FloatDenormalMode; // OPT_denorm
std::vector<std::string> Exports; // OPT_exports
bool AllResourcesBound = false; // OPT_all_resources_bound
bool AstDump = false; // OPT_ast_dump

Просмотреть файл

@ -233,6 +233,7 @@ def enable_16bit_types: Flag<["-", "/"], "enable-16bit-types">, Flags<[CoreOptio
HelpText<"Enable 16bit types and disable min precision types. Available in HLSL 2018 and shader model 6.2">;
def ignore_line_directives : Flag<["-", "/"], "ignore-line-directives">, HelpText<"Ignore line directives">, Flags<[CoreOption]>, Group<hlslcomp_Group>;
def auto_binding_space : Separate<["-", "/"], "auto-binding-space">, Group<hlslcomp_Group>, Flags<[CoreOption]>, HelpText<"Set auto binding space - enables auto resource binding in libraries">;
def exports : Separate<["-", "/"], "exports">, Group<hlslcomp_Group>, Flags<[CoreOption]>, HelpText<"Specify exports when compiling a library: export1[[,export1_clone,...]=internal_name][;...]">;
// SPIRV Change Starts
def spirv : Flag<["-"], "spirv">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,

Просмотреть файл

@ -220,22 +220,6 @@ public:
_COM_Outptr_ IDxcOperationResult *
*ppResult // Linker output status, buffer, and errors
) = 0;
// Links the shader with export and produces a shader blob that the Direct3D
// runtime can use.
virtual HRESULT STDMETHODCALLTYPE LinkWithExports(
_In_opt_ LPCWSTR pEntryName, // Entry point name
_In_ LPCWSTR pTargetProfile, // shader profile to link
_In_count_(libCount)
const LPCWSTR *pLibNames, // Array of library names to link
UINT32 libCount, // Number of libraries to link
_In_count_(argCount)
const LPCWSTR *pArguments, // Array of pointers to arguments
_In_ UINT32 argCount, // Number of arguments
_In_count_(exportCount) const DxcDefine *pExports, // Array of exports
_In_ UINT32 exportCount, // Number of exports
_COM_Outptr_ IDxcOperationResult *
*ppResult // Linker output status, buffer, and errors
) = 0;
};
static const UINT32 DxcValidatorFlags_Default = 0;

Просмотреть файл

@ -266,6 +266,9 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
// Set entry point to impossible name.
opts.EntryPoint = "lib.no::entry";
}
} else if (Args.getLastArg(OPT_exports)) {
errors << "library profile required when using -exports option";
return 1;
}
llvm::StringRef ver = Args.getLastArgValue(OPT_hlsl_version);
@ -351,6 +354,8 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
}
}
opts.Exports = Args.getAllArgValues(OPT_exports);
// Check options only allowed in shader model >= 6.2FPDenormalMode
unsigned Major = 0;
unsigned Minor = 0;

Просмотреть файл

@ -41,6 +41,7 @@ add_llvm_library(LLVMHLSL
DxilTargetTransformInfo.cpp
DxilTypeSystem.cpp
DxilUtil.cpp
DxilExportMap.cpp
DxilValidation.cpp
DxcOptimizer.cpp
HLMatrixLowerPass.cpp

Просмотреть файл

@ -190,10 +190,13 @@ class DxilLibraryReflection : public DxilModuleReflection, public ID3D12LibraryR
private:
DXC_MICROCOM_TM_REF_FIELDS()
typedef MapVector<StringRef, std::unique_ptr<CFunctionReflection> > FunctionMap;
// Storage, and function by name:
typedef DenseMap<StringRef, std::unique_ptr<CFunctionReflection> > FunctionMap;
typedef DenseMap<const Function*, CFunctionReflection*> FunctionsByPtr;
FunctionMap m_FunctionMap;
FunctionsByPtr m_FunctionsByPtr;
// Enable indexing into functions in deterministic order:
std::vector<CFunctionReflection*> m_FunctionVector;
void AddResourceUseToFunctions(DxilResourceBase &resource, unsigned resIndex);
void AddResourceDependencies();
@ -1223,8 +1226,8 @@ static D3D_SHADER_INPUT_TYPE ResourceToShaderInputType(DxilResourceBase *RB) {
if (R->HasCounter()) return D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER;
return D3D_SIT_UAV_RWSTRUCTURED;
}
case DxilResource::Kind::TBuffer:
case DxilResource::Kind::TypedBuffer:
return isUAV ? D3D_SIT_UAV_RWTYPED : D3D_SIT_STRUCTURED;
case DxilResource::Kind::Texture1D:
case DxilResource::Kind::Texture1DArray:
case DxilResource::Kind::Texture2D:
@ -1234,7 +1237,7 @@ static D3D_SHADER_INPUT_TYPE ResourceToShaderInputType(DxilResourceBase *RB) {
case DxilResource::Kind::Texture3D:
case DxilResource::Kind::TextureCube:
case DxilResource::Kind::TextureCubeArray:
return R->IsRW() ? D3D_SIT_UAV_RWTYPED : D3D_SIT_TEXTURE;
return isUAV ? D3D_SIT_UAV_RWTYPED : D3D_SIT_TEXTURE;
case DxilResource::Kind::RTAccelerationStructure:
return (D3D_SHADER_INPUT_TYPE)D3D_SIT_RTACCELERATIONSTRUCTURE;
default:
@ -1266,6 +1269,7 @@ static D3D_SRV_DIMENSION ResourceToDimension(DxilResourceBase *RB) {
switch (RB->GetKind()) {
case DxilResource::Kind::StructuredBuffer:
case DxilResource::Kind::TypedBuffer:
case DxilResource::Kind::TBuffer:
return D3D_SRV_DIMENSION_BUFFER;
case DxilResource::Kind::Texture1D:
return D3D_SRV_DIMENSION_TEXTURE1D;
@ -2248,14 +2252,22 @@ void DxilLibraryReflection::AddResourceUseToFunctions(DxilResourceBase &resource
}
void DxilLibraryReflection::AddResourceDependencies() {
std::map<StringRef, CFunctionReflection*> orderedMap;
for (auto &F : m_pModule->functions()) {
if (F.isDeclaration())
continue;
auto &func = m_FunctionMap[F.getName().str()];
auto &func = m_FunctionMap[F.getName()];
DXASSERT(!func.get(), "otherwise duplicate named functions");
func.reset(new CFunctionReflection());
func->Initialize(this, &F);
m_FunctionsByPtr[&F] = func.get();
orderedMap[F.getName()] = func.get();
}
// Fill in function vector sorted by name
m_FunctionVector.clear();
m_FunctionVector.reserve(orderedMap.size());
for (auto &it : orderedMap) {
m_FunctionVector.push_back(it.second);
}
UINT resIndex = 0;
for (auto &resource : m_Resources) {
@ -2305,15 +2317,15 @@ HRESULT DxilLibraryReflection::GetDesc(D3D12_LIBRARY_DESC * pDesc) {
//Unset: LPCSTR Creator; // The name of the originator of the library.
//Unset: UINT Flags; // Compilation flags.
//UINT FunctionCount; // Number of functions exported from the library.
pDesc->FunctionCount = (UINT)m_FunctionMap.size();
pDesc->FunctionCount = (UINT)m_FunctionVector.size();
return S_OK;
}
_Use_decl_annotations_
ID3D12FunctionReflection *DxilLibraryReflection::GetFunctionByIndex(INT FunctionIndex) {
if (FunctionIndex >= m_FunctionMap.size())
if (FunctionIndex >= m_FunctionVector.size())
return &g_InvalidFunction;
return ((m_FunctionMap.begin() + FunctionIndex)->second).get();
return m_FunctionVector[FunctionIndex];
}
// DxilRuntimeReflection implementation

221
lib/HLSL/DxilExportMap.cpp Normal file
Просмотреть файл

@ -0,0 +1,221 @@
///////////////////////////////////////////////////////////////////////////////
// //
// DxilExportMap.cpp //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
// dxilutil::ExportMap for handling -exports option. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "dxc/Support/Global.h"
#include "dxc/HLSL/DxilUtil.h"
#include "dxc/HLSL/DxilExportMap.h"
#include "dxc/HLSL/DxilTypeSystem.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/Function.h"
#include <string>
#include <vector>
#include <set>
using namespace llvm;
using namespace hlsl;
namespace hlsl {
namespace dxilutil {
void ExportMap::clear() {
m_ExportMap.clear();
}
bool ExportMap::empty() const {
return m_ExportMap.empty();
}
bool ExportMap::ParseExports(const std::vector<std::string> &exportOpts, llvm::raw_ostream &errors) {
for (auto &str : exportOpts) {
llvm::StringRef exports = StoreString(str);
size_t start = 0;
size_t end = llvm::StringRef::npos;
// def1;def2;...
while (true) {
end = exports.find_first_of(';', start);
llvm::StringRef exportDef = exports.slice(start, end);
// def: export1[[,export2,...]=internal]
llvm::StringRef internalName = exportDef;
size_t equals = exportDef.find_first_of('=');
if (equals != llvm::StringRef::npos) {
internalName = exportDef.substr(equals + 1);
size_t exportStart = 0;
while (true) {
size_t comma = exportDef.find_first_of(',', exportStart);
if (comma == llvm::StringRef::npos || comma > equals)
break;
if (exportStart < comma)
Add(exportDef.slice(exportStart, comma), internalName);
exportStart = comma + 1;
}
if (exportStart < equals)
Add(exportDef.slice(exportStart, equals), internalName);
} else {
Add(internalName);
}
if (equals == 0 || internalName.empty()) {
errors << "Invalid syntax for -exports: '" << exportDef
<< "'. Syntax is: export1[[,export2,...]=internal][;...]";
return false;
}
if (end == llvm::StringRef::npos)
break;
start = end + 1;
}
}
return true;
}
void ExportMap::Add(llvm::StringRef exportName, llvm::StringRef internalName) {
// Incoming strings may be escaped (because they originally come from arguments)
// Unescape them here, if necessary
if (exportName.startswith("\\")) {
std::string str;
llvm::raw_string_ostream os(str);
PrintUnescapedString(exportName, os);
exportName = StoreString(os.str());
}
if (internalName.startswith("\\")) {
std::string str;
llvm::raw_string_ostream os(str);
PrintUnescapedString(internalName, os);
internalName = StoreString(os.str());
}
if (internalName.empty())
internalName = exportName;
exportName = DemangleFunctionName(exportName);
m_ExportMap[internalName].insert(exportName);
}
ExportMap::const_iterator ExportMap::GetExportsByName(llvm::StringRef Name) const {
ExportMap::const_iterator it = m_ExportMap.find(Name);
StringRef unmangled = DemangleFunctionName(Name);
if (it == end()) {
if (Name.startswith(ManglingPrefix)) {
it = m_ExportMap.find(unmangled);
}
else if (Name.startswith(EntryPrefix)) {
it = m_ExportMap.find(Name.substr(strlen(EntryPrefix)));
}
}
return it;
}
bool ExportMap::IsExported(llvm::StringRef original) const {
if (m_ExportMap.empty())
return true;
return GetExportsByName(original) != end();
}
void ExportMap::BeginProcessing() {
m_ExportNames.clear();
m_NameCollisions.clear();
m_UnusedExports.clear();
for (auto &it : m_ExportMap) {
m_UnusedExports.emplace(it.getKey());
}
}
bool ExportMap::ProcessFunction(llvm::Function *F, bool collisionAvoidanceRenaming) {
// Skip if already added. This can happen due to patch constant functions.
if (m_RenameMap.find(F) != m_RenameMap.end())
return true;
StringRef originalName = F->getName();
StringRef unmangled = DemangleFunctionName(originalName);
auto it = GetExportsByName(F->getName());
// Early out if not exported, and do optional collision avoidance
if (it == end()) {
F->setLinkage(GlobalValue::LinkageTypes::InternalLinkage);
if (collisionAvoidanceRenaming) {
std::string internalName = (Twine("internal.") + unmangled).str();
internalName = dxilutil::ReplaceFunctionName(originalName, internalName);
F->setName(internalName);
}
return false;
}
F->setLinkage(GlobalValue::LinkageTypes::ExternalLinkage);
// Add entry to m_RenameMap:
auto &renames = m_RenameMap[F];
const llvm::StringSet<> &exportRenames = it->getValue();
llvm::StringRef internalName = it->getKey();
// mark export used
UseExport(internalName);
// Add identity first
auto itIdentity = exportRenames.find(unmangled);
if (exportRenames.empty() || itIdentity != exportRenames.end()) {
if (exportRenames.size() > 1)
renames.insert(originalName);
ExportName(originalName);
} else if (collisionAvoidanceRenaming) {
// do optional collision avoidance for exports being renamed
std::string tempName = (Twine("temp.") + unmangled).str();
tempName = dxilutil::ReplaceFunctionName(originalName, tempName);
F->setName(tempName);
}
for (auto itName = exportRenames.begin(); itName != exportRenames.end(); itName++) {
// Now add actual renames
if (itName != itIdentity) {
StringRef newName = StoreString(dxilutil::ReplaceFunctionName(F->getName(), itName->getKey()));
renames.insert(newName);
ExportName(newName);
}
}
return true;
}
void ExportMap::RegisterExportedFunction(llvm::Function *F) {
// Skip if already added
if (m_RenameMap.find(F) != m_RenameMap.end())
return;
F->setLinkage(GlobalValue::LinkageTypes::ExternalLinkage);
NameSet &renames = m_RenameMap[F];
(void)(renames); // Don't actually add anything
ExportName(F->getName());
}
void ExportMap::UseExport(llvm::StringRef internalName) {
auto it = m_UnusedExports.find(internalName);
if (it != m_UnusedExports.end())
m_UnusedExports.erase(it);
}
void ExportMap::ExportName(llvm::StringRef exportName) {
auto result = m_ExportNames.insert(exportName);
if (!result.second) {
// Already present, report collision
m_NameCollisions.insert(exportName);
}
}
bool ExportMap::EndProcessing() const {
return m_UnusedExports.empty() && m_NameCollisions.empty();
}
llvm::StringRef ExportMap::StoreString(llvm::StringRef str) {
return *m_StringStorage.insert(str).first;
}
} // dxilutil
} // hlsl

Просмотреть файл

@ -38,6 +38,8 @@
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "dxc/HLSL/DxilExportMap.h"
using namespace llvm;
using namespace hlsl;
@ -65,7 +67,9 @@ void AddResourceMap(
}
}
void CloneFunction(Function *F, Function *NewF, ValueToValueMapTy &vmap) {
void CloneFunction(Function *F, Function *NewF, ValueToValueMapTy &vmap,
hlsl::DxilTypeSystem *TypeSys = nullptr,
hlsl::DxilTypeSystem *SrcTypeSys = nullptr) {
SmallVector<ReturnInst *, 2> Returns;
// Map params.
auto paramIt = NewF->arg_begin();
@ -74,6 +78,11 @@ void CloneFunction(Function *F, Function *NewF, ValueToValueMapTy &vmap) {
}
llvm::CloneFunctionInto(NewF, F, vmap, /*ModuleLevelChanges*/ true, Returns);
if (TypeSys) {
if (SrcTypeSys == nullptr)
SrcTypeSys = TypeSys;
TypeSys->CopyFunctionAnnotation(NewF, F, *SrcTypeSys);
}
// Remove params from vmap.
for (Argument &param : F->args()) {
@ -138,8 +147,7 @@ public:
void DetachAll() override;
std::unique_ptr<llvm::Module>
Link(StringRef entry, StringRef profile,
llvm::StringMap<llvm::StringRef> &exportMap) override;
Link(StringRef entry, StringRef profile, dxilutil::ExportMap &exportMap) override;
private:
bool AttachLib(DxilLib *lib);
@ -318,7 +326,7 @@ DxilResourceBase *DxilLib::GetResource(const llvm::Constant *GV) {
namespace {
// Create module from link defines.
struct DxilLinkJob {
DxilLinkJob(LLVMContext &Ctx, llvm::StringMap<llvm::StringRef> &exportMap,
DxilLinkJob(LLVMContext &Ctx, dxilutil::ExportMap &exportMap,
unsigned valMajor, unsigned valMinor)
: m_ctx(Ctx), m_exportMap(exportMap), m_valMajor(valMajor),
m_valMinor(valMinor) {}
@ -350,7 +358,7 @@ private:
llvm::StringMap<std::pair<DxilResourceBase *, llvm::GlobalVariable *>>
m_resourceMap;
LLVMContext &m_ctx;
llvm::StringMap<llvm::StringRef> &m_exportMap;
dxilutil::ExportMap &m_exportMap;
unsigned m_valMajor, m_valMinor;
};
} // namespace
@ -368,6 +376,9 @@ const char kNoEntryProps[] =
const char kRedefineResource[] =
"Resource already exists as ";
const char kInvalidValidatorVersion[] = "Validator version does not support target profile ";
const char kExportNameCollision[] = "Export name collides with another export: ";
const char kExportFunctionMissing[] = "Could not find target for export: ";
const char kNoFunctionsToExport[] = "Library has no functions to export";
} // namespace
//------------------------------------------------------------------------------
//
@ -783,6 +794,10 @@ DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
std::unique_ptr<Module>
DxilLinkJob::LinkToLib(const ShaderModel *pSM) {
if (m_functionDefs.empty()) {
m_ctx.emitError(Twine(kNoFunctionsToExport));
return nullptr;
}
DxilLib *pLib = m_functionDefs.begin()->second;
DxilModule &tmpDM = pLib->GetDxilModule();
// Create new module.
@ -854,19 +869,68 @@ DxilLinkJob::LinkToLib(const ShaderModel *pSM) {
RunPreparePass(*pM);
if (!m_exportMap.empty()) {
m_exportMap.BeginProcessing();
DM.ClearDxilMetadata(*pM);
for (auto it = pM->begin(); it != pM->end();) {
Function *F = it++;
if (F->isDeclaration())
continue;
StringRef name = F->getName();
name = dxilutil::DemangleFunctionName(name);
// Remove Function not in exportMap.
if (m_exportMap.find(name) == m_exportMap.end()) {
if (!m_exportMap.ProcessFunction(F, true)) {
// Remove Function not in exportMap.
DM.RemoveFunction(F);
F->eraseFromParent();
}
}
if(!m_exportMap.EndProcessing()) {
for (auto &name : m_exportMap.GetNameCollisions()) {
std::string escaped;
llvm::raw_string_ostream os(escaped);
dxilutil::PrintEscapedString(name, os);
m_ctx.emitError(Twine(kExportNameCollision) + os.str());
}
for (auto &name : m_exportMap.GetUnusedExports()) {
std::string escaped;
llvm::raw_string_ostream os(escaped);
dxilutil::PrintEscapedString(name, os);
m_ctx.emitError(Twine(kExportFunctionMissing) + os.str());
}
return nullptr;
}
// Rename the original, if necessary, then clone the rest
for (auto &it : m_exportMap.GetFunctionRenames()) {
Function *F = it.first;
auto &renames = it.second;
if (renames.empty())
continue;
auto itName = renames.begin();
// Rename the original, if necessary, then clone the rest
if (renames.find(F->getName()) == renames.end())
F->setName(*(itName++));
while (itName != renames.end()) {
if (F->getName() != *itName) {
Function *NewF = Function::Create(F->getFunctionType(),
GlobalValue::LinkageTypes::ExternalLinkage,
*itName, DM.GetModule());
ValueToValueMapTy vmap;
CloneFunction(F, NewF, vmap, &DM.GetTypeSystem());
// add DxilFunctionProps if entry
if (DM.HasDxilFunctionProps(F)) {
DxilFunctionProps &props = DM.GetDxilFunctionProps(F);
auto newProps = llvm::make_unique<DxilFunctionProps>(props);
DM.AddDxilFunctionProps(NewF, newProps);
}
}
itName++;
}
}
DM.EmitDxilMetadata();
}
@ -1153,8 +1217,7 @@ bool DxilLinkerImpl::AddFunctions(SmallVector<StringRef, 4> &workList,
}
std::unique_ptr<llvm::Module>
DxilLinkerImpl::Link(StringRef entry, StringRef profile,
llvm::StringMap<llvm::StringRef> &exportMap) {
DxilLinkerImpl::Link(StringRef entry, StringRef profile, dxilutil::ExportMap &exportMap) {
const ShaderModel *pSM = ShaderModel::GetByName(profile.data());
DXIL::ShaderKind kind = pSM->GetKind();
if (kind == DXIL::ShaderKind::Invalid ||
@ -1170,16 +1233,13 @@ DxilLinkerImpl::Link(StringRef entry, StringRef profile,
return nullptr;
}
// Skip validation for lib target until implemented.
if (!pSM->IsLib()) {
// Verifying validator version supports the requested profile
unsigned minValMajor, minValMinor;
pSM->GetMinValidatorVersion(minValMajor, minValMinor);
if (minValMajor > m_valMajor ||
(minValMajor == m_valMajor && minValMinor > m_valMinor)) {
m_ctx.emitError(Twine(kInvalidValidatorVersion) + profile);
return nullptr;
}
// Verifying validator version supports the requested profile
unsigned minValMajor, minValMinor;
pSM->GetMinValidatorVersion(minValMajor, minValMinor);
if (minValMajor > m_valMajor ||
(minValMajor == m_valMajor && minValMinor > m_valMinor)) {
m_ctx.emitError(Twine(kInvalidValidatorVersion) + profile);
return nullptr;
}
DxilLinkJob linkJob(m_ctx, exportMap, m_valMajor, m_valMinor);
@ -1234,9 +1294,8 @@ DxilLinkerImpl::Link(StringRef entry, StringRef profile,
// Only add exported functions.
for (auto &it : m_functionNameMap) {
StringRef name = it.getKey();
StringRef demangledName = dxilutil::DemangleFunctionName(name);
// Only add names exist in exportMap.
if (exportMap.find(demangledName) != exportMap.end())
if (exportMap.IsExported(name))
workList.emplace_back(name);
}

Просмотреть файл

@ -373,6 +373,8 @@ private:
}
} else {
std::vector<Function *> entries;
// Handle when multiple hull shaders point to the same patch constant function
DenseMap<Function*,Function*> patchConstantUpdates;
for (iplist<Function>::iterator F : M.getFunctionList()) {
if (DM.IsEntryThatUsesSignatures(F)) {
auto *FT = F->getFunctionType();
@ -384,9 +386,15 @@ private:
for (Function *entry : entries) {
DxilFunctionProps &props = DM.GetDxilFunctionProps(entry);
if (props.IsHS()) {
Function* patchConstFunc = props.ShaderProps.HS.patchConstantFunc;
auto it = patchConstantUpdates.find(patchConstFunc);
if (it == patchConstantUpdates.end()) {
patchConstFunc = patchConstantUpdates[patchConstFunc] =
StripFunctionParameter(patchConstFunc, DM, FunctionDIs);
} else {
patchConstFunc = it->second;
}
// Strip patch constant function first.
Function *patchConstFunc = StripFunctionParameter(
props.ShaderProps.HS.patchConstantFunc, DM, FunctionDIs);
DM.SetPatchConstantFunctionForHS(entry, patchConstFunc);
}
StripFunctionParameter(entry, DM, FunctionDIs);

Просмотреть файл

@ -25,6 +25,8 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/IRBuilder.h"
#include "dxc/Support/Global.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
using namespace llvm;
using namespace hlsl;
@ -33,6 +35,9 @@ namespace hlsl {
namespace dxilutil {
const char ManglingPrefix[] = "\01?";
const char EntryPrefix[] = "dx.entry.";
Type *GetArrayEltTy(Type *Ty) {
if (isa<PointerType>(Ty))
Ty = Ty->getPointerElementType();
@ -129,17 +134,60 @@ void PrintDiagnosticHandler(const llvm::DiagnosticInfo &DI, void *Context) {
}
StringRef DemangleFunctionName(StringRef name) {
if (!name.startswith("\01?")) {
// Name don't mangled.
if (!name.startswith(ManglingPrefix)) {
// Name isn't mangled.
return name;
}
size_t nameEnd = name.find_first_of("@");
DXASSERT(nameEnd != StringRef::npos, "else Name don't mangled but has \01?");
DXASSERT(nameEnd != StringRef::npos, "else Name isn't mangled but has \01?");
return name.substr(2, nameEnd - 2);
}
std::string ReplaceFunctionName(StringRef originalName, StringRef newName) {
if (originalName.startswith(ManglingPrefix)) {
return (Twine(ManglingPrefix) + newName +
originalName.substr(originalName.find_first_of('@'))).str();
} else if (originalName.startswith(EntryPrefix)) {
return (Twine(EntryPrefix) + newName).str();
}
return newName.str();
}
// From AsmWriter.cpp
// PrintEscapedString - Print each character of the specified string, escaping
// it if it is not printable or if it is an escape char.
void PrintEscapedString(StringRef Name, raw_ostream &Out) {
for (unsigned i = 0, e = Name.size(); i != e; ++i) {
unsigned char C = Name[i];
if (isprint(C) && C != '\\' && C != '"')
Out << C;
else
Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
}
}
void PrintUnescapedString(StringRef Name, raw_ostream &Out) {
for (unsigned i = 0, e = Name.size(); i != e; ++i) {
unsigned char C = Name[i];
if (C == '\\') {
C = Name[++i];
unsigned value = hexDigitValue(C);
if (value != -1U) {
C = (unsigned char)value;
unsigned value2 = hexDigitValue(Name[i+1]);
assert(value2 != -1U && "otherwise, not a two digit hex escape");
if (value2 != -1U) {
C = (C << 4) + (unsigned char)value2;
++i;
}
} // else, the next character (in C) should be the escaped character
}
Out << C;
}
}
std::unique_ptr<llvm::Module> LoadModuleFromBitcode(llvm::MemoryBuffer *MB,
llvm::LLVMContext &Ctx,
std::string &DiagStr) {
@ -293,5 +341,6 @@ llvm::Instruction *FirstNonAllocaInsertionPt(llvm::Function* F) {
return SkipAllocas(
F->getEntryBlock().getFirstInsertionPt());
}
}
}

Просмотреть файл

@ -202,6 +202,8 @@ public:
hlsl::DXIL::Float32DenormMode HLSLFloat32DenormMode;
/// HLSLDefaultSpace also enables automatic binding for libraries if set. UINT_MAX == unset
unsigned HLSLDefaultSpace = UINT_MAX;
/// HLSLLibraryExports specifies desired exports, with optional renaming
std::vector<std::string> HLSLLibraryExports;
// HLSL Change Ends
/// Regular expression to select optimizations for which we should enable
/// optimization remarks. Transformation passes whose name matches this

Просмотреть файл

@ -28,6 +28,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
@ -44,6 +45,7 @@
#include "dxc/dxcapi.h" // stream support
#include "dxc/HLSL/HLSLExtensionsCodegenHelper.h"
#include "dxc/HLSL/DxilGenerationPass.h" // support pause/resume passes
#include "dxc/HLSL/DxilExportMap.h"
using namespace clang;
using namespace CodeGen;
@ -125,6 +127,9 @@ private:
bool m_bDebugInfo;
bool m_bIsLib;
// For library, m_ExportMap maps from internal name to zero or more renames
dxilutil::ExportMap m_ExportMap;
HLCBuffer &GetGlobalCBuffer() {
return *static_cast<HLCBuffer*>(&(m_pHLModule->GetCBuffer(globalCBIndex)));
}
@ -143,7 +148,7 @@ private:
};
EntryFunctionInfo Entry;
// Map to save patch constant functions
struct PatchConstantInfo {
clang::SourceLocation SL = clang::SourceLocation();
@ -436,6 +441,15 @@ CGMSHLSLRuntime::CGMSHLSLRuntime(CodeGenModule &CGM)
// set Float Denorm Mode
m_pHLModule->SetFloat32DenormMode(CGM.getCodeGenOpts().HLSLFloat32DenormMode);
// Fill in m_ExportMap, which maps from internal name to zero or more renames
m_ExportMap.clear();
std::string errors;
llvm::raw_string_ostream os(errors);
if (!m_ExportMap.ParseExports(CGM.getCodeGenOpts().HLSLLibraryExports, os)) {
DiagnosticsEngine &Diags = CGM.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "Error parsing -exports options: %0");
Diags.Report(DiagID) << os.str();
}
}
bool CGMSHLSLRuntime::IsHlslObjectType(llvm::Type *Ty) {
@ -1880,14 +1894,24 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
AddTypeAnnotation(Ty, dxilTypeSys, arrayEltSize);
}
// clear isExportedEntry if not exporting entry
bool isExportedEntry = profileAttributes != 0;
if (isExportedEntry) {
// use unmangled or mangled name depending on which is used for final entry function
StringRef name = isRay ? F->getName() : FD->getName();
if (!m_ExportMap.IsExported(name)) {
isExportedEntry = false;
}
}
// Only add functionProps when exist.
if (profileAttributes || isEntry)
if (isExportedEntry || isEntry)
m_pHLModule->AddDxilFunctionProps(F, funcProps);
if (isPatchConstantFunction)
patchConstantFunctionPropsMap[F] = std::move(funcProps);
// Save F to entry map.
if (profileAttributes) {
if (isExportedEntry) {
if (entryFunctionMap.count(FD->getName())) {
DiagnosticsEngine &Diags = CGM.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
@ -4110,44 +4134,48 @@ static void SimpleTransformForHLDXIR(llvm::Module *pM) {
I->eraseFromParent();
}
// Clone shader entry function to be called by other functions.
// The original function will be used as shader entry.
static void CloneShaderEntry(Function *ShaderF, StringRef EntryName,
HLModule &HLM) {
// Use mangled name for cloned one.
Function *F = Function::Create(ShaderF->getFunctionType(),
static Function *CloneFunction(Function *Orig,
const llvm::Twine &Name,
llvm::Module *llvmModule,
hlsl::DxilTypeSystem &TypeSys,
hlsl::DxilTypeSystem &SrcTypeSys) {
Function *F = Function::Create(Orig->getFunctionType(),
GlobalValue::LinkageTypes::ExternalLinkage,
"", HLM.GetModule());
F->takeName(ShaderF);
// Set to name before mangled.
ShaderF->setName(EntryName);
Name, llvmModule);
SmallVector<ReturnInst *, 2> Returns;
ValueToValueMapTy vmap;
// Map params.
auto entryParamIt = F->arg_begin();
for (Argument &param : ShaderF->args()) {
for (Argument &param : Orig->args()) {
vmap[&param] = (entryParamIt++);
}
llvm::CloneFunctionInto(F, ShaderF, vmap, /*ModuleLevelChagnes*/ false,
Returns);
llvm::CloneFunctionInto(F, Orig, vmap, /*ModuleLevelChagnes*/ false, Returns);
TypeSys.CopyFunctionAnnotation(F, Orig, SrcTypeSys);
// Copy function annotation.
DxilFunctionAnnotation *shaderAnnot = HLM.GetFunctionAnnotation(ShaderF);
DxilFunctionAnnotation *annot = HLM.AddFunctionAnnotation(F);
return F;
}
DxilParameterAnnotation &retAnnot = shaderAnnot->GetRetTypeAnnotation();
// Clone shader entry function to be called by other functions.
// The original function will be used as shader entry.
static void CloneShaderEntry(Function *ShaderF, StringRef EntryName,
HLModule &HLM) {
Function *F = CloneFunction(ShaderF, "", HLM.GetModule(),
HLM.GetTypeSystem(), HLM.GetTypeSystem());
F->takeName(ShaderF);
// Set to name before mangled.
ShaderF->setName(EntryName);
DxilFunctionAnnotation *annot = HLM.GetFunctionAnnotation(F);
DxilParameterAnnotation &cloneRetAnnot = annot->GetRetTypeAnnotation();
cloneRetAnnot = retAnnot;
// Clear semantic for cloned one.
cloneRetAnnot.SetSemanticString("");
cloneRetAnnot.SetSemanticIndexVec({});
for (unsigned i = 0; i < shaderAnnot->GetNumParameters(); i++) {
for (unsigned i = 0; i < annot->GetNumParameters(); i++) {
DxilParameterAnnotation &cloneParamAnnot = annot->GetParameterAnnotation(i);
DxilParameterAnnotation &paramAnnot =
shaderAnnot->GetParameterAnnotation(i);
cloneParamAnnot = paramAnnot;
// Clear semantic for cloned one.
cloneParamAnnot.SetSemanticString("");
cloneParamAnnot.SetSemanticIndexVec({});
@ -4429,6 +4457,8 @@ void CGMSHLSLRuntime::FinishCodeGen() {
if (m_pHLModule->GetDxilFunctionProps(it.second.Func).IsRay())
continue;
// TODO: change flattened function names to dx.entry.<name>:
//std::string entryName = (Twine(dxilutil::EntryPrefix) + it.getKey()).str();
CloneShaderEntry(it.second.Func, it.getKey(), *m_pHLModule);
auto AttrIter = HSEntryPatchConstantFuncAttr.find(it.second.Func);
@ -4480,6 +4510,17 @@ void CGMSHLSLRuntime::FinishCodeGen() {
// translate opcode into parameter for intrinsic functions
AddOpcodeParamForIntrinsics(*m_pHLModule, m_IntrinsicMap, resMetadataMap);
// Register patch constant functions referenced by exported Hull Shaders
if (m_bIsLib && !m_ExportMap.empty()) {
for (auto &it : entryFunctionMap) {
if (m_pHLModule->HasDxilFunctionProps(it.second.Func)) {
const DxilFunctionProps &props = m_pHLModule->GetDxilFunctionProps(it.second.Func);
if (props.IsHS())
m_ExportMap.RegisterExportedFunction(props.ShaderProps.HS.patchConstantFunc);
}
}
}
// Pin entry point and constant buffers, mark everything else internal.
for (Function &f : m_pHLModule->GetModule()->functions()) {
if (!m_bIsLib) {
@ -4498,6 +4539,62 @@ void CGMSHLSLRuntime::FinishCodeGen() {
f.addFnAttr(llvm::Attribute::AlwaysInline);
}
if (m_bIsLib && !m_ExportMap.empty()) {
m_ExportMap.BeginProcessing();
for (Function &f : m_pHLModule->GetModule()->functions()) {
if (f.isDeclaration() || f.isIntrinsic() ||
GetHLOpcodeGroup(&f) != HLOpcodeGroup::NotHL)
continue;
m_ExportMap.ProcessFunction(&f, true);
}
// TODO: add subobject export names here.
if (!m_ExportMap.EndProcessing()) {
for (auto &name : m_ExportMap.GetNameCollisions()) {
DiagnosticsEngine &Diags = CGM.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"Export name collides with another export: %0");
std::string escaped;
llvm::raw_string_ostream os(escaped);
dxilutil::PrintEscapedString(name, os);
Diags.Report(DiagID) << os.str();
}
for (auto &name : m_ExportMap.GetUnusedExports()) {
DiagnosticsEngine &Diags = CGM.getDiags();
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
"Could not find target for export: %0");
std::string escaped;
llvm::raw_string_ostream os(escaped);
dxilutil::PrintEscapedString(name, os);
Diags.Report(DiagID) << os.str();
}
}
}
for (auto &it : m_ExportMap.GetFunctionRenames()) {
Function *F = it.first;
auto &renames = it.second;
if (renames.empty())
continue;
// Rename the original, if necessary, then clone the rest
if (renames.find(F->getName()) == renames.end())
F->setName(*renames.begin());
for (auto &itName : renames) {
if (F->getName() != itName) {
Function *pClone = CloneFunction(F, itName, m_pHLModule->GetModule(),
m_pHLModule->GetTypeSystem(), m_pHLModule->GetTypeSystem());
// add DxilFunctionProps if entry
if (m_pHLModule->HasDxilFunctionProps(F)) {
DxilFunctionProps &props = m_pHLModule->GetDxilFunctionProps(F);
auto newProps = llvm::make_unique<DxilFunctionProps>(props);
m_pHLModule->AddDxilFunctionProps(pClone, newProps);
}
}
}
}
// Do simple transform to make later lower pass easier.
SimpleTransformForHLDXIR(m_pHLModule->GetModule());

Просмотреть файл

@ -0,0 +1,93 @@
// RUN: %dxc -auto-binding-space 13 -exports VS_RENAMED=\01?VSMain@@YA?AV?$vector@M$03@@V?$vector@H$02@@@Z;PS_RENAMED=PSMain -T lib_6_3 %s | %D3DReflect %s | FileCheck %s
Buffer<float> T_unused;
float fn_unused(int i) { return T_unused.Load(i); }
Buffer<int> T0;
Texture2D<float4> T1;
struct Foo { uint u; float f; };
StructuredBuffer<Foo> T2;
[shader("vertex")]
float4 VSMain(int3 coord : COORD) : SV_Position {
return T1.Load(coord);
}
[shader("pixel")]
float4 PSMain(int idx : INDEX) : SV_Target {
return T2[T0.Load(idx)].f;
}
// CHECK: ID3D12LibraryReflection:
// CHECK: D3D12_LIBRARY_DESC:
// CHECK: FunctionCount: 3
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?PS_RENAMED@@YA?AV?$vector@M$03@@H@Z
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 2
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T0
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_SINT
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T2
// CHECK: Type: D3D_SIT_STRUCTURED
// CHECK: uID: 2
// CHECK: BindCount: 1
// CHECK: BindPoint: 2
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 8
// CHECK: uFlags: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?VS_RENAMED@@YA?AV?$vector@M$03@@V?$vector@H$02@@@Z
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 1
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T1
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 1
// CHECK: BindCount: 1
// CHECK: BindPoint: 1
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_FLOAT
// CHECK: Dimension: D3D_SRV_DIMENSION_TEXTURE2D
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0xc
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: PS_RENAMED
// CHECK: Shader Version: Pixel 6.3
// CHECK: BoundResources: 2
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T0
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_SINT
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T2
// CHECK: Type: D3D_SIT_STRUCTURED
// CHECK: uID: 2
// CHECK: BindCount: 1
// CHECK: BindPoint: 2
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 8
// CHECK: uFlags: 0

Просмотреть файл

@ -0,0 +1,92 @@
// RUN: %dxc -auto-binding-space 13 -exports VSMain;VS_RENAMED=\01?VSMain@@YA?AV?$vector@M$03@@V?$vector@H$02@@@Z;RayGen1,RayGen2=RayGen -T lib_6_3 %s | %D3DReflect %s | FileCheck %s
Buffer<int> T0;
Texture2D<float4> T1;
struct Foo { uint u; float f; };
StructuredBuffer<Foo> T2;
RWByteAddressBuffer U0;
[shader("vertex")]
float4 VSMain(int3 coord : COORD) : SV_Position {
return T1.Load(coord);
}
[shader("pixel")]
float4 PSMain(int idx : INDEX) : SV_Target {
return T2[T0.Load(idx)].f;
}
[shader("raygeneration")]
void RayGen() {
uint2 dim = DispatchRaysDimensions();
uint2 idx = DispatchRaysIndex();
U0.Store(idx.y * dim.x * 4 + idx.x * 4, idx.x ^ idx.y);
}
// CHECK: ID3D12LibraryReflection:
// CHECK: D3D12_LIBRARY_DESC:
// CHECK: FunctionCount: 4
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?RayGen1@@YAXXZ
// CHECK: Shader Version: RayGeneration 6.3
// CHECK: BoundResources: 1
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: U0
// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 0
// CHECK: uFlags: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?RayGen2@@YAXXZ
// CHECK: Shader Version: RayGeneration 6.3
// CHECK: BoundResources: 1
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: U0
// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 0
// CHECK: uFlags: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?VS_RENAMED@@YA?AV?$vector@M$03@@V?$vector@H$02@@@Z
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 1
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T1
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_FLOAT
// CHECK: Dimension: D3D_SRV_DIMENSION_TEXTURE2D
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0xc
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: VSMain
// CHECK: Shader Version: Vertex 6.3
// CHECK: BoundResources: 1
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T1
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_FLOAT
// CHECK: Dimension: D3D_SRV_DIMENSION_TEXTURE2D
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0xc

Просмотреть файл

@ -0,0 +1,173 @@
// RUN: %dxc -auto-binding-space 13 -exports PSMain,PSMain_Clone1,PSMain_Clone2=PSMain -T lib_6_3 %s | %D3DReflect %s | FileCheck %s
Buffer<int> T0;
Texture2D<float4> T1;
struct Foo { uint u; float f; };
StructuredBuffer<Foo> T2;
[shader("vertex")]
float4 VSMain(int3 coord : COORD) : SV_Position {
return T1.Load(coord);
}
[shader("pixel")]
float4 PSMain(int idx : INDEX) : SV_Target {
return T2[T0.Load(idx)].f;
}
// CHECK: ID3D12LibraryReflection:
// CHECK: D3D12_LIBRARY_DESC:
// CHECK: FunctionCount: 6
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?PSMain@@YA?AV?$vector@M$03@@H@Z
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 2
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T0
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_SINT
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T2
// CHECK: Type: D3D_SIT_STRUCTURED
// CHECK: uID: 1
// CHECK: BindCount: 1
// CHECK: BindPoint: 1
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 8
// CHECK: uFlags: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?PSMain_Clone1@@YA?AV?$vector@M$03@@H@Z
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 2
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T0
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_SINT
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T2
// CHECK: Type: D3D_SIT_STRUCTURED
// CHECK: uID: 1
// CHECK: BindCount: 1
// CHECK: BindPoint: 1
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 8
// CHECK: uFlags: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?PSMain_Clone2@@YA?AV?$vector@M$03@@H@Z
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 2
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T0
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_SINT
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T2
// CHECK: Type: D3D_SIT_STRUCTURED
// CHECK: uID: 1
// CHECK: BindCount: 1
// CHECK: BindPoint: 1
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 8
// CHECK: uFlags: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: PSMain
// CHECK: Shader Version: Pixel 6.3
// CHECK: BoundResources: 2
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T0
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_SINT
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T2
// CHECK: Type: D3D_SIT_STRUCTURED
// CHECK: uID: 1
// CHECK: BindCount: 1
// CHECK: BindPoint: 1
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 8
// CHECK: uFlags: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: PSMain_Clone1
// CHECK: Shader Version: Pixel 6.3
// CHECK: BoundResources: 2
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T0
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_SINT
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T2
// CHECK: Type: D3D_SIT_STRUCTURED
// CHECK: uID: 1
// CHECK: BindCount: 1
// CHECK: BindPoint: 1
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 8
// CHECK: uFlags: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: PSMain_Clone2
// CHECK: Shader Version: Pixel 6.3
// CHECK: BoundResources: 2
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T0
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_SINT
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T2
// CHECK: Type: D3D_SIT_STRUCTURED
// CHECK: uID: 1
// CHECK: BindCount: 1
// CHECK: BindPoint: 1
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 8
// CHECK: uFlags: 0

Просмотреть файл

@ -0,0 +1,103 @@
// RUN: %dxc -auto-binding-space 13 -exports VSMain=PSMain;PSMain=VSMain -T lib_6_3 %s | %D3DReflect %s | FileCheck %s
Buffer<int> T0;
Texture2D<float4> T1;
struct Foo { uint u; float f; };
StructuredBuffer<Foo> T2;
[shader("vertex")]
float4 VSMain(int3 coord : COORD) : SV_Position {
return T1.Load(coord);
}
[shader("pixel")]
float4 PSMain(int idx : INDEX) : SV_Target {
return T2[T0.Load(idx)].f;
}
// CHECK: ID3D12LibraryReflection:
// CHECK: D3D12_LIBRARY_DESC:
// CHECK: FunctionCount: 4
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?PSMain@@YA?AV?$vector@M$03@@V?$vector@H$02@@@Z
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 1
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T1
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 1
// CHECK: BindCount: 1
// CHECK: BindPoint: 1
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_FLOAT
// CHECK: Dimension: D3D_SRV_DIMENSION_TEXTURE2D
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0xc
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?VSMain@@YA?AV?$vector@M$03@@H@Z
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 2
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T0
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_SINT
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T2
// CHECK: Type: D3D_SIT_STRUCTURED
// CHECK: uID: 2
// CHECK: BindCount: 1
// CHECK: BindPoint: 2
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 8
// CHECK: uFlags: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: PSMain
// CHECK: Shader Version: Vertex 6.3
// CHECK: BoundResources: 1
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T1
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 1
// CHECK: BindCount: 1
// CHECK: BindPoint: 1
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_FLOAT
// CHECK: Dimension: D3D_SRV_DIMENSION_TEXTURE2D
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0xc
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: VSMain
// CHECK: Shader Version: Pixel 6.3
// CHECK: BoundResources: 2
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T0
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_SINT
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T2
// CHECK: Type: D3D_SIT_STRUCTURED
// CHECK: uID: 2
// CHECK: BindCount: 1
// CHECK: BindPoint: 2
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 8
// CHECK: uFlags: 0

Просмотреть файл

@ -0,0 +1,97 @@
// RUN: %dxc -auto-binding-space 13 -exports Foo=VSMain;Foo=\01?VSMain@@YA?AV?$vector@M$03@@V?$vector@H$02@@@Z;Foo=RayGen;fn1=fn2 -T lib_6_3 %s | %D3DReflect %s | FileCheck %s
Buffer<int> T0;
Texture2D<float4> T1;
struct Foo { uint u; float f; };
StructuredBuffer<Foo> T2;
RWByteAddressBuffer U0;
[shader("vertex")]
float4 VSMain(int3 coord : COORD) : SV_Position {
return T1.Load(coord);
}
[shader("pixel")]
float4 PSMain(int idx : INDEX) : SV_Target {
return T2[T0.Load(idx)].f;
}
void fn1() { U0.Store(1, T0.Load(2)); }
// rename fn2 to fn1, no collision because fn1 is internal
void fn2() { U0.Store(1, 3); }
[shader("raygeneration")]
void RayGen() {
uint2 dim = DispatchRaysDimensions();
uint2 idx = DispatchRaysIndex();
U0.Store(idx.y * dim.x * 4 + idx.x * 4, idx.x ^ idx.y);
}
// No Collision here between differently mangled functions, or to non-exported functions.
// CHECK: ID3D12LibraryReflection:
// CHECK: D3D12_LIBRARY_DESC:
// CHECK: FunctionCount: 4
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?Foo@@YA?AV?$vector@M$03@@V?$vector@H$02@@@Z
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 1
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T1
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_FLOAT
// CHECK: Dimension: D3D_SRV_DIMENSION_TEXTURE2D
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0xc
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?Foo@@YAXXZ
// CHECK: Shader Version: RayGeneration 6.3
// CHECK: BoundResources: 1
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: U0
// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 0
// CHECK: uFlags: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?fn1@@YAXXZ
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 1
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: U0
// CHECK: Type: D3D_SIT_UAV_RWBYTEADDRESS
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_MIXED
// CHECK: Dimension: D3D_SRV_DIMENSION_BUFFER
// CHECK: NumSamples (or stride): 0
// CHECK: uFlags: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: Foo
// CHECK: Shader Version: Vertex 6.3
// CHECK: BoundResources: 1
// CHECK: Bound Resources:
// CHECK: D3D12_SHADER_BUFFER_DESC: Name: T1
// CHECK: Type: D3D_SIT_TEXTURE
// CHECK: uID: 0
// CHECK: BindCount: 1
// CHECK: BindPoint: 0
// CHECK: Space: 13
// CHECK: ReturnType: D3D_RETURN_TYPE_FLOAT
// CHECK: Dimension: D3D_SRV_DIMENSION_TEXTURE2D
// CHECK: NumSamples (or stride): 4294967295
// CHECK: uFlags: 0xc

Просмотреть файл

@ -0,0 +1,96 @@
// RUN: %dxc -auto-binding-space 13 -T lib_6_3 -exports HSMain1;HSMain2;HSMain3 %s | %D3DReflect %s | FileCheck %s
// This version of HSPerPatchFunc1 should not be exported
// CHECK: ID3D12FunctionReflection:
// CHECK-NOT: D3D12_FUNCTION_DESC: Name: \01?HSPerPatchFunc1@@YA?AUHSPerPatchData@@V?$InputPatch@UPSSceneIn@@$0BA@@@@Z
// CHECK-NOT: D3D_SRV_DIMENSION_BUFFER
Buffer<float> T_unused;
struct PSSceneIn
{
float4 pos : SV_Position;
float2 tex : TEXCOORD0;
float3 norm : NORMAL;
};
struct HSPerPatchData
{
float edges[3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
// Should not be selected, since later candidate function with same name exists.
// If selected, it should fail, since patch size mismatches HS function.
HSPerPatchData HSPerPatchFunc1(
const InputPatch< PSSceneIn, 16 > points)
{
HSPerPatchData d;
d.edges[0] = -5;
d.edges[1] = -6;
d.edges[2] = -7;
d.inside = T_unused.Load(1).x;
return d;
}
HSPerPatchData HSPerPatchFunc2(
const InputPatch< PSSceneIn, 4 > points)
{
HSPerPatchData d;
d.edges[0] = -5;
d.edges[1] = -6;
d.edges[2] = -7;
d.inside = -8;
return d;
}
[shader("hull")]
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[patchconstantfunc("HSPerPatchFunc1")]
[outputcontrolpoints(3)]
void HSMain1( const uint id : SV_OutputControlPointID,
const InputPatch< PSSceneIn, 3 > points )
{
}
[shader("hull")]
[domain("quad")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[patchconstantfunc("HSPerPatchFunc2")]
[outputcontrolpoints(4)]
void HSMain2( const uint id : SV_OutputControlPointID,
const InputPatch< PSSceneIn, 4 > points )
{
}
[shader("hull")]
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_ccw")]
[patchconstantfunc("HSPerPatchFunc1")]
[outputcontrolpoints(3)]
void HSMain3( const uint id : SV_OutputControlPointID,
const InputPatch< PSSceneIn, 3 > points )
{
}
// actual selected HSPerPatchFunc1 for HSMain1 and HSMain3
HSPerPatchData HSPerPatchFunc1()
{
HSPerPatchData d;
d.edges[0] = -5;
d.edges[1] = -6;
d.edges[2] = -7;
d.inside = -8;
return d;
}

Просмотреть файл

@ -0,0 +1,118 @@
// RUN: %dxc -auto-binding-space 13 -T lib_6_3 -exports HSMain1;HSMain3 %s | %D3DReflect %s | FileCheck %s
Buffer<float> T_unused;
struct PSSceneIn
{
float4 pos : SV_Position;
float2 tex : TEXCOORD0;
float3 norm : NORMAL;
};
struct HSPerPatchData
{
float edges[3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
// Should not be selected, since later candidate function with same name exists.
// If selected, it should fail, since patch size mismatches HS function.
HSPerPatchData HSPerPatchFunc1(
const InputPatch< PSSceneIn, 16 > points)
{
HSPerPatchData d;
d.edges[0] = -5;
d.edges[1] = -6;
d.edges[2] = -7;
d.inside = T_unused.Load(1).x;
return d;
}
HSPerPatchData HSPerPatchFunc2(
const InputPatch< PSSceneIn, 4 > points)
{
HSPerPatchData d;
d.edges[0] = -5;
d.edges[1] = -6;
d.edges[2] = -7;
d.inside = -8;
return d;
}
[shader("hull")]
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[patchconstantfunc("HSPerPatchFunc1")]
[outputcontrolpoints(3)]
void HSMain1( const uint id : SV_OutputControlPointID,
const InputPatch< PSSceneIn, 3 > points )
{
}
[shader("hull")]
[domain("quad")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[patchconstantfunc("HSPerPatchFunc2")]
[outputcontrolpoints(4)]
void HSMain2( const uint id : SV_OutputControlPointID,
const InputPatch< PSSceneIn, 4 > points )
{
}
[shader("hull")]
[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_ccw")]
[patchconstantfunc("HSPerPatchFunc1")]
[outputcontrolpoints(3)]
void HSMain3( const uint id : SV_OutputControlPointID,
const InputPatch< PSSceneIn, 3 > points )
{
}
// actual selected HSPerPatchFunc1 for HSMain1 and HSMain3
HSPerPatchData HSPerPatchFunc1()
{
HSPerPatchData d;
d.edges[0] = -5;
d.edges[1] = -6;
d.edges[2] = -7;
d.inside = -8;
return d;
}
// CHECK: ID3D12LibraryReflection:
// CHECK: D3D12_LIBRARY_DESC:
// CHECK: FunctionCount: 5
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?HSMain1@@YAXIV?$InputPatch@UPSSceneIn@@$02@@@Z
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 0
// CHECK: ID3D12FunctionReflection:
// CHECK-NOT: D3D12_FUNCTION_DESC: Name: \01?HSMain2@@YAXIV?$InputPatch@UPSSceneIn@@$03@@@Z
// CHECK: D3D12_FUNCTION_DESC: Name: \01?HSMain3@@YAXIV?$InputPatch@UPSSceneIn@@$02@@@Z
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 0
// CHECK: ID3D12FunctionReflection:
// CHECK: D3D12_FUNCTION_DESC: Name: \01?HSPerPatchFunc1@@YA?AUHSPerPatchData@@XZ
// CHECK: Shader Version: Library 6.3
// CHECK: BoundResources: 0
// CHECK: ID3D12FunctionReflection:
// CHECK-NOT: D3D12_FUNCTION_DESC: Name: \01?HSPerPatchFunc2@@YA?AUHSPerPatchData@@V?$InputPatch@UPSSceneIn@@$03@@@Z
// CHECK: D3D12_FUNCTION_DESC: Name: HSMain1
// CHECK: Shader Version: Hull 6.3
// CHECK: BoundResources: 0
// CHECK: ID3D12FunctionReflection:
// CHECK-NOT: D3D12_FUNCTION_DESC: Name: HSMain2
// CHECK: D3D12_FUNCTION_DESC: Name: HSMain3
// CHECK: Shader Version: Hull 6.3
// CHECK: BoundResources: 0

Просмотреть файл

@ -0,0 +1,40 @@
// RUN: %dxc -auto-binding-space 13 -exports Foo=VSMain;Foo=VSMainDup;Foo=\01?VSMain@@YA?AV?$vector@M$03@@V?$vector@H$02@@@Z;Foo=\01?VSMainDup@@YA?AV?$vector@M$03@@V?$vector@H$02@@@Z;RayGen;RayGen=fn -T lib_6_3 %s | FileCheck %s
// Verify export collision errors
// CHECK: error: Export name collides with another export: \01?Foo@@YA?AV?$vector@M$03@@V?$vector@H$02@@@Z
// CHECK: error: Export name collides with another export: \01?RayGen@@YAXXZ
// CHECK: error: Export name collides with another export: Foo
Buffer<int> T0;
Texture2D<float4> T1;
struct Foo { uint u; float f; };
StructuredBuffer<Foo> T2;
RWByteAddressBuffer U0;
[shader("vertex")]
float4 VSMain(int3 coord : COORD) : SV_Position {
return T1.Load(coord);
}
[shader("vertex")]
float4 VSMainDup(int3 coord : COORD) : SV_Position {
return T1.Load(coord);
}
[shader("pixel")]
float4 PSMain(int idx : INDEX) : SV_Target {
return T2[T0.Load(idx)].f;
}
void fn() {
}
[shader("raygeneration")]
void RayGen() {
uint2 dim = DispatchRaysDimensions();
uint2 idx = DispatchRaysIndex();
U0.Store(idx.y * dim.x * 4 + idx.x * 4, idx.x ^ idx.y);
}

Просмотреть файл

@ -69,23 +69,6 @@ public:
*ppResult // Linker output status, buffer, and errors
) override;
// Links the shader with export and produces a shader blob that the Direct3D
// runtime can use.
HRESULT STDMETHODCALLTYPE LinkWithExports(
_In_opt_ LPCWSTR pEntryName, // Entry point name
_In_ LPCWSTR pTargetProfile, // shader profile to link
_In_count_(libCount)
const LPCWSTR *pLibNames, // Array of library names to link
UINT32 libCount, // Number of libraries to link
_In_count_(argCount)
const LPCWSTR *pArguments, // Array of pointers to arguments
_In_ UINT32 argCount, // Number of arguments
_In_count_(exportCount) const DxcDefine *pExports, // Array of exports
_In_ UINT32 exportCount, // Number of exports
_COM_Outptr_ IDxcOperationResult *
*ppResult // Linker output status, buffer, and errors
) override;
HRESULT STDMETHODCALLTYPE RegisterDxilContainerEventHandler(
IDxcContainerEventsHandler *pHandler, UINT64 *pCookie) override {
DxcThreadMalloc TM(m_pMalloc);
@ -166,6 +149,8 @@ DxcLinker::RegisterLibrary(_In_opt_ LPCWSTR pLibName, // Name of the library.
}
}
// Links the shader and produces a shader blob that the Direct3D runtime can
// use.
HRESULT STDMETHODCALLTYPE DxcLinker::Link(
_In_opt_ LPCWSTR pEntryName, // Entry point name
_In_ LPCWSTR pTargetProfile, // shader profile to link
@ -177,27 +162,6 @@ HRESULT STDMETHODCALLTYPE DxcLinker::Link(
_In_ UINT32 argCount, // Number of arguments
_COM_Outptr_ IDxcOperationResult *
*ppResult // Linker output status, buffer, and errors
) {
return LinkWithExports(pEntryName, pTargetProfile, pLibNames, libCount,
pArguments, argCount, /*pExorts*/ nullptr,
/*exportCount*/ 0, ppResult);
}
// Links the shader with export and produces a shader blob that the Direct3D
// runtime can use.
__override HRESULT STDMETHODCALLTYPE DxcLinker::LinkWithExports(
_In_opt_ LPCWSTR pEntryName, // Entry point name
_In_ LPCWSTR pTargetProfile, // shader profile to link
_In_count_(libCount)
const LPCWSTR *pLibNames, // Array of library names to link
UINT32 libCount, // Number of libraries to link
_In_count_(argCount)
const LPCWSTR *pArguments, // Array of pointers to arguments
_In_ UINT32 argCount, // Number of arguments
_In_count_(exportCount) const DxcDefine *pExports, // Array of exports
_In_ UINT32 exportCount, // Number of exports
_COM_Outptr_ IDxcOperationResult *
*ppResult // Linker output status, buffer, and errors
) {
DxcThreadMalloc TM(m_pMalloc);
// Prepare UTF8-encoded versions of API values.
@ -237,7 +201,7 @@ __override HRESULT STDMETHODCALLTYPE DxcLinker::LinkWithExports(
}
std::string warnings;
llvm::raw_string_ostream w(warnings);
//llvm::raw_string_ostream w(warnings);
IFT(CreateMemoryStream(pMalloc, &pDiagStream));
raw_stream_ostream DiagStream(pDiagStream);
llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
@ -252,16 +216,11 @@ __override HRESULT STDMETHODCALLTYPE DxcLinker::LinkWithExports(
bSuccess &= m_pLinker->AttachLib(pUtf8LibName.m_psz);
}
dxilutil::ExportMap exportMap;
bSuccess = exportMap.ParseExports(opts.Exports, DiagStream);
bool hasErrorOccurred = !bSuccess;
if (bSuccess) {
StringMap<StringRef> exportMap;
std::vector<std::string> names(exportCount);
for (unsigned i=0;i<exportCount;i++) {
const DxcDefine &pExport = pExports[i];
names[i] = CW2A(pExport.Name);
exportMap[names[i]] = "";
}
std::unique_ptr<Module> pM = m_pLinker->Link(
opts.EntryPoint, pUtf8TargetProfile.m_psz, exportMap);
if (pM) {

Просмотреть файл

@ -876,6 +876,9 @@ public:
// AutoBindingSpace also enables automatic binding for libraries if set. UINT_MAX == unset
compiler.getCodeGenOpts().HLSLDefaultSpace = Opts.AutoBindingSpace;
// processed export names from -exports option:
compiler.getCodeGenOpts().HLSLLibraryExports = Opts.Exports;
}
// IDxcVersionInfo

Просмотреть файл

@ -109,6 +109,8 @@ bool CheckOperationResultMsgs(IDxcOperationResult *pResult,
bool maySucceedAnyway, bool bRegex);
bool CheckMsgs(const LPCSTR pText, size_t TextCount, const LPCSTR *pErrorMsgs,
size_t errorMsgCount, bool bRegex);
bool CheckNotMsgs(const LPCSTR pText, size_t TextCount, const LPCSTR *pErrorMsgs,
size_t errorMsgCount, bool bRegex);
void GetDxilPart(dxc::DxcDllSupport &dllSupport, IDxcBlob *pProgram, IDxcBlob **pDxilPart);
std::string DisassembleProgram(dxc::DxcDllSupport &dllSupport, IDxcBlob *pProgram);
void SplitPassList(LPWSTR pPassesBuffer, std::vector<LPCWSTR> &passes);

Просмотреть файл

@ -53,6 +53,10 @@ public:
TEST_METHOD(RunLinkFailSelectRes);
TEST_METHOD(RunLinkToLibWithUnresolvedFunctions);
TEST_METHOD(RunLinkToLibWithUnresolvedFunctionsExports);
TEST_METHOD(RunLinkToLibWithExportNamesSwapped);
TEST_METHOD(RunLinkToLibWithExportCollision);
TEST_METHOD(RunLinkToLibWithUnusedExport);
TEST_METHOD(RunLinkToLibWithNoExports);
TEST_METHOD(RunLinkWithPotentialIntrinsicNameCollisions);
@ -98,10 +102,13 @@ public:
void Link(LPCWSTR pEntryName, LPCWSTR pShaderModel, IDxcLinker *pLinker,
ArrayRef<LPCWSTR> libNames, llvm::ArrayRef<LPCSTR> pCheckMsgs,
llvm::ArrayRef<LPCSTR> pCheckNotMsgs) {
llvm::ArrayRef<LPCSTR> pCheckNotMsgs,
llvm::ArrayRef<LPCWSTR> pArguments = {}) {
CComPtr<IDxcOperationResult> pResult;
VERIFY_SUCCEEDED(pLinker->Link(pEntryName, pShaderModel, libNames.data(),
libNames.size(), nullptr, 0, &pResult));
libNames.size(),
pArguments.data(), pArguments.size(),
&pResult));
CComPtr<IDxcBlob> pProgram;
CheckOperationSucceeded(pResult, &pProgram);
@ -113,40 +120,17 @@ public:
VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembly));
std::string IR = BlobToUtf8(pDisassembly);
CheckMsgs(IR.c_str(), IR.size(), pCheckMsgs.data(), pCheckMsgs.size(), false);
for (auto notMsg : pCheckNotMsgs) {
VERIFY_IS_TRUE(IR.find(notMsg) == std::string::npos);
}
CheckNotMsgs(IR.c_str(), IR.size(), pCheckNotMsgs.data(), pCheckNotMsgs.size(), false);
}
void LinkWithExports(IDxcLinker *pLinker, ArrayRef<LPCWSTR> libNames,
ArrayRef<DxcDefine> exportNames,
llvm::ArrayRef<LPCSTR> pCheckMsgs,
llvm::ArrayRef<LPCSTR> pCheckNotMsgs) {
CComPtr<IDxcOperationResult> pResult;
VERIFY_SUCCEEDED(pLinker->LinkWithExports(
/*pEntryName*/ nullptr, /*pShaderModel*/ L"lib_6_2", libNames.data(),
libNames.size(), nullptr, 0, exportNames.data(), exportNames.size(),
&pResult));
CComPtr<IDxcBlob> pProgram;
CheckOperationSucceeded(pResult, &pProgram);
CComPtr<IDxcCompiler> pCompiler;
CComPtr<IDxcBlobEncoding> pDisassembly;
VERIFY_SUCCEEDED(
m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembly));
std::string IR = BlobToUtf8(pDisassembly);
CheckMsgs(IR.c_str(), IR.size(), pCheckMsgs.data(), pCheckMsgs.size(), false);
for (auto notMsg : pCheckNotMsgs) {
VERIFY_IS_TRUE(IR.find(notMsg) == std::string::npos);
}
}
void LinkCheckMsg(LPCWSTR pEntryName, LPCWSTR pShaderModel, IDxcLinker *pLinker,
ArrayRef<LPCWSTR> libNames, llvm::ArrayRef<LPCSTR> pErrorMsgs) {
ArrayRef<LPCWSTR> libNames, llvm::ArrayRef<LPCSTR> pErrorMsgs,
llvm::ArrayRef<LPCWSTR> pArguments = {}) {
CComPtr<IDxcOperationResult> pResult;
VERIFY_SUCCEEDED(pLinker->Link(pEntryName, pShaderModel, libNames.data(),
libNames.size(), nullptr, 0, &pResult));
VERIFY_SUCCEEDED(pLinker->Link(pEntryName, pShaderModel,
libNames.data(), libNames.size(),
pArguments.data(), pArguments.size(),
&pResult));
CheckOperationResultMsgs(pResult, pErrorMsgs.data(), pErrorMsgs.size(),
false, false);
}
@ -374,8 +358,10 @@ TEST_F(LinkerTest, RunLinkToLibExport) {
LPCWSTR libName2 = L"test";
RegisterDxcModule(libName2, pLib, pLinker);
DxcDefine exports[] = { {L"test", L""} };
LinkWithExports(pLinker, {libName, libName2}, exports, {"@\"\\01?test@@","@test"}, {"@\"\\01?GetBuf"});
Link(L"", L"lib_6_3", pLinker, {libName, libName2},
{ "@\"\\01?renamed_test@@","@\"\\01?cloned_test@@","@test" },
{ "@\"\\01?GetBuf", "@renamed_test", "@cloned_test" },
{L"-exports", L"renamed_test,cloned_test=\\01?test@@YA?AV?$vector@M$03@@I@Z;test"});
}
TEST_F(LinkerTest, RunLinkFailSelectRes) {
@ -447,15 +433,127 @@ TEST_F(LinkerTest, RunLinkToLibWithUnresolvedFunctionsExports) {
LPCWSTR libName2 = L"lib2";
RegisterDxcModule(libName2, pLib2, pLinker);
DxcDefine exports[] = { { L"call_lib1", L"" }, { L"call_lib2", L"" } };
LinkWithExports(pLinker, { libName1, libName2 }, exports, {
"declare float @\"\\01?external_fn1@@YAMXZ\"()",
"declare float @\"\\01?external_fn2@@YAMXZ\"()",
"declare float @\"\\01?external_fn@@YAMXZ\"()",
"define float @\"\\01?call_lib1@@YAMXZ\"()",
"define float @\"\\01?call_lib2@@YAMXZ\"()"
}, { "declare float @\"\\01?unused_fn1", "declare float @\"\\01?unused_fn2",
"declare float @\"\\01?lib1_fn", "declare float @\"\\01?lib2_fn" });
Link(L"", L"lib_6_3", pLinker, { libName1, libName2 },
{ "declare float @\"\\01?external_fn1@@YAMXZ\"()",
"declare float @\"\\01?external_fn2@@YAMXZ\"()",
"declare float @\"\\01?external_fn@@YAMXZ\"()",
"define float @\"\\01?renamed_lib1@@YAMXZ\"()",
"define float @\"\\01?call_lib2@@YAMXZ\"()"
},
{ "float @\"\\01?unused_fn1", "float @\"\\01?unused_fn2",
"float @\"\\01?lib1_fn", "float @\"\\01?lib2_fn",
"float @\"\\01?call_lib1"
},
{ L"-exports", L"renamed_lib1=call_lib1",
L"-exports", L"call_lib2"
});
}
TEST_F(LinkerTest, RunLinkToLibWithExportNamesSwapped) {
LPCWSTR option[] = { L"-Zi" };
CComPtr<IDxcBlob> pLib1;
CompileLib(L"..\\CodeGenHLSL\\shader-compat-suite\\lib_unresolved_func1.hlsl",
&pLib1, option, 1);
CComPtr<IDxcBlob> pLib2;
CompileLib(L"..\\CodeGenHLSL\\shader-compat-suite\\lib_unresolved_func2.hlsl",
&pLib2, option, 1);
CComPtr<IDxcLinker> pLinker;
CreateLinker(&pLinker);
LPCWSTR libName1 = L"lib1";
RegisterDxcModule(libName1, pLib1, pLinker);
LPCWSTR libName2 = L"lib2";
RegisterDxcModule(libName2, pLib2, pLinker);
Link(L"", L"lib_6_3", pLinker, { libName1, libName2 },
{ "declare float @\"\\01?external_fn1@@YAMXZ\"()",
"declare float @\"\\01?external_fn2@@YAMXZ\"()",
"declare float @\"\\01?external_fn@@YAMXZ\"()",
"define float @\"\\01?call_lib1@@YAMXZ\"()",
"define float @\"\\01?call_lib2@@YAMXZ\"()"
},
{ "float @\"\\01?unused_fn1", "float @\"\\01?unused_fn2",
"float @\"\\01?lib1_fn", "float @\"\\01?lib2_fn"
},
{ L"-exports", L"call_lib2=call_lib1;call_lib1=call_lib2" });
}
TEST_F(LinkerTest, RunLinkToLibWithExportCollision) {
LPCWSTR option[] = { L"-Zi" };
CComPtr<IDxcBlob> pLib1;
CompileLib(L"..\\CodeGenHLSL\\shader-compat-suite\\lib_unresolved_func1.hlsl",
&pLib1, option, 1);
CComPtr<IDxcBlob> pLib2;
CompileLib(L"..\\CodeGenHLSL\\shader-compat-suite\\lib_unresolved_func2.hlsl",
&pLib2, option, 1);
CComPtr<IDxcLinker> pLinker;
CreateLinker(&pLinker);
LPCWSTR libName1 = L"lib1";
RegisterDxcModule(libName1, pLib1, pLinker);
LPCWSTR libName2 = L"lib2";
RegisterDxcModule(libName2, pLib2, pLinker);
LinkCheckMsg(L"", L"lib_6_3", pLinker, { libName1, libName2 },
{ "Export name collides with another export: \\01?call_lib2@@YAMXZ"
},
{ L"-exports", L"call_lib2=call_lib1;call_lib2" });
}
TEST_F(LinkerTest, RunLinkToLibWithUnusedExport) {
LPCWSTR option[] = { L"-Zi" };
CComPtr<IDxcBlob> pLib1;
CompileLib(L"..\\CodeGenHLSL\\shader-compat-suite\\lib_unresolved_func1.hlsl",
&pLib1, option, 1);
CComPtr<IDxcBlob> pLib2;
CompileLib(L"..\\CodeGenHLSL\\shader-compat-suite\\lib_unresolved_func2.hlsl",
&pLib2, option, 1);
CComPtr<IDxcLinker> pLinker;
CreateLinker(&pLinker);
LPCWSTR libName1 = L"lib1";
RegisterDxcModule(libName1, pLib1, pLinker);
LPCWSTR libName2 = L"lib2";
RegisterDxcModule(libName2, pLib2, pLinker);
LinkCheckMsg(L"", L"lib_6_3", pLinker, { libName1, libName2 },
{ "Could not find target for export: call_lib"
},
{ L"-exports", L"call_lib2=call_lib;call_lib1" });
}
TEST_F(LinkerTest, RunLinkToLibWithNoExports) {
LPCWSTR option[] = { L"-Zi" };
CComPtr<IDxcBlob> pLib1;
CompileLib(L"..\\CodeGenHLSL\\shader-compat-suite\\lib_unresolved_func1.hlsl",
&pLib1, option, 1);
CComPtr<IDxcBlob> pLib2;
CompileLib(L"..\\CodeGenHLSL\\shader-compat-suite\\lib_unresolved_func2.hlsl",
&pLib2, option, 1);
CComPtr<IDxcLinker> pLinker;
CreateLinker(&pLinker);
LPCWSTR libName1 = L"lib1";
RegisterDxcModule(libName1, pLib1, pLinker);
LPCWSTR libName2 = L"lib2";
RegisterDxcModule(libName2, pLib2, pLinker);
LinkCheckMsg(L"", L"lib_6_3", pLinker, { libName1, libName2 },
{ "Library has no functions to export"
},
{ L"-exports", L"call_lib2=call_lib" });
}
TEST_F(LinkerTest, RunLinkWithPotentialIntrinsicNameCollisions) {

Просмотреть файл

@ -45,7 +45,12 @@ static bool CheckMsgs(llvm::StringRef text, llvm::ArrayRef<LPCSTR> pMsgs,
llvm::Regex RE(pMsg);
std::string reErrors;
VERIFY_IS_TRUE(RE.isValid(reErrors));
VERIFY_IS_TRUE(RE.match(text));
if (!RE.match(text)) {
WEX::Logging::Log::Comment(WEX::Common::String().Format(
L"Unable to find regex '%S' in text:\r\n%.*S", pMsg, (pEnd - pStart),
pStart));
VERIFY_IS_TRUE(false);
}
} else {
const char *pMatch = std::search(pStart, pEnd, pMsg, pMsg + strlen(pMsg));
if (pEnd == pMatch) {
@ -53,7 +58,7 @@ static bool CheckMsgs(llvm::StringRef text, llvm::ArrayRef<LPCSTR> pMsgs,
L"Unable to find '%S' in text:\r\n%.*S", pMsg, (pEnd - pStart),
pStart));
}
VERIFY_ARE_NOT_EQUAL(pEnd, pMatch);
VERIFY_IS_FALSE(pEnd == pMatch);
}
}
return true;
@ -65,6 +70,41 @@ bool CheckMsgs(const LPCSTR pText, size_t TextCount, const LPCSTR *pErrorMsgs,
llvm::ArrayRef<LPCSTR>(pErrorMsgs, errorMsgCount), bRegex);
}
static bool CheckNotMsgs(llvm::StringRef text, llvm::ArrayRef<LPCSTR> pMsgs,
bool bRegex) {
const char *pStart = !text.empty() ? text.begin() : nullptr;
const char *pEnd = !text.empty() ? text.end() : nullptr;
for (auto pMsg : pMsgs) {
if (bRegex) {
llvm::Regex RE(pMsg);
std::string reErrors;
VERIFY_IS_TRUE(RE.isValid(reErrors));
if (RE.match(text)) {
WEX::Logging::Log::Comment(WEX::Common::String().Format(
L"Unexpectedly found regex '%S' in text:\r\n%.*S", pMsg, (pEnd - pStart),
pStart));
VERIFY_IS_TRUE(false);
}
}
else {
const char *pMatch = std::search(pStart, pEnd, pMsg, pMsg + strlen(pMsg));
if (pEnd != pMatch) {
WEX::Logging::Log::Comment(WEX::Common::String().Format(
L"Unexpectedly found '%S' in text:\r\n%.*S", pMsg, (pEnd - pStart),
pStart));
}
VERIFY_IS_TRUE(pEnd == pMatch);
}
}
return true;
}
bool CheckNotMsgs(const LPCSTR pText, size_t TextCount, const LPCSTR *pErrorMsgs,
size_t errorMsgCount, bool bRegex) {
return CheckNotMsgs(llvm::StringRef(pText, TextCount),
llvm::ArrayRef<LPCSTR>(pErrorMsgs, errorMsgCount), bRegex);
}
static
bool CheckOperationResultMsgs(IDxcOperationResult *pResult,
llvm::ArrayRef<LPCSTR> pErrorMsgs,