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:
Родитель
e835567cd2
Коммит
8db08cb21e
|
@ -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
|
||||
|
|
|
@ -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 ¶m : 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 ¶m : ShaderF->args()) {
|
||||
for (Argument ¶m : Orig->args()) {
|
||||
vmap[¶m] = (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 ¶mAnnot =
|
||||
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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче