Commit 68850e52 authored by Tim Thirion's avatar Tim Thirion

Choose graphics driver with command line switch or config file

parent fcf21541
......@@ -91,7 +91,7 @@
# )
#
###############################################################################
include(vtkForwardingExecutable)
include(pvForwardingExecutable)
FUNCTION(build_paraview_client BPC_NAME)
PV_PARSE_ARGUMENTS(BPC
......@@ -291,7 +291,7 @@ FUNCTION(build_paraview_client BPC_NAME)
SET (PV_EXE_LIST ${BPC_NAME})
# needed to set up shared forwarding correctly.
vtk_add_executable_with_forwarding2(pv_exe_suffix
pv_add_executable_with_forwarding2(pv_exe_suffix
"${PARAVIEW_LIBRARY_DIRS}"
"../${PARAVIEW_INSTALL_LIB_DIR}"
"${BPC_INSTALL_LIBRARY_DIR}"
......
......@@ -412,12 +412,13 @@ endmacro()
#------------------------------------------------------------------------------
# replacement for vtk-add executable that also adds the install rules.
#------------------------------------------------------------------------------
include(vtkForwardingExecutable)
include(pvForwardingExecutable)
function(pv_add_executable name)
set (VTK_EXE_SUFFIX)
if(UNIX AND VTK_BUILD_FORWARDING_EXECUTABLES)
vtk_add_executable_with_forwarding(VTK_EXE_SUFFIX ${name} ${ARGN})
set(PV_INSTALL_LIBRARY_DIR ${VTK_INSTALL_LIBRARY_DIR})
pv_add_executable_with_forwarding(VTK_EXE_SUFFIX ${name} ${ARGN})
set_property(GLOBAL APPEND PROPERTY VTK_TARGETS ${name})
else()
add_executable(${name} ${ARGN})
......
......@@ -23,7 +23,291 @@ PURPOSE. See the above copyright notice for more information.
#include <vtksys/SharedForward.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
/* Query functions for AVX vs AVX2. */
#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300)
#include <immintrin.h>
int avx_support_level()
{
if (_may_i_use_cpu_feature(_FEATURE_AVX2) > 0)
return 2;
if (_may_i_use_cpu_feature(_FEATURE_AVX) > 0)
return 1;
return 0;
}
#if 0
int check_4th_gen_intel_core_features()
{
const int the_4th_gen_features =
(_FEATURE_AVX2 | _FEATURE_FMA | _FEATURE_BMI | _FEATURE_LZCNT | _FEATURE_MOVBE);
return _may_i_use_cpu_feature( the_4th_gen_features );
}
#endif
#else /* non-Intel compiler */
#include <stdint.h>
#if defined(_MSC_VER)
# include <intrin.h>
#endif
void run_cpuid(uint32_t eax, uint32_t ecx, uint32_t* abcd)
{
#if defined(_MSC_VER)
__cpuidex(abcd, eax, ecx);
#else
uint32_t ebx, edx;
# if defined( __i386__ ) && defined ( __PIC__ )
/* in case of PIC under 32-bit EBX cannot be clobbered */
__asm__ ("movl %%ebx, %%edi \n\t cpuid \n\t xchgl %%ebx, %%edi" : "=D" (ebx),
# else
__asm__ ("cpuid" : "+b" (ebx),
# endif
"+a" (eax), "+c" (ecx), "=d" (edx) );
abcd[0] = eax; abcd[1] = ebx; abcd[2] = ecx; abcd[3] = edx;
#endif
}
int check_xcr0_ymm()
{
uint32_t xcr0;
#if defined(_MSC_VER)
xcr0 = (uint32_t)_xgetbv(0); /* min VS2010 SP1 compiler is required */
#else
__asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
#endif
return ((xcr0 & 6) == 6); /* checking if xmm and ymm state are enabled in XCR0 */
}
int check_4th_gen_intel_core_features()
{
uint32_t abcd[4];
uint32_t fma_movbe_osxsave_mask = ((1 << 12) | (1 << 22) | (1 << 27));
uint32_t avx2_bmi12_mask = (1 << 5) | (1 << 3) | (1 << 8);
/* CPUID.(EAX=01H, ECX=0H):ECX.FMA[bit 12]==1 &&
CPUID.(EAX=01H, ECX=0H):ECX.MOVBE[bit 22]==1 &&
CPUID.(EAX=01H, ECX=0H):ECX.OSXSAVE[bit 27]==1 */
run_cpuid( 1, 0, abcd );
if ( (abcd[2] & fma_movbe_osxsave_mask) != fma_movbe_osxsave_mask )
return 0;
if ( ! check_xcr0_ymm() )
return 0;
/* CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]==1 &&
CPUID.(EAX=07H, ECX=0H):EBX.BMI1[bit 3]==1 &&
CPUID.(EAX=07H, ECX=0H):EBX.BMI2[bit 8]==1 */
run_cpuid( 7, 0, abcd );
if ( (abcd[1] & avx2_bmi12_mask) != avx2_bmi12_mask )
return 0;
/* CPUID.(EAX=80000001H):ECX.LZCNT[bit 5]==1 */
run_cpuid( 0x80000001, 0, abcd );
if ( (abcd[2] & (1 << 5)) == 0)
return 0;
return 1;
}
int avx_support_level()
{
if (check_4th_gen_intel_core_features())
return 2;
/* Need way to detect AVX on non-Intel compilers */
// return 1
return 0;
}
#endif /* non-Intel compiler */
const char *determine_mesa_version()
{
switch (avx_support_level())
{
case 2: return "mesa-swr-avx2";
case 1: return "mesa-swr-avx";
}
return "mesa-llvm";
}
int get_driver_cache_path(const char *this_exe_path, char *driver_cache_path)
{
const char *home = getenv("HOME");
if (!home)
{
home = getpwuid(getuid())->pw_dir;
}
strncpy(driver_cache_path, home, strlen(home));
strcat(driver_cache_path, "/");
strcat(driver_cache_path, ".paraview");
return 1;
// Get directory containing true paraview executable.
#if 0
char self_path[KWSYS_SHARED_FORWARD_MAXPATH] = { 0 };
char throwaway_ldpath[KWSYS_SHARED_FORWARD_MAXPATH] = { 0 };
char exe[KWSYS_SHARED_FORWARD_MAXPATH] = { 0 };
kwsys_shared_forward_self_path(this_exe_path, self_path);
kwsys_shared_forward_get_settings(self_path, throwaway_ldpath, exe);
char driver_install_path[KWSYS_SHARED_FORWARD_MAXPATH] = { 0 };
char *last_slash = strrchr(exe, '/');
if (last_slash)
{
strncpy(driver_install_path, exe, last_slash - exe + 1);
strcat(driver_cache_path, driver_install_path);
strcat(driver_cache_path, "pv_driver");
return 1;
}
return 0;
#endif
}
int append_driver_to_ldpath(const char *this_exe_path, const char *driver)
{
char self_path[KWSYS_SHARED_FORWARD_MAXPATH] = { 0 };
char throwaway_ldpath[KWSYS_SHARED_FORWARD_MAXPATH] = { 0 };
char exe[KWSYS_SHARED_FORWARD_MAXPATH] = { 0 };
char cache_path[KWSYS_SHARED_FORWARD_MAXPATH] = { 0 };
FILE *cache = NULL;
// Use default native driver, so don't update LD_LIBRARY_PATH
if (!driver || driver && driver[0] == '\0')
{
return 0;
}
// Check for a newline in the driver name
char *newline = strchr(driver, '\n');
if (newline)
{
*newline = '\0';
}
kwsys_shared_forward_self_path(this_exe_path, self_path);
kwsys_shared_forward_get_settings(self_path, throwaway_ldpath, exe);
char driver_install_path[KWSYS_SHARED_FORWARD_MAXPATH] = { 0 };
char *last_slash = strrchr(exe, '/');
if (last_slash)
{
strncpy(driver_install_path, exe, last_slash - exe + 1);
strcat(kwsys_shared_forward_ldpath, driver_install_path);
strcat(kwsys_shared_forward_ldpath, driver);
strcat(kwsys_shared_forward_ldpath, kwsys_shared_forward_path_sep);
// Checks
//fprintf(stdout, "driver_install_path = %s\n", driver_install_path);
//fprintf(stdout, "kwsys_shared_forward_ldpath = %s\n",
// kwsys_shared_forward_ldpath);
return 1;
}
return 0;
}
#define MAX_DRIVER_CHOICE 32
int main(int argc, char** argv)
{
return vtksys_shared_forward_to_real(argc, argv);
int i = 0;
int true_argc = 0;
int true_i = 0;
char **true_argv = malloc(argc * sizeof(char*));
int result = 0;
FILE *driver_cache = NULL;
int driver_changed = 0;
char driver_choice[MAX_DRIVER_CHOICE] = { 0 };
char driver_cache_path[KWSYS_SHARED_FORWARD_MAXPATH] = { 0 };
// See if there's a cached choice already
get_driver_cache_path(argv[0], driver_cache_path);
driver_cache = fopen(driver_cache_path, "r");
if (driver_cache)
{
fgets(driver_choice, sizeof(driver_choice), driver_cache);
fclose(driver_cache);
}
// Check for driver specification; forward all other args
for (; i < argc; ++i)
{
if (strcmp(argv[i], "--native") == 0)
{
driver_choice[0] = '\0';
driver_changed = 1;
}
else if (strcmp(argv[i], "--mesa") == 0)
{
strncpy(driver_choice, determine_mesa_version(), MAX_DRIVER_CHOICE);
driver_changed = 1;
}
else if (strcmp(argv[i], "--mesa-llvm") == 0 ||
strcmp(argv[i], "--mesa-swr-avx") == 0 ||
strcmp(argv[i], "--mesa-swr-avx2") == 0)
{
strncpy(driver_choice, argv[i] + 2, MAX_DRIVER_CHOICE);
driver_changed = 1;
}
else
{
true_argc++;
true_argv[true_i++] = argv[i];
}
}
// Update the LD_LIBRARY_PATH
append_driver_to_ldpath(argv[0], driver_choice);
// Only read the config file
#if 0
// Update the cache if we changed driver
if (driver_changed)
{
driver_cache = fopen(driver_cache_path, "w");
if (driver_cache)
{
fprintf(driver_cache, "%s", driver_choice);
fclose(driver_cache);
}
else
{
fprintf(stderr, "%s", "Could not write driver cache.\n"
"Run again with super user permissions.\n");
}
}
#endif
// Check original args vs. forwarded args
#if 0
// Original
printf("%d original args:\n", argc);
for (i = 0; i < argc; ++i)
{
printf("\t%s\n", argv[i]);
}
// Forwarded
printf("%d forwarded args:\n", true_argc);
for (i = 0; i < true_argc; ++i)
{
printf("\t%s\n", true_argv[i]);
}
#endif
result = vtksys_shared_forward_to_real(true_argc, true_argv);
free(true_argv);
return result;
}
#----------------------------------------------------------------------------
# Function for adding an executable with support for shared forwarding.
# Typically, one just uses ADD_EXECUTABLE to add an executable target. However
# on linuxes when rpath is off, and shared libararies are on, to over come the
# need for setting the LD_LIBRARY_PATH, we use shared-forwarding. This macro
# makes it easier to employ shared forwarding if needed.
# ARGUMENTS:
# out_real_exe_suffix -- (out) suffix to be added to the exe-target to locate the
# real executable target when shared forwarding is employed.
# This is empty when shared forwarding is not needed.
# exe_name -- (in) exe target name i.e. the first argument to
# ADD_EXECUTABLE.
# Any remaining arguments are simply passed on to the ADD_EXECUTABLE call.
# While writing install rules for this executable. One typically does the
# following.
# install(TARGETS exe_name
# DESTINATION "bin"
# COMPONENT Runtime)
# if(vtk_exe_suffix)
# # Shared forwarding enabled.
# install(TARGETS exe_name${out_real_exe_suffix}
# DESTINATION "lib"
# COMPONENT Runtime)
# endif()
#----------------------------------------------------------------------------
function(pv_add_executable_with_forwarding
out_real_exe_suffix
exe_name)
if(NOT DEFINED PV_INSTALL_LIBRARY_DIR)
message(FATAL_ERROR
"PV_INSTALL_LIBRARY_DIR variable must be set before calling add_executable_with_forwarding")
endif()
pv_add_executable_with_forwarding2(out_var "" ""
${PV_INSTALL_LIBRARY_DIR}
${exe_name} ${ARGN})
set(${out_real_exe_suffix} "${out_var}" PARENT_SCOPE)
endfunction()
#----------------------------------------------------------------------------
function(pv_add_executable_with_forwarding2
out_real_exe_suffix
extra_build_dirs
extra_install_dirs
install_lib_dir
exe_name)
set(mac_bundle)
if(APPLE)
set(largs ${ARGN})
list(FIND largs "MACOSX_BUNDLE" mac_bundle_index)
if(mac_bundle_index GREATER -1)
set(mac_bundle TRUE)
endif()
endif()
set(PV_EXE_SUFFIX)
if(BUILD_SHARED_LIBS AND NOT mac_bundle)
if(NOT WIN32)
set(exe_output_path ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(exe_output_path ${CMAKE_BINARY_DIR})
endif()
set(PV_EXE_SUFFIX -launcher)
set(PV_FORWARD_DIR_BUILD "${exe_output_path}")
set(PV_FORWARD_DIR_INSTALL "../${install_lib_dir}")
set(PV_FORWARD_PATH_BUILD "\"${PV_FORWARD_DIR_BUILD}\"")
set(PV_FORWARD_PATH_INSTALL "\"${PV_FORWARD_DIR_INSTALL}\"")
foreach(dir ${extra_build_dirs})
set(PV_FORWARD_PATH_BUILD "${PV_FORWARD_PATH_BUILD},\"${dir}\"")
endforeach()
foreach(dir ${extra_install_dirs})
set(PV_FORWARD_PATH_INSTALL "${PV_FORWARD_PATH_INSTALL},\"${dir}\"")
endforeach()
set(PV_FORWARD_EXE ${exe_name})
configure_file(
${ParaView_CMAKE_DIR}/pv-forward.c.in
${CMAKE_CURRENT_BINARY_DIR}/${exe_name}-forward.c
@ONLY)
add_executable(${exe_name}${PV_EXE_SUFFIX}
${CMAKE_CURRENT_BINARY_DIR}/${exe_name}-forward.c)
set_target_properties(${exe_name}${PV_EXE_SUFFIX} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/launcher)
set_target_properties(${exe_name}${PV_EXE_SUFFIX} PROPERTIES
OUTPUT_NAME ${exe_name})
add_dependencies(${exe_name}${PV_EXE_SUFFIX} ${exe_name})
endif()
endif()
add_executable(${exe_name} ${ARGN})
set(${out_real_exe_suffix} "${PV_EXE_SUFFIX}" PARENT_SCOPE)
endfunction()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment