GpuComputeConfig for a given VisionOp and its parameters.
Assembled ops (Threshold, NormalizeInplace, NormalizeRange, RgbaToGray, GrayToRgba) produce a config via ShaderSpec::Assemble + config_from_spec with no .comp file. All other implemented ops reference a .comp path under Portal/Shaders/Vision/. Unimplemented ops return a config with shader_id == INVALID_SHADER.
Stateless; does not depend on or affect m_contexts.
321{
322 switch (op) {
323 case VisionOp::Threshold: {
324 const auto spec = ShaderSpec::Assemble {}
325 .storage_image("out", BindingDirection::Output)
326 .storage_image("src", BindingDirection::Input)
327 .pc("threshold")
328 .op(KernelOp::CompareGE)
329 .workgroup(k_wg2d[0], k_wg2d[1])
330 .build();
332 }
333 case VisionOp::RgbaToGray: {
334 const auto spec = ShaderSpec::Assemble {}
335 .storage_image("out", BindingDirection::Output)
336 .storage_image("src", BindingDirection::Input)
337 .pc("wr")
338 .pc("wg")
339 .pc("wb")
340 .pc("wa")
341 .op(KernelOp::ChannelDot)
342 .workgroup(k_wg2d[0], k_wg2d[1])
343 .build();
345 }
346 case VisionOp::GrayToRgba: {
347 const auto spec = ShaderSpec::Assemble {}
348 .storage_image("out", BindingDirection::Output)
349 .storage_image("src", BindingDirection::Input)
350 .op(KernelOp::ChannelReplicate)
351 .workgroup(k_wg2d[0], k_wg2d[1])
352 .build();
354 }
355 case VisionOp::GaussianBlur: {
356 const auto spec = ShaderSpec::Assemble {}
357 .tmpl(KernelTemplate::Convolve2D)
358 .storage_image("out", BindingDirection::Output)
359 .storage_image("src", BindingDirection::Input)
364 .workgroup(k_wg2d[0], k_wg2d[1])
365 .build();
367 }
368 case VisionOp::NormalizeRange: {
369 const auto spec = ShaderSpec::Assemble {}
370 .storage_image("out", BindingDirection::Output)
371 .storage_image("src", BindingDirection::Input)
372 .pc("scale")
373 .pc("offset")
374 .op(KernelOp::ScaleOffset)
375 .workgroup(k_wg2d[0], k_wg2d[1])
376 .build();
378 }
379 case VisionOp::NormalizeInplace: {
380 const auto spec = ShaderSpec::Assemble {}
381 .storage_image("out", BindingDirection::Output)
382 .storage_image("src", BindingDirection::Input)
383 .op(KernelOp::Scale)
384 .workgroup(k_wg2d[0], k_wg2d[1])
385 .build();
387 }
388 case VisionOp::Canny: {
389 const auto spec = ShaderSpec::Assemble {}
390 .storage_image("out", BindingDirection::Output)
391 .storage_image("src", BindingDirection::Input)
392 .pc("threshold")
393 .pc("value")
394 .op(KernelOp::CompareGEPreserve)
395 .workgroup(k_wg2d[0], k_wg2d[1])
396 .build();
398 }
399 case VisionOp::RgbaToHsv:
400 return { .shader_path = "rgba_to_hsv.comp.spv", .workgroup_size = k_wg2d };
401 case VisionOp::Downsample2x:
402 return { .shader_path = "downsample_2x.comp.spv", .workgroup_size = k_wg2d };
403 case VisionOp::FilterSeparable:
404 return { .shader_path = "filter_separable.comp.spv", .workgroup_size = k_wg2d };
405 case VisionOp::Sobel:
406 return { .shader_path = "sobel.comp.spv", .workgroup_size = k_wg2d };
407 case VisionOp::Scharr:
408 return { .shader_path = "scharr.comp.spv", .workgroup_size = k_wg2d };
409 case VisionOp::Erode:
410 return { .shader_path = "erode.comp.spv", .workgroup_size = k_wg2d, .push_constant_size = sizeof(MorphPC) };
411 case VisionOp::Dilate:
412 return { .shader_path = "dilate.comp.spv", .workgroup_size = k_wg2d, .push_constant_size = sizeof(MorphPC) };
413 case VisionOp::Open:
414 return { .shader_path = "open.comp.spv", .workgroup_size = k_wg2d, .push_constant_size = sizeof(MorphPC) };
415 case VisionOp::Close:
416 return { .shader_path = "close.comp.spv", .workgroup_size = k_wg2d, .push_constant_size = sizeof(MorphPC) };
417 case VisionOp::MorphGradient:
418 return { .shader_path = "morph_gradient.comp.spv", .workgroup_size = k_wg2d, .push_constant_size = sizeof(MorphPC) };
419 case VisionOp::HarrisResponse:
420 return { .shader_path = "harris_response.comp.spv", .workgroup_size = k_wg2d, .push_constant_size = sizeof(HarrisPC) };
421 case VisionOp::ExtractPeaks:
422 return { .shader_path = "extract_peaks.comp.spv", .workgroup_size = { 256, 1, 1 }, .push_constant_size = sizeof(ExtractPC) };
423 case VisionOp::ConnectedComponents:
424 return { .shader_path = "cc_colorize.comp.spv", .workgroup_size = k_wg2d, .push_constant_size = sizeof(uint32_t) * 2 };
425 case VisionOp::FindContours:
426 return { .shader_path = "contour_segments.comp.spv", .workgroup_size = k_wg2d, .push_constant_size = sizeof(ContourSegmentsPC) };
427 case VisionOp::ThresholdAdaptive:
428 return { .shader_path = "threshold_adaptive.comp.spv", .workgroup_size = k_wg2d, .push_constant_size = sizeof(ThresholdAdaptivePC) };
429 case VisionOp::ThresholdOtsu:
430 return { .shader_path = "threshold_otsu.comp.spv", .workgroup_size = { 256, 1, 1 } };
431 default:
433 }
434}
constexpr ShaderID INVALID_SHADER
Portal::Graphics::GpuComputeConfig GpuComputeConfig
GpuComputeConfig config_from_spec(const Portal::Graphics::ShaderSpec &spec)
Derive a GpuComputeConfig from a ShaderSpec.