Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/build-scripts/ci-test.bash
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ set -ex

$OSL_ROOT/bin/testshade --help

echo ; echo "Results of testshade --buildinfo:"
$OSL_ROOT/bin/testshade --buildinfo | tee -a "${GITHUB_STEP_SUMMARY:-/dev/null}"
# Note: the above both echos the --buildinfo output, and also appends it to the
# message that will be visible in the GHA summary log page so it's easy to
# see at a glance which build chain & dependencies were used across all the
# tests.
echo

echo "Parallel test ${CTEST_PARALLEL_LEVEL}"
echo "Default timeout ${CTEST_TEST_TIMEOUT}"
echo "Test exclusions '${CTEST_EXCLUSIONS}'"
Expand Down
19 changes: 18 additions & 1 deletion src/include/OSL/oslexec.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,24 @@ class OSLEXECPUBLIC ShadingSystem {
/// - `string osl:simd`, `string hw:simd` : A comma-separated list of
/// CPU hardware SIMD features. The `osl:simd` is a list of features
/// enabled when OSL was built, and `hw:simd` is a list of features
/// detected on the actual hardware at runtime.
/// detected on the actual hardware at runtime. `build:simd` is a
/// synonym for `osl:simd`.
///
/// - `string build:compiler` : The compiler used to build OSL (for
/// example, "gcc 11.2" or "Apple clang 17.0").
///
/// - `string build:platform` : The OS and CPU architecture OSL was
/// built for (for example, "Linux/x86_64" or "MacOS/ARM").
///
/// - `string build:dependencies` : A semicolon-separated list of the
/// dependencies examined when OSL was built, each as "name version",
/// or "name NONE" if it was not found or not enabled.
///
/// - `string build:batched`, `string hw:batched` : A comma-separated
/// list of batched SIMD targets (for example, "b8_AVX2,b16_AVX512").
/// The `build:batched` lists all targets that were built into OSL,
/// and `hw:batched` lists only those that the hardware we're running
/// on can execute. Both are empty if batched execution was not built.
///
/// - `string osl:cuda_version` : The version string of the Cuda version
/// OSL is using (empty string if no Cuda support was enabled at build
Expand Down
3 changes: 3 additions & 0 deletions src/liboslexec/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -540,13 +540,16 @@ foreach(batched_target ${BATCHED_TARGET_LIST})

endforeach(batched_target)

configure_file (buildopts.h.in "${CMAKE_CURRENT_BINARY_DIR}/buildopts.h" @ONLY)

add_library (${local_lib} ${lib_src})
target_include_directories (${local_lib}
PUBLIC
${CMAKE_INSTALL_FULL_INCLUDEDIR}
${IMATH_INCLUDES}
PRIVATE
"${CMAKE_SOURCE_DIR}/src/liboslcomp"
"${CMAKE_CURRENT_BINARY_DIR}"
${ROBINMAP_INCLUDES}
)

Expand Down
11 changes: 11 additions & 0 deletions src/liboslexec/buildopts.h.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright Contributors to the Open Shading Language project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage

// Build options recorded at configure time, private to liboslexec.

#pragma once

// Semicolon-separated list of "Package version" (or "Package NONE") for
// every dependency that checked_find_package looked for.
#define OSL_ALL_BUILD_DEPS_FOUND "@CFP_ALL_BUILD_DEPS_FOUND@"
128 changes: 124 additions & 4 deletions src/liboslexec/shadingsys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <OpenImageIO/thread.h>
#include <OpenImageIO/timer.h>

#include "buildopts.h"
#include "opcolor.h"

using namespace OSL;
Expand Down Expand Up @@ -1585,6 +1586,7 @@ osl_simd_caps()
if (OIIO_AVX512CD_ENABLED) caps.emplace_back ("avx512cd");
if (OIIO_AVX512BW_ENABLED) caps.emplace_back ("avx512bw");
if (OIIO_AVX512VL_ENABLED) caps.emplace_back ("avx512vl");
if (OIIO_SIMD_NEON) caps.emplace_back ("neon");
if (OIIO_FMA_ENABLED) caps.emplace_back ("fma");
if (OIIO_F16C_ENABLED) caps.emplace_back ("f16c");
// if (OIIO_POPCOUNT_ENABLED) caps.emplace_back ("popcnt");
Expand All @@ -1594,6 +1596,103 @@ osl_simd_caps()



// Return a string describing the compiler used to build OSL.
// (Modeled on oiio_build_compiler in OIIO's imageio.cpp.)
static std::string
osl_build_compiler()
{
#if OSL_INTEL_LLVM_COMPILER_VERSION
return fmtformat("Intel icx {}.{}", __clang_major__, __clang_minor__);
#elif OSL_APPLE_CLANG_VERSION
return fmtformat("Apple clang {}.{}", __clang_major__, __clang_minor__);
#elif OSL_CLANG_VERSION
return fmtformat("clang {}.{}", __clang_major__, __clang_minor__);
#elif OSL_GNUC_VERSION
return fmtformat("gcc {}.{}", __GNUC__, __GNUC_MINOR__);
#elif OSL_MSVS_VERSION
return fmtformat("MSVS {}", OSL_MSVS_VERSION);
#else
return "unknown compiler?";
#endif
}



// Return "OS/arch" for the platform OSL was built for.
// (Modeled on oiio_build_platform in OIIO's imageio.cpp.)
static std::string
osl_build_platform()
{
std::string platform;
#if defined(__linux__)
platform = "Linux";
#elif defined(__APPLE__)
platform = "MacOS";
#elif defined(_WIN32)
platform = "Windows";
#elif defined(__MINGW32__)
platform = "MinGW";
#elif defined(__FreeBSD__)
platform = "FreeBSD";
#else
platform = "UnknownOS";
#endif
platform += "/";
#if defined(__x86_64__) || defined(_M_AMD64)
platform += "x86_64";
#elif defined(__i386__) || defined(_M_IX86)
platform += "i386";
#elif defined(_M_ARM64) || defined(__aarch64__) || defined(__aarch64) \
|| defined(__ARM_ARCH)
platform += "ARM";
#else
platform += "unknown arch?";
#endif
return platform;
}



// Return a comma-separated list of the batched SIMD targets that were
// compiled into OSL (e.g. "b8_AVX2,b16_AVX512"). If hw_only is true, list
// only the ones that the hardware we're running on can execute.
static std::string
osl_batched_targets(bool hw_only)
{
std::vector<string_view> targets;
OSL_MAYBE_UNUSED auto add = [&](string_view name, TargetISA isa) {
if (!hw_only || LLVM_Util::supports_isa(isa))
targets.emplace_back(name);
};
#ifdef __OSL_SUPPORTS_b4_SSE2
add("b4_SSE2", TargetISA::x64);
#endif
#ifdef __OSL_SUPPORTS_b8_AVX
add("b8_AVX", TargetISA::AVX);
#endif
#ifdef __OSL_SUPPORTS_b8_AVX2
add("b8_AVX2", TargetISA::AVX2);
#endif
#ifdef __OSL_SUPPORTS_b8_AVX2_noFMA
add("b8_AVX2_noFMA", TargetISA::AVX2_noFMA);
#endif
#ifdef __OSL_SUPPORTS_b8_AVX512
add("b8_AVX512", TargetISA::AVX512);
#endif
#ifdef __OSL_SUPPORTS_b8_AVX512_noFMA
add("b8_AVX512_noFMA", TargetISA::AVX512_noFMA);
#endif
#ifdef __OSL_SUPPORTS_b16_AVX512
add("b16_AVX512", TargetISA::AVX512);
#endif
#ifdef __OSL_SUPPORTS_b16_AVX512_noFMA
add("b16_AVX512_noFMA", TargetISA::AVX512_noFMA);
#endif
return OIIO::Strutil::join(targets, ",");
}



bool
ShadingSystemImpl::attribute(string_view name, TypeDesc type, const void* val)
{
Expand Down Expand Up @@ -2086,19 +2185,40 @@ ShadingSystemImpl::getattribute(string_view name, TypeDesc type, void* val)
== (char*)&colorsystem().colorspace());
return true;
}
if (name == "osl:simd" && type == TypeDesc::STRING) {
if ((name == "osl:simd" || name == "build:simd")
&& type == TypeDesc::STRING) {
*(const char**)val = ustring(osl_simd_caps()).c_str();
return true;
}
if (name == "build:compiler" && type == TypeDesc::STRING) {
*(const char**)val = ustring(osl_build_compiler()).c_str();
return true;
}
if (name == "build:platform" && type == TypeDesc::STRING) {
*(const char**)val = ustring(osl_build_platform()).c_str();
return true;
}
if (name == "build:dependencies" && type == TypeDesc::STRING) {
*(const char**)val = ustring(OSL_ALL_BUILD_DEPS_FOUND).c_str();
return true;
}
if (name == "build:batched" && type == TypeDesc::STRING) {
*(const char**)val = ustring(osl_batched_targets(false)).c_str();
return true;
}
if (name == "hw:batched" && type == TypeDesc::STRING) {
*(const char**)val = ustring(osl_batched_targets(true)).c_str();
return true;
}
if (name == "hw:simd" && type == TypeDesc::STRING) {
return OIIO::getattribute("hw:string", type, val);
return OIIO::getattribute("hw:simd", type, val);
}
if (name == "osl:cuda_version" && type == TypeDesc::STRING) {
*(const char**)val = OSL_CUDA_VERSION;
*(const char**)val = ustring(OSL_CUDA_VERSION).c_str();
return true;
}
if (name == "osl:optix_version" && type == TypeDesc::STRING) {
*(const char**)val = OSL_OPTIX_VERSION;
*(const char**)val = ustring(OSL_OPTIX_VERSION).c_str();
return true;
}
if (name == "osl:dependencies" && type == TypeDesc::STRING) {
Expand Down
94 changes: 94 additions & 0 deletions src/testshade/testshade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,97 @@ print_info()



// Print the build toolchain, back ends, dependencies, and the hardware
// we're running on. Almost all of it comes from ShadingSystem attributes.
static void
print_build_info()
{
using OIIO::Strutil::fmt::format;
int columns = OIIO::Sysutil::terminal_columns() - 2;
auto print_wrapped = [&](const std::string& s) {
OIIO::print("{}\n", OIIO::Strutil::wordwrap(s, columns, 4));
};

SimpleRenderer rend;
auto texturesys = TextureSystem::create();
#if OIIO_TEXTURESYSTEM_CREATE_SHARED
ShadingSystem ss(&rend, texturesys.get(), &rend.errhandler());
#else
ShadingSystem ss(&rend, texturesys, &rend.errhandler());
#endif
auto ss_string_attr = [&](string_view name) {
ustring val;
ss.getattribute(name, val);
return val.string();
};

std::string platform = ss_string_attr("build:platform");
print_wrapped(format("OSL {} | {}", OSL_LIBRARY_VERSION_STRING, platform));
print_wrapped(format(" Build compiler: {} | C++{}/{}",
ss_string_attr("build:compiler"), OSL_BUILD_CPP,
__cplusplus));
std::string simd = ss_string_attr("build:simd");
print_wrapped(format(" HW features enabled at build: {}",
simd.size() ? simd : std::string("no SIMD")));

// Back ends: the single-point CPU path is always present; batched and
// OptiX only if they were enabled when OSL was built.
std::vector<std::string> backends;
size_t slash = platform.find('/');
backends.push_back(format("{} single", slash != std::string::npos
? platform.substr(slash + 1)
: platform));
std::string batched = ss_string_attr("build:batched");
std::string hw_batched = ss_string_attr("hw:batched");
if (batched.size()) {
if (hw_batched == batched)
backends.push_back("batched " + batched);
else if (hw_batched.empty())
backends.push_back(
format("batched {} (none usable on this HW)", batched));
else
backends.push_back(
format("batched {} (this HW: {})", batched, hw_batched));
}
if (ss_string_attr("osl:optix_version").size())
backends.push_back("OptiX");
print_wrapped(" Back ends: " + OIIO::Strutil::join(backends, ", "));

// Note if the OIIO we're running with differs from the one we built
// against.
std::vector<std::string> deps;
std::string alldeps = ss_string_attr("build:dependencies");
std::string oiio_runtime = OIIO::get_string_attribute("version");
for (auto dep : OIIO::Strutil::splitsv(alldeps, ";")) {
std::string d(dep);
if (OIIO::Strutil::starts_with(dep, "OpenImageIO ")
&& oiio_runtime != OIIO_VERSION_STRING)
d += format(" (runtime {})", oiio_runtime);
deps.push_back(d);
}
print_wrapped(" Dependencies: " + OIIO::Strutil::join(deps, ", "));

std::string hw = format(" Running on: {} cores, {:.1f} GB, SIMD {}",
OIIO::Sysutil::hardware_concurrency(),
OIIO::Sysutil::physical_memory() / double(1 << 30),
ss_string_attr("hw:simd"));
#if OSL_USE_OPTIX
int ndevices = 0, driver = 0;
if (cudaGetDeviceCount(&ndevices) == cudaSuccess && ndevices > 0) {
cudaDeviceProp prop;
cudaDriverGetVersion(&driver);
if (cudaGetDeviceProperties(&prop, 0) == cudaSuccess)
hw += format(", GPU {} (CUDA driver {}.{})", prop.name,
driver / 1000, (driver % 1000) / 10);
} else {
hw += ", no CUDA device";
}
#endif
print_wrapped(hw);
}



static void
getargs(int argc, const char* argv[])
{
Expand All @@ -715,6 +806,9 @@ getargs(int argc, const char* argv[])
.action([&](cspan<const char*> argv){ stash_shader_arg(argv); });
ap.arg("-v", &verbose)
.help("Verbose messages");
ap.arg("--buildinfo")
.help("Print OSL build information, then exit")
.action([&](cspan<const char*>){ print_build_info(); exit(EXIT_SUCCESS); });
ap.arg("-t %d:NTHREADS", &num_threads)
.help("Set thread count (default = 0: auto-detect #cores)");
ap.arg("--optix", &use_optix)
Expand Down
Loading