Source browser
examples/runner.hpp
Read the complete file below or download its original bytes. Line numbers provide stable links to a declaration or processing step.
File fingerprint
1#ifndef SHDR_EXAMPLES_RUNNER_HPP // Open this include guard or optional feature branch.
2#define SHDR_EXAMPLES_RUNNER_HPP // Define SHDR_EXAMPLES_RUNNER_HPP for the declarations that follow.
3
4#include "shdr.h" // Include shdr.h declarations.
5#include <cmath> // Include cmath declarations.
6#include <iostream> // Include iostream declarations.
7#include <memory> // Include memory declarations.
8#include <random> // Include random declarations.
9#include <stdexcept> // Include stdexcept declarations.
10#include <string> // Include string declarations.
11#ifdef SHDR_HAVE_EGL // Enable this branch when its feature macro is defined.
12#include "egl_context.hpp" // Include egl_context.hpp declarations.
13#endif // Finish this conditional compilation branch.
14
15namespace shdr_examples { // Group these helpers within their namespace.
16
17/// Select CPU execution by default, or an explicitly requested GL profile.
18class runner { // Own an optional GPU device and select the pipeline execution backend.
19 std::unique_ptr<shdr::device> device_; // Keep the optional headless context alive until the example finishes.
20
21 public: // Set public access for the following class members.
22 runner(int argc, char** argv) { // Read the common optional GPU profile from this example's command line.
23 if (argc == 1) // Select CPU execution for the default command line.
24 return; // Finish initializing the CPU runner.
25 if (argc != 3 || std::string(argv[1]) != "--gpu") // Accept exactly the documented --gpu PROFILE option.
26 throw std::invalid_argument("usage: executable [--gpu es31|es32|gl43|gl45|gl46]"); // Report usage: executable [--gpu es31|es32|gl43|gl45|gl46].
27 const std::string name(argv[2]); // Construct name with these initial values.
28 shdr::profile profile; // Declare profile for the following calculation.
29 if (name == "es31") // Check this condition before entering the following branch.
30 profile = shdr::profile::es31; // Set profile from this expression.
31 else if (name == "es32") // Select the GLES 3.2 device profile.
32 profile = shdr::profile::es32; // Set profile from this expression.
33 else if (name == "gl43") // Select the desktop GL 4.3 device profile.
34 profile = shdr::profile::gl43; // Set profile from this expression.
35 else if (name == "gl45") // Select the desktop GL 4.5 device profile.
36 profile = shdr::profile::gl45; // Set profile from this expression.
37 else if (name == "gl46") // Select the desktop GL 4.6 device profile.
38 profile = shdr::profile::gl46; // Set profile from this expression.
39 else // Reject profile names outside the supported list.
40 throw std::invalid_argument("unknown GL profile: " + name); // Report unknown GL profile: .
41#ifdef SHDR_HAVE_EGL // Enable this branch when its feature macro is defined.
42 device_.reset(new shdr::headless_device(profile)); // Create the requested headless context through the public library backend.
43#else // Select the alternative implementation for this build.
44 (void)profile; // Consume the parsed profile value in the CPU build configuration.
45 throw std::runtime_error( // Report this failed operation.
46 "GPU examples were not enabled. Configure with EGL development files"); // Provide this text argument for the operation above.
47#endif // Finish this conditional compilation branch.
48 } // End this block.
49
50 void run(const shdr::pipeline& pipeline) { // Execute any prepared pipeline using this example's selected backend.
51 if (device_) // Use the GPU device only when the command line requested one.
52 pipeline.run(*device_); // Run default stages on GPU while preserving explicitly selected CPU stages.
53 else // Execute the default stages on the CPU backend.
54 pipeline.run(); // Run the pipeline through the standard C++ implementation.
55 } // End this block.
56
57 bool gpu() const { // Expose the selected backend for result labels and optional GPU checks.
58 return bool(device_); // Report whether this runner owns a headless GPU device.
59 } // End this block.
60 shdr::device* device() const { // Expose the optional device for interop, synchronization and timing.
61 return device_.get(); // Return the retained device or null for ordinary CPU execution.
62 } // End this block.
63}; // Finish this declaration.
64
65/// Fail examples and tests with a useful diagnostic when CPU/GPU results diverge.
66inline void // Declare void for the following calculation.
67require_close(float actual, float expected, const std::string& label, float tolerance = 0.0001f) { // Compare a computed scalar with its independently calculated reference.
68 if (!std::isfinite(actual) || std::fabs(actual - expected) > tolerance) { // Reject nonfinite results and differences above the chosen absolute tolerance.
69 throw std::runtime_error(label + ": expected " + std::to_string(expected) + ", received " + // Identify the failed case and show both expected and received values.
70 std::to_string(actual)); // Include the computed value in the comparison diagnostic.
71 } // End this block.
72} // End this block.
73
74/// Use repeatable random inputs so each backend receives identical test data.
75inline void randomize(shdr::buffer<float>& values, unsigned seed, float lower, float upper) { // Fill a host buffer with reproducible uniformly distributed test values.
76 std::mt19937 generator(seed); // Initialize the deterministic random sequence from the caller's seed.
77 std::uniform_real_distribution<float> distribution(lower, upper); // Select the caller's inclusive lower and upper distribution bounds.
78 float* data = values.data(); // Mark the host resource modified before filling its elements.
79 for (std::size_t i = 0; i < values.size(); ++i) // Initialize every element of the buffer exactly once.
80 data[i] = distribution(generator); // Store the next random sample from the selected interval.
81} // End this block.
82
83} // namespace shdr_examples
84#endif // Finish this conditional compilation branch.