Skip to content

Commit 7e93e81

Browse files
jsmall-zzzT. Foley
and
T. Foley
authored
Downstream compiler location fix. (shader-slang#1866)
* #include an absolute path didn't work - because paths were taken to always be relative. * Move logic to determine how to load a downstream shared library to DownstreamCompilerUtil::loadSharedLibrary. Handle if the given path is directory or a file. * Improve comment. * Special handling for a downstream compiler loading SharedLibrary detection - take into account filename may be different. * Handle cases if path is set but paths can't be determined. * Fix typo. Co-authored-by: T. Foley <tfoleyNV@users.noreply.github.com>
1 parent b699a36 commit 7e93e81

5 files changed

+136
-44
lines changed

source/compiler-core/slang-downstream-compiler.cpp

+121
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,125 @@ const DownstreamCompiler::Desc& DownstreamCompilerUtil::getCompiledWithDesc()
737737
outFuncs[int(SLANG_PASS_THROUGH_GLSLANG)] = &GlslangDownstreamCompilerUtil::locateCompilers;
738738
}
739739

740+
static String _getParentPath(const String& path)
741+
{
742+
// If we can get the canonical path, we'll do that before getting the parent
743+
String canonicalPath;
744+
if (SLANG_SUCCEEDED(Path::getCanonical(path, canonicalPath)))
745+
{
746+
return Path::getParentDirectory(canonicalPath);
747+
}
748+
else
749+
{
750+
return Path::getParentDirectory(path);
751+
}
752+
}
753+
754+
static SlangResult _findPaths(const String& path, const char* libraryName, String& outParentPath, String& outLibraryPath)
755+
{
756+
// Try to determine what the path is by looking up the path type
757+
SlangPathType pathType;
758+
if (SLANG_SUCCEEDED(Path::getPathType(path, &pathType)))
759+
{
760+
if (pathType == SLANG_PATH_TYPE_DIRECTORY)
761+
{
762+
outParentPath = path;
763+
outLibraryPath = Path::combine(outParentPath, libraryName);
764+
}
765+
else
766+
{
767+
SLANG_ASSERT(pathType == SLANG_PATH_TYPE_FILE);
768+
769+
outParentPath = _getParentPath(path);
770+
outLibraryPath = path;
771+
}
772+
773+
return SLANG_OK;
774+
}
775+
776+
// If this failed the path could be to a shared library, but we may need to convert to the shared library filename first
777+
const String sharedLibraryFilePath = SharedLibrary::calcPlatformPath(path.getUnownedSlice());
778+
if (SLANG_SUCCEEDED(Path::getPathType(sharedLibraryFilePath, &pathType)) && pathType == SLANG_PATH_TYPE_FILE)
779+
{
780+
// We pass in the shared library path, as canonical paths can sometimes only apply to pre-existing objects.
781+
outParentPath = _getParentPath(sharedLibraryFilePath);
782+
// The original path should work as is for the SharedLibrary load. Notably we don't use the sharedLibraryFilePath
783+
// as this is the wrong name to do a SharedLibrary load with.
784+
outLibraryPath = path;
785+
786+
return SLANG_OK;
787+
}
788+
789+
return SLANG_FAIL;
790+
}
791+
792+
/* static */SlangResult DownstreamCompilerUtil::loadSharedLibrary(const String& path, ISlangSharedLibraryLoader* loader, const char*const* dependentNames, const char* inLibraryName, ComPtr<ISlangSharedLibrary>& outSharedLib)
793+
{
794+
String parentPath;
795+
String libraryPath;
796+
797+
// If a path is passed in lets, try and determine what kind of path it is.
798+
if (path.getLength())
799+
{
800+
if (SLANG_FAILED(_findPaths(path, inLibraryName, parentPath, libraryPath)))
801+
{
802+
// We have a few scenarios here.
803+
// 1) The path could be the shared library/dll filename, that will be found through some operating system mechanism
804+
// 2) That the shared library is *NOT* on the filesystem directly (the loader does something different)
805+
// 3) Permissions or some other mechanism stops the lookup from working
806+
807+
// We should probably assume that the path means something, else why set it.
808+
// It's probably less likely that it is a directory that we can't detect - as if it's a directory as part of an app
809+
// it's permissions should allow detection, or be made to allow it.
810+
811+
// All this being the case we should probably assume that it is the shared library name.
812+
libraryPath = path;
813+
814+
// Attempt to get a parent. If there isn't one this will be empty, which will mean it will be ignored, which is probably
815+
// what we want if path is just a shared library name
816+
parentPath = Path::getParentDirectory(libraryPath);
817+
}
818+
}
819+
820+
// Keep all dependent libs in scope, before we load the library we want
821+
List<ComPtr<ISlangSharedLibrary>> dependentLibs;
822+
823+
// Try to load any dependent libs from the parent path
824+
if (dependentNames)
825+
{
826+
for (const char*const* cur = dependentNames; *cur; ++cur)
827+
{
828+
const char* dependentName = *cur;
829+
ComPtr<ISlangSharedLibrary> lib;
830+
if (parentPath.getLength())
831+
{
832+
String dependentPath = Path::combine(parentPath, dependentName);
833+
loader->loadSharedLibrary(dependentPath.getBuffer(), lib.writeRef());
834+
}
835+
else
836+
{
837+
loader->loadSharedLibrary(dependentName, lib.writeRef());
838+
}
839+
840+
if (lib)
841+
{
842+
dependentLibs.add(lib);
843+
}
844+
}
845+
}
846+
847+
if (libraryPath.getLength())
848+
{
849+
// If we hare a library path use that
850+
return loader->loadSharedLibrary(libraryPath.getBuffer(), outSharedLib.writeRef());
851+
}
852+
else
853+
{
854+
// Else just use the name that was passed in.
855+
return loader->loadSharedLibrary(inLibraryName, outSharedLib.writeRef());
856+
}
857+
}
858+
740859
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerSet !!!!!!!!!!!!!!!!!!!!!!*/
741860

742861
void DownstreamCompilerSet::getCompilerDescs(List<DownstreamCompiler::Desc>& outCompilerDescs) const
@@ -813,4 +932,6 @@ void DownstreamCompilerSet::addCompiler(DownstreamCompiler* compiler)
813932
}
814933
}
815934

935+
936+
816937
}

source/compiler-core/slang-downstream-compiler.h

+8
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,14 @@ struct DownstreamCompilerUtil: public DownstreamCompilerBaseUtil
512512
static void updateDefaults(DownstreamCompilerSet* set);
513513

514514
static void setDefaultLocators(DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]);
515+
516+
/// Attempts to determine what 'path' is and load appropriately. Is it a path to a shared library? Is it a directory holding the libraries?
517+
/// Some downstream shared libraries need other shared libraries to be loaded before the main shared library, such that they are in the same directory
518+
/// otherwise the shared library could come from some unwanted location.
519+
/// dependentNames names shared libraries which should be attempted to be loaded in the path of the main shared library.
520+
/// The list is optional (nullptr can be passed in), and the list is terminated by nullptr.
521+
static SlangResult loadSharedLibrary(const String& path, ISlangSharedLibraryLoader* loader, const char*const* dependantNames, const char* libraryName, ComPtr<ISlangSharedLibrary>& outSharedLib);
522+
515523
};
516524

517525
}

source/compiler-core/slang-dxc-compiler.cpp

+3-24
Original file line numberDiff line numberDiff line change
@@ -397,30 +397,9 @@ SlangResult DXCDownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarg
397397
{
398398
ComPtr<ISlangSharedLibrary> library;
399399

400-
// If the user supplies a path to their preferred version of DXC
401-
// we just use this.
402-
if (path.getLength() != 0)
403-
{
404-
// We *assume* path is the path to d3dcompiler.
405-
ComPtr<ISlangSharedLibrary> dxil;
406-
407-
// Attempt to load dxil from same path that d3dcompiler is located
408-
const String parentPath = Path::getParentDirectory(path);
409-
if (parentPath.getLength())
410-
{
411-
String dxilPath = Path::combine(parentPath, "dxil");
412-
// Try to load dxil along this path first
413-
// If it fails - then DXC may load from a different place and thats ok.
414-
loader->loadSharedLibrary(dxilPath.getBuffer(), dxil.writeRef());
415-
}
416-
417-
SLANG_RETURN_ON_FAIL(loader->loadSharedLibrary(path.getBuffer(), library.writeRef()));
418-
}
419-
else
420-
{
421-
SLANG_RETURN_ON_FAIL(loader->loadSharedLibrary("dxcompiler", library.writeRef()));
422-
}
423-
400+
const char* dependentNames[] = {"dxil", nullptr } ;
401+
SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary(path, loader, dependentNames, "dxcompiler", library));
402+
424403
SLANG_ASSERT(library);
425404
if (!library)
426405
{

source/compiler-core/slang-fxc-compiler.cpp

+1-10
Original file line numberDiff line numberDiff line change
@@ -326,16 +326,7 @@ SlangResult FXCDownstreamCompiler::disassemble(SlangCompileTarget sourceBlobTarg
326326
{
327327
ComPtr<ISlangSharedLibrary> library;
328328

329-
// If the user supplies a path to their preferred version of FXC,
330-
// we just use this.
331-
if (path.getLength() != 0)
332-
{
333-
SLANG_RETURN_ON_FAIL(loader->loadSharedLibrary(path.getBuffer(), library.writeRef()));
334-
}
335-
else
336-
{
337-
SLANG_RETURN_ON_FAIL(loader->loadSharedLibrary("d3dcompiler_47", library.writeRef()));
338-
}
329+
SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "d3dcompiler_47", library));
339330

340331
SLANG_ASSERT(library);
341332
if (!library)

source/compiler-core/slang-glslang-compiler.cpp

+3-10
Original file line numberDiff line numberDiff line change
@@ -256,20 +256,13 @@ SlangResult GlslangDownstreamCompiler::disassemble(SlangCompileTarget sourceBlob
256256
// On unix systems we need to ensure pthread is loaded first.
257257
// TODO(JS):
258258
// There is an argument that this should be performed through the loader....
259+
// NOTE! We don't currently load through a dependent library, as it is *assumed* something as core as 'ptheads'
260+
// isn't going to be distributed with the shader compiler.
259261
ComPtr<ISlangSharedLibrary> pthreadLibrary;
260262
DefaultSharedLibraryLoader::load(loader, path, "pthread", pthreadLibrary.writeRef());
261263
#endif
262264

263-
// If the user supplies a path to their preferred version of FXC,
264-
// we just use this.
265-
if (path.getLength() != 0)
266-
{
267-
SLANG_RETURN_ON_FAIL(loader->loadSharedLibrary(path.getBuffer(), library.writeRef()));
268-
}
269-
else
270-
{
271-
SLANG_RETURN_ON_FAIL(loader->loadSharedLibrary("slang-glslang", library.writeRef()));
272-
}
265+
SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-glslang", library));
273266

274267
SLANG_ASSERT(library);
275268
if (!library)

0 commit comments

Comments
 (0)