| … | 21 unchanged lines hidden |
| 22 |
22 |
|
example = "parity_stencil_clip", |
| 23 |
23 |
|
ledger = "bp-stencil", |
| 24 |
24 |
|
negative_control = true, |
|
25 |
+ |
required_backends = { "vulkan", "opengl", "d3d11", "d3d12" }, |
| 25 |
26 |
|
assertions = { |
| 26 |
27 |
|
{ kind = "point", x = 48, y = 48, expected = "background" }, |
| 27 |
28 |
|
{ kind = "point", x = 128, y = 128, expected = "foreground" }, |
| … | 5 unchanged lines hidden |
| 33 |
34 |
|
example = "parity_resource_sync", |
| 34 |
35 |
|
ledger = "bp-resource-sync", |
| 35 |
36 |
|
negative_control = false, |
|
37 |
+ |
required_backends = { "vulkan", "opengl", "d3d11", "d3d12" }, |
| 36 |
38 |
|
assertions = { |
| 37 |
39 |
|
{ kind = "point", x = 96, y = 96, expected = "compute_to_draw" }, |
| 38 |
40 |
|
{ kind = "point", x = 160, y = 96, expected = "offscreen_sampled" }, |
| … | 4 unchanged lines hidden |
| 43 |
45 |
|
example = "parity_backend_features", |
| 44 |
46 |
|
ledger = "bp-validation", |
| 45 |
47 |
|
negative_control = false, |
|
48 |
+ |
required_backends = { "vulkan", "opengl", "d3d11", "d3d12" }, |
| 46 |
49 |
|
assertions = { |
| 47 |
50 |
|
{ kind = "point", x = 64, y = 64, expected = "mrt" }, |
| 48 |
51 |
|
{ kind = "point", x = 128, y = 64, expected = "indirect_instance" }, |
| … | 90 unchanged lines hidden |
| 139 |
142 |
|
raw_result = path.join(dir, "run.json"), |
| 140 |
143 |
|
assertions = scene.assertions, |
| 141 |
144 |
|
negative_control_required = scene.negative_control, |
|
145 |
+ |
required_backends = scene.required_backends, |
| 142 |
146 |
|
dry_run = opts.dry_run and true or false, |
| 143 |
147 |
|
} |
| 144 |
148 |
|
end |
| … | 35 unchanged lines hidden |
| 180 |
184 |
|
end |
| 181 |
185 |
|
|
| 182 |
186 |
|
row.status = "fail" |
| 183 |
|
- |
row.error = "exact assertion evaluator/readback proof not implemented yet" |
|
187 |
+ |
row.error = "trusted GPU readback proof artifact missing" |
| 184 |
188 |
|
return row |
| 185 |
189 |
|
end |
| 186 |
190 |
|
|
| … | 11 unchanged lines hidden |
| 198 |
202 |
|
return summary |
| 199 |
203 |
|
end |
| 200 |
204 |
|
|
|
205 |
+ |
local function backend_required(scene, backend) |
|
206 |
+ |
for _, required in ipairs(scene.required_backends or {}) do |
|
207 |
+ |
if required == backend then return true end |
|
208 |
+ |
end |
|
209 |
+ |
return false |
|
210 |
+ |
end |
|
211 |
+ |
|
|
212 |
+ |
local function ledger_gate(scene, rows) |
|
213 |
+ |
local gate = { |
|
214 |
+ |
ledger = scene.ledger, |
|
215 |
+ |
scene = scene.id, |
|
216 |
+ |
required_backends = scene.required_backends or {}, |
|
217 |
+ |
status = "incomplete", |
|
218 |
+ |
pass = {}, |
|
219 |
+ |
fail = {}, |
|
220 |
+ |
skip = {}, |
|
221 |
+ |
missing = {}, |
|
222 |
+ |
} |
|
223 |
+ |
for _, backend in ipairs(gate.required_backends) do |
|
224 |
+ |
local found = false |
|
225 |
+ |
for _, row in ipairs(rows) do |
|
226 |
+ |
if row.scene == scene.id and row.backend == backend then |
|
227 |
+ |
found = true |
|
228 |
+ |
if row.status == "pass" then |
|
229 |
+ |
gate.pass[#gate.pass + 1] = backend |
|
230 |
+ |
elseif row.status == "skip" then |
|
231 |
+ |
gate.skip[#gate.skip + 1] = backend |
|
232 |
+ |
else |
|
233 |
+ |
gate.fail[#gate.fail + 1] = backend |
|
234 |
+ |
end |
|
235 |
+ |
break |
|
236 |
+ |
end |
|
237 |
+ |
end |
|
238 |
+ |
if not found then |
|
239 |
+ |
gate.missing[#gate.missing + 1] = backend |
|
240 |
+ |
end |
|
241 |
+ |
end |
|
242 |
+ |
if #gate.pass == #gate.required_backends and #gate.fail == 0 and #gate.skip == 0 and #gate.missing == 0 then |
|
243 |
+ |
gate.status = "pass" |
|
244 |
+ |
end |
|
245 |
+ |
return gate |
|
246 |
+ |
end |
|
247 |
+ |
|
|
248 |
+ |
local function ledger_gates(rows) |
|
249 |
+ |
local gates = {} |
|
250 |
+ |
for _, scene in ipairs(SCENES) do |
|
251 |
+ |
gates[#gates + 1] = ledger_gate(scene, rows) |
|
252 |
+ |
end |
|
253 |
+ |
return gates |
|
254 |
+ |
end |
|
255 |
+ |
|
| 201 |
256 |
|
function M.run(opts, config) |
| 202 |
257 |
|
config = config or {} |
| 203 |
258 |
|
local root = config.root or path.repo_root("tools/test.lua") |
| … | 8 unchanged lines hidden |
| 212 |
267 |
|
version = 1, |
| 213 |
268 |
|
rows = rows, |
| 214 |
269 |
|
summary = summarize(rows), |
|
270 |
+ |
ledger_gates = ledger_gates(rows), |
| 215 |
271 |
|
} |
| 216 |
272 |
|
if opts.json then |
| 217 |
273 |
|
path.mkdir_p(path.dirname(opts.json)) |
| … | 14 unchanged lines hidden |
| 232 |
288 |
|
assert(result.summary.skip == 2) |
| 233 |
289 |
|
assert(result.summary.pass == 0) |
| 234 |
290 |
|
assert(result.summary.fail == 0) |
|
291 |
+ |
assert(result.ledger_gates[1].status == "incomplete") |
|
292 |
+ |
assert(#result.ledger_gates[1].skip == 2) |
|
293 |
+ |
assert(#result.ledger_gates[1].missing == 2) |
| 235 |
294 |
|
assert(result.rows[1].status == "skip") |
| 236 |
295 |
|
assert(result.rows[1].skip_reason == "dry-run") |
| 237 |
296 |
|
assert(result.rows[1].negative_control_required == true) |
| … | 14 unchanged lines hidden |