Source browser

examples/evt3.cpp

Read the complete file below or download its original bytes. Line numbers provide stable links to a declaration or processing step.

File fingerprint
1/** @file evt3.cpp
2 * @brief Validate a streaming parallel EVT3 decoder against a scalar host oracle.
3 * Checks direct/vector events, trigger order, camera bit, synchronization, wraps,
4 * empty/odd-size batches, arbitrary block cuts, and state carried between calls.
5 */
6#include "runner.hpp" // Include runner.hpp declarations.
7#include "evt3_support.hpp" // Include evt3_support.hpp declarations.
8#include "evt3_flow_checks.hpp" // Include evt3_flow_checks.hpp declarations.
9#include <cstdint> // Include cstdint declarations.
10#include <vector> // Include vector declarations.
11
12namespace { // Group these helpers within their namespace.
13using shdr::glsl::uvec4; // Give this type or declaration a convenient local name.
14
15// A scalar switch interpreter forms timestamps in uint64 arithmetic independently
16// of the GPU block summaries, prefix passes, and packed output addressing.
17struct reference_decoder { // Declare reference decoder.
18    unsigned y = 0, base = 0, polarity = 0, high = 0, low = 0, wraps = 0; // Set y from this expression.
19    bool synchronized = false; // Set synchronized from this expression.
20    std::vector<uvec4> decode(const std::vector<std::uint16_t>& words) { // Implement decode for the operations below.
21        std::vector<uvec4> result; // Declare result for the following calculation.
22        for (std::uint16_t word : words) { // Visit each std required by this loop.
23            const unsigned value = word & 4095u; // Set value from this expression.
24            switch (word >> 12u) { // Select behavior from the value of this expression.
25            case 0: // Handle this specific selection value.
26                y = value; // Set y from this expression.
27                break; // Finish this loop or selection immediately.
28            case 3: // Handle this specific selection value.
29                base = value & 2047u; // Set base from this expression.
30                polarity = value >> 11u; // Set polarity from this expression.
31                break; // Finish this loop or selection immediately.
32            case 6: // Handle this specific selection value.
33                low = value; // Set low from this expression.
34                break; // Finish this loop or selection immediately.
35            case 8: // Handle this specific selection value.
36                if (synchronized && high > value && high - value >= 4085u) // Check this condition before entering the following branch.
37                    ++wraps; // Continue the expression using wraps.
38                high = value; // Set high from this expression.
39                low = 0; // Set low from this expression.
40                synchronized = true; // Set synchronized from this expression.
41                break; // Finish this loop or selection immediately.
42            case 2: // Handle this specific selection value.
43                if (synchronized) // Check this condition before entering the following branch.
44                    append(result, // Apply append to these arguments.
45                           value & 2047u, // Continue the expression using value.
46                           (y & 2047u) | ((value >> 11u) << 11u) | ((y >> 11u) << 12u)); // Continue the expression using y, value, y.
47                break; // Finish this loop or selection immediately.
48            case 4: // Handle this specific selection value.
49            case 5: { // Handle this specific selection value.
50                const unsigned width = (word >> 12u) == 4 ? 12u : 8u; // Set width from this expression.
51                if (synchronized) // Check this condition before entering the following branch.
52                    for (unsigned bit = 0; bit < width; ++bit) // Iterate over bit for this calculation.
53                        if (value & (1u << bit)) // Check this condition before entering the following branch.
54                            append(result, // Apply append to these arguments.
55                                   (base + bit) & 2047u, // Continue the expression using base, bit.
56                                   (y & 2047u) | (polarity << 11u) | ((y >> 11u) << 12u)); // Continue the expression using y, polarity, y.
57                base = (base + width) & 2047u; // Set base from this expression.
58                break; // Finish this loop or selection immediately.
59            } // End this block.
60            case 10: // Handle this specific selection value.
61                if (synchronized) // Check this condition before entering the following branch.
62                    append(result, value >> 8u, 0x80000000u | (value & 1u)); // Apply append to these arguments.
63                break; // Finish this loop or selection immediately.
64            default: // Skip extension and reserved word types after processing supported event words.
65                break; // Finish this loop or selection immediately.
66            } // End this block.
67        } // End this block.
68        return result; // Return result.
69    } // End this block.
70    void append(std::vector<uvec4>& result, unsigned x, unsigned yp) const { // Implement append for the operations below.
71        const std::uint64_t t = // Set t from this expression.
72            (std::uint64_t(wraps) * 16777216u) + (std::uint64_t(high) * 4096u) + low; // Apply uint64 t to these arguments.
73        result.push_back(uvec4(x, yp, static_cast<unsigned>(t), static_cast<unsigned>(t >> 32))); // Apply push back to these arguments.
74    } // End this block.
75    void verify_state(const shdr::buffer<uvec4>& state) const { // Implement verify state for the operations below.
76        const uvec4* actual = state.data(); // Set actual from this expression.
77        if (actual[0] != uvec4(y, base, polarity, high) || // Check this condition before entering the following branch.
78            actual[1] != uvec4(low, wraps, synchronized ? 1u : 0u, 0u)) // Apply uvec4 to these arguments.
79            throw std::runtime_error("EVT3 persistent decoder state mismatch"); // Report EVT3 persistent decoder state mismatch.
80    } // End this block.
81}; // Finish this declaration.
82
83void compare(shdr_examples::evt3_decoder& decoder, // Declare compare with the parameters continued below.
84             const std::vector<uvec4>& expected, // Declare expected for the following calculation.
85             reference_decoder& reference) { // Declare reference for the following calculation.
86    if (decoder.event_count() != expected.size()) // Check this condition before entering the following branch.
87        throw std::runtime_error("EVT3 output length mismatch"); // Report EVT3 output length mismatch.
88    const uvec4* actual = static_cast<const shdr::buffer<uvec4>&>(decoder.events).data(); // Use a constant buffer view so GPU writes synchronize before host reads.
89    for (std::size_t i = 0; i < expected.size(); ++i) // Iterate over i for this calculation.
90        if (actual[i] != expected[i]) // Check this condition before entering the following branch.
91            throw std::runtime_error("EVT3 ordered event mismatch at " + std::to_string(i)); // Report EVT3 ordered event mismatch at .
92    reference.verify_state(decoder.state); // Apply verify state to these arguments.
93} // End this block.
94
95void independent(shdr_examples::runner& runner) { // Implement independent for the operations below.
96    std::vector<std::uint16_t> words = { // Set words from this expression.
97        0x0007u, 0x3003u, 0x4fffu, 0x2002u, 0xa101u, // Defer these prefix events until a timestamp establishes synchronization.
98        0x8ffeu, 0x6fffu, 0x0fffu, 0x3ffdu, 0x400bu, 0x5101u, // camera + X wrap, VECT8 ignores unused bits
99        0x8fffu, 0x6002u, 0x2005u, 0x8000u, 0x6023u, 0xaff1u, 0xe012u, // Complete this expression or declaration.
100        0xf123u, 0x7004u, 0x1000u, 0x4000u, 0x5fffu, // extensions/reserved/empty vectors
101        0x8000u, 0x2007u // repeated TIME_HIGH resets low time
102    }; // Finish this declaration.
103    const unsigned block_sizes[] = {1, 3, 7, 64, 128}; // Declare block sizes for the following calculation.
104    for (unsigned block_size : block_sizes) { // Visit each block size required by this loop.
105        shdr_examples::evt3_decoder decoder(unsigned(words.size()), block_size); // Construct decoder with these initial values.
106        decoder.load(words); // Apply load to these arguments.
107        reference_decoder reference; // Declare reference for the following calculation.
108        const std::vector<uvec4> expected = reference.decode(words); // Set expected from this expression.
109        runner.run(decoder.reset_pipeline()); // Execute the configured pipeline on the requested backend.
110        compare(decoder, expected, reference); // Apply compare to these arguments.
111        runner.run(decoder.reset_pipeline()); // Execute the configured pipeline on the requested backend.
112        compare(decoder, expected, reference); // Apply compare to these arguments.
113    } // End this block.
114    shdr_examples::evt3_decoder decoder(6013); // Construct decoder with these initial values.
115    words = shdr_examples::evt3_random_words(6013, 897); // Set words from this expression.
116    decoder.load(words); // Apply load to these arguments.
117    reference_decoder reference; // Declare reference for the following calculation.
118    const std::vector<uvec4> expected = reference.decode(words); // Set expected from this expression.
119    runner.run(decoder.reset_pipeline()); // Execute the configured pipeline on the requested backend.
120    compare(decoder, expected, reference); // Apply compare to these arguments.
121} // End this block.
122
123void streaming(shdr_examples::runner& runner) { // Implement streaming for the operations below.
124    const std::vector<std::uint16_t> words = shdr_examples::evt3_random_words(2049, 293); // Set words from this expression.
125    const unsigned chunks[] = {1, 17, 127, 128, 129}; // Declare chunks for the following calculation.
126    for (unsigned chunk : chunks) { // Visit each chunk required by this loop.
127        shdr_examples::evt3_decoder decoder(chunk, 7); // Construct decoder with these initial values.
128        reference_decoder reference; // Declare reference for the following calculation.
129        for (std::size_t begin = 0; begin < words.size(); begin += chunk) { // Iterate over begin for this calculation.
130            const std::size_t end = std::min(words.size(), begin + chunk); // Set end from this expression.
131            const std::vector<std::uint16_t> batch(words.begin() + begin, words.begin() + end); // Construct batch with these initial values.
132            decoder.load(batch); // Apply load to these arguments.
133            const std::vector<uvec4> expected = reference.decode(batch); // Set expected from this expression.
134            runner.run(decoder.stream_pipeline()); // Execute the configured pipeline on the requested backend.
135            compare(decoder, expected, reference); // Apply compare to these arguments.
136        } // End this block.
137        decoder.load(std::vector<std::uint16_t>()); // Apply load to these arguments.
138        runner.run(decoder.stream_pipeline()); // Execute the configured pipeline on the requested backend.
139        compare(decoder, std::vector<uvec4>(), reference); // Apply compare to these arguments.
140    } // End this block.
141    // The 256th wrap crosses uint32 timestamp range, pair representation keeps it exact.
142    shdr_examples::evt3_decoder decoder(3, 1); // Construct decoder with these initial values.
143    decoder.state.data()[0] = uvec4(2047u, 0u, 1u, 4095u); // Apply data to these arguments.
144    decoder.state.data()[1] = uvec4(0u, 255u, 1u, 0u); // Apply data to these arguments.
145    decoder.load(std::vector<std::uint16_t>{0x8000u, 0x6123u, 0x2001u}); // Apply load to these arguments.
146    reference_decoder reference; // Declare reference for the following calculation.
147    reference.y = 2047u; // Set reference.y from this expression.
148    reference.polarity = 1u; // Set reference.polarity from this expression.
149    reference.high = 4095u; // Set reference.high from this expression.
150    reference.wraps = 255u; // Set reference.wraps from this expression.
151    reference.synchronized = true; // Set reference.synchronized from this expression.
152    const std::vector<uvec4> expected = // Set expected from this expression.
153        reference.decode(std::vector<std::uint16_t>{0x8000u, 0x6123u, 0x2001u}); // Apply decode to these arguments.
154    runner.run(decoder.stream_pipeline()); // Execute the configured pipeline on the requested backend.
155    compare(decoder, expected, reference); // Apply compare to these arguments.
156} // End this block.
157
158// Consume CPU or GPU decoded events on the host in a compact downstream CD layout.
159void compact_processing(shdr_examples::runner& runner) { // Implement compact processing for the operations below.
160    const std::vector<std::uint16_t> words = { // Set words from this expression.
161        0x8fffu, 0x6fffu, 0x02cfu, 0x2cffu, 0xa101u, 0x8000u, 0x6003u, 0x2002u}; // Complete this expression or declaration.
162    shdr_examples::evt3_decoder decoder(unsigned(words.size()), 3); // Construct decoder with these initial values.
163    decoder.load(words); // Apply load to these arguments.
164    runner.run(decoder.reset_pipeline()); // Execute the configured pipeline on the requested backend.
165    const std::vector<std::uint64_t> compact = // Set compact from this expression.
166        shdr_examples::evt3_compact_cd_to64(decoder.events, decoder.event_count()); // Apply evt3 compact cd to64 to these arguments.
167    if (compact.size() != 2u) // Check this condition before entering the following branch.
168        throw std::runtime_error("compact CD consumer should omit trigger records"); // Report compact CD consumer should omit trigger records.
169    const unsigned expected_x[] = {1279u, 2u}; // Declare expected x for the following calculation.
170    const unsigned expected_p[] = {1u, 0u}; // Declare expected p for the following calculation.
171    const std::uint64_t expected_t[] = {16777215u, 16777219u}; // Declare expected t for the following calculation.
172    for (unsigned i = 0; i < 2u; ++i) { // Iterate over i for this calculation.
173        if ((compact[i] & 2047u) != expected_x[i] || ((compact[i] >> 11u) & 1023u) != 719u || // Check this condition before entering the following branch.
174            ((compact[i] >> 21u) & 1u) != expected_p[i] || (compact[i] >> 22u) != expected_t[i]) // Continue the expression using compact, i, expected p.
175            throw std::runtime_error( // Report this failed operation.
176                "64-bit CD consumer changed coordinates, polarity, or 42-bit timestamp"); // Provide this text argument for the operation above.
177    } // End this block.
178    shdr::buffer<uvec4> invalid(1); // Construct invalid with these initial values.
179    invalid.data()[0] = uvec4(1u, 1024u, 0u, 0u); // Apply data to these arguments.
180    bool caught = false; // Set caught from this expression.
181    try { // Run the operation while retaining the error handling below.
182        shdr_examples::evt3_compact_cd_to64(invalid, 1); // Apply evt3 compact cd to64 to these arguments.
183    } catch (const shdr::error&) { // Report the exception from the preceding operation.
184        caught = true; // Set caught from this expression.
185    } // End this block.
186    if (!caught) // Check this condition before entering the following branch.
187        throw std::runtime_error("compact CD consumer must validate Y capacity"); // Report compact CD consumer must validate Y capacity.
188    invalid.data()[0] = uvec4(1u, 1u, 0u, 1024u); // Apply data to these arguments.
189    caught = false; // Set caught from this expression.
190    try { // Run the operation while retaining the error handling below.
191        shdr_examples::evt3_compact_cd_to64(invalid, 1); // Apply evt3 compact cd to64 to these arguments.
192    } catch (const shdr::error&) { // Report the exception from the preceding operation.
193        caught = true; // Set caught from this expression.
194    } // End this block.
195    if (!caught) // Check this condition before entering the following branch.
196        throw std::runtime_error("compact CD consumer must validate timestamp capacity"); // Report compact CD consumer must validate timestamp capacity.
197    std::cout << "CPU CD consumer: " << compact.size() // Write this part of the example result or diagnostic.
198              << " compact uint64 words with 42-bit timestamps verified\n"; // Write this part of the example result or diagnostic.
199} // End this block.
200} // namespace
201
202int main(int argc, char** argv) { // Run this example and validate its results.
203    try { // Run the operation while retaining the error handling below.
204        shdr_examples::runner runner(argc, argv); // Construct runner with these initial values.
205        independent(runner); // Apply independent to these arguments.
206        streaming(runner); // Apply streaming to these arguments.
207        compact_processing(runner); // Apply compact processing to these arguments.
208        shdr_examples::check_evt3_flow(runner); // Apply check evt3 flow to these arguments.
209        std::cout // Write this part of the example result or diagnostic.
210            << "EVT3 ordered direct/vector/trigger events, block and batch boundaries, and timestamps verified\n"; // Write this part of the example result or diagnostic.
211        return 0; // Report successful completion.
212    } // End this block.
213#ifdef SHDR_HAVE_EGL // Enable this branch when its feature macro is defined.
214    catch (const shdr_examples::context_unavailable& e) { // Handle the indicated exception from the preceding operation.
215        std::cerr << "SKIP: " << e.what() << '\n'; // Write this part of the example result or diagnostic.
216        return 77; // Report an unavailable optional GPU backend.
217    } // End this block.
218#endif // Finish this conditional compilation branch.
219    catch (const std::exception& e) { // Handle the indicated exception from the preceding operation.
220        std::cerr << e.what() << '\n'; // Write this part of the example result or diagnostic.
221        return 1; // Report a failed check or operation.
222    } // End this block.
223} // End this block.