swr: allow a single swr architecture to be builtin

Part 2 of 2 (part 1 is autoconf changes, part 2 is C++ changes)

When only a single SWR architecture is being used, this allows that
architecture to be builtin rather than as a separate libswrARCH.so that
gets loaded via dlopen.  Since there are now several different code
paths for each detected CPU architecture, the log output is also
adjusted to convey where the backend is getting loaded from.

This allows SWR to be used for static mesa builds which are still
important for large HPC environments where shared libraries can impose
unacceptable application startup times as hundreds of thousands of copies
of the libs are loaded from a shared parallel filesystem.

Based on an initial implementation by Tim Rowley.

v2: Refactor repetitive preprocessor checks to reduce code duplication
v3: Formatting changes per Bruce C. Also delay screen creation until end
    to avoid leaks when failure conditions are hit.

Signed-off-by: Chuck Atkins <chuck.atkins@kitware.com>
Reviewed-by: Bruce Cherniak <bruce.cherniak@intel.com>
CC: Tim Rowley <timothy.o.rowley@intel.com>
Reviewed-by: Bruce Cherniak <bruce.cherniak@intel.com>
This commit is contained in:
Chuck Atkins 2018-01-18 14:57:58 -05:00 committed by George Kyriazis
parent 2ed8b6f827
commit a4be2bcee2

View file

@ -28,81 +28,95 @@
#include <stdio.h> #include <stdio.h>
// Helper function to resolve the backend filename based on architecture
inline void get_swr_arch_filename(const char arch[], char filename[])
{
#ifdef HAVE_SWR_BUILTIN
strcpy(filename , "builtin");
#else
sprintf(filename, "%sswr%s%s", UTIL_DL_PREFIX, arch, UTIL_DL_EXT);
#endif
}
struct pipe_screen * struct pipe_screen *
swr_create_screen(struct sw_winsys *winsys) swr_create_screen(struct sw_winsys *winsys)
{ {
char filename[256] = { 0 }; char filename[256] = { 0 };
fprintf(stderr, "SWR detected "); bool found = false;
bool is_knl = false;
util_dl_library *pLibrary = nullptr; PFNSwrGetInterface pfnSwrGetInterface = nullptr;
util_cpu_detect(); util_cpu_detect();
bool is_knl = false; if (!found && util_cpu_caps.has_avx512f && util_cpu_caps.has_avx512er) {
fprintf(stderr, "SWR detected KNL instruction support ");
if (!strlen(filename) && #ifndef HAVE_SWR_KNL
util_cpu_caps.has_avx512f && util_cpu_caps.has_avx512er) { fprintf(stderr, "(skipping not built).\n");
#if HAVE_SWR_KNL #else
fprintf(stderr, "KNL "); get_swr_arch_filename("KNL", filename);
sprintf(filename, "%s%s%s", UTIL_DL_PREFIX, "swrKNL", UTIL_DL_EXT); found = true;
is_knl = true; is_knl = true;
#else
fprintf(stderr, "KNL (not built) ");
#endif #endif
} }
if (!strlen(filename) && if (!found && util_cpu_caps.has_avx512f && util_cpu_caps.has_avx512bw) {
util_cpu_caps.has_avx512f && util_cpu_caps.has_avx512bw) { fprintf(stderr, "SWR detected SKX instruction support ");
#if HAVE_SWR_SKX #ifndef HAVE_SWR_SKX
fprintf(stderr, "SKX "); fprintf(stderr, "(skipping not built).\n");
sprintf(filename, "%s%s%s", UTIL_DL_PREFIX, "swrSKX", UTIL_DL_EXT);
#else #else
fprintf(stderr, "SKX (not built) "); get_swr_arch_filename("SKX", filename);
found = true;
#endif #endif
} }
if (!strlen(filename) && util_cpu_caps.has_avx2) { if (!found && util_cpu_caps.has_avx2) {
#if HAVE_SWR_AVX2 fprintf(stderr, "SWR detected AVX2 instruction support ");
fprintf(stderr, "AVX2 "); #ifndef HAVE_SWR_AVX2
sprintf(filename, "%s%s%s", UTIL_DL_PREFIX, "swrAVX2", UTIL_DL_EXT); fprintf(stderr, "(skipping not built).\n");
#else #else
fprintf(stderr, "AVX2 (not built) "); get_swr_arch_filename("AVX2", filename);
found = true;
#endif #endif
} }
if (!strlen(filename) && util_cpu_caps.has_avx) { if (!found && util_cpu_caps.has_avx) {
#if HAVE_SWR_AVX fprintf(stderr, "SWR detected AVX instruction support ");
fprintf(stderr, "AVX "); #ifndef HAVE_SWR_AVX
sprintf(filename, "%s%s%s", UTIL_DL_PREFIX, "swrAVX", UTIL_DL_EXT); fprintf(stderr, "(skipping not built).\n");
#else #else
fprintf(stderr, "AVX (not built) "); get_swr_arch_filename("AVX", filename);
found = true;
#endif #endif
} }
if (!strlen(filename)) { if (!found) {
fprintf(stderr, "- no appropriate swr architecture library. Aborting!\n"); fprintf(stderr, "SWR could not detect a supported CPU architecture.\n");
exit(-1); exit(-1);
} else {
fprintf(stderr, "\n");
} }
pLibrary = util_dl_open(filename); fprintf(stderr, "(using %s).\n", filename);
#ifdef HAVE_SWR_BUILTIN
pfnSwrGetInterface = SwrGetInterface;
#else
util_dl_library *pLibrary = util_dl_open(filename);
if (!pLibrary) { if (!pLibrary) {
fprintf(stderr, "SWR library load failure: %s\n", util_dl_error()); fprintf(stderr, "SWR library load failure: %s\n", util_dl_error());
exit(-1); exit(-1);
} }
util_dl_proc pApiProc = util_dl_get_proc_address(pLibrary, "SwrGetInterface"); util_dl_proc pApiProc = util_dl_get_proc_address(pLibrary, "SwrGetInterface");
if (!pApiProc) { if (!pApiProc) {
fprintf(stderr, "SWR library search failure: %s\n", util_dl_error()); fprintf(stderr, "SWR library search failure: %s\n", util_dl_error());
exit(-1); exit(-1);
} }
pfnSwrGetInterface = (PFNSwrGetInterface)pApiProc;
#endif
struct pipe_screen *screen = swr_create_screen_internal(winsys); struct pipe_screen *screen = swr_create_screen_internal(winsys);
swr_screen(screen)->pfnSwrGetInterface = (PFNSwrGetInterface)pApiProc;
swr_screen(screen)->is_knl = is_knl; swr_screen(screen)->is_knl = is_knl;
swr_screen(screen)->pfnSwrGetInterface = pfnSwrGetInterface;
return screen; return screen;
} }