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.