MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ op_open_close()

GpuVisionPass::Completed MayaFlux::Yantra::VisionGpuExecutor::op_open_close ( VisionGpuContexts &  contexts,
Kinesis::Vision::VisionOp  op,
const Kinesis::Vision::MorphParams &  p 
)
private

Apply morphological opening or closing to the current image.

Opening erodes then dilates; closing dilates then erodes. The final image becomes the working image for the following step.

Returns
The resulting image and the image it was derived from.

Definition at line 164 of file VisionImageDispatch.cpp.

168{
169 auto& pixel_ctx = contexts.pixel;
170 auto w = contexts.pass.w;
171 auto h = contexts.pass.h;
172 auto& foundry = Portal::Graphics::get_shader_foundry();
173
174 const auto morph_input = contexts.pass.current;
175 const auto radius = p.radius;
176 const bool is_open = (op == VisionOp::Open);
177 const MorphPC morph_pc { .radius = radius };
178
179 const GpuComputeConfig first_cfg {
180 .shader_path = is_open ? "erode.comp.spv" : "dilate.comp.spv",
181 .workgroup_size = k_wg2d,
182 .push_constant_size = sizeof(MorphPC),
183 };
184 const GpuComputeConfig second_cfg {
185 .shader_path = is_open ? "dilate.comp.spv" : "erode.comp.spv",
186 .workgroup_size = k_wg2d,
187 .push_constant_size = sizeof(MorphPC),
188 };
189 const std::array<uint32_t, 3> image_groups { (w + k_wg2d[0] - 1U) / k_wg2d[0], (h + k_wg2d[1] - 1U) / k_wg2d[1], 1U };
190
191 std::shared_ptr<Core::VKImage> intermediate;
192 std::shared_ptr<Core::VKImage> opened_closed;
193
194 std::vector<DependencyStage> morph_stages;
195 morph_stages.reserve(2);
196 morph_stages.push_back({
197 .config = first_cfg,
198 .stage_fn = [&pixel_ctx, &intermediate, morph_input, morph_pc, w, h](GpuDispatchCore& ctx) {
199 pixel_ctx.stage_image(morph_input);
200 pixel_ctx.prepare_output_image(w, h);
201 intermediate = pixel_ctx.get_output_image(0);
202 ctx.set_push_constants(morph_pc); },
203 .hazard_fn = [&intermediate](GpuDispatchCore&) { return std::vector<HazardResource> {
204 { .binding = { .set = 0, .binding = 1, .direction = GpuBufferBinding::Direction::INPUT_OUTPUT, .element_type = GpuBufferBinding::ElementType::IMAGE_STORAGE },
205 .image = intermediate->get_image() },
206 }; },
207 .explicit_groups = image_groups,
208 });
209 morph_stages.push_back({
210 .config = second_cfg,
211 .stage_fn = [&pixel_ctx, &intermediate, &opened_closed, morph_pc, w, h](GpuDispatchCore& ctx) {
212 pixel_ctx.stage_image(intermediate);
213 pixel_ctx.prepare_output_image(w, h);
214 opened_closed = pixel_ctx.get_output_image(0);
215 ctx.set_push_constants(morph_pc); },
216 .explicit_groups = image_groups,
217 });
218
219 {
220 ExecutionContext morph_ctx;
221 morph_ctx.mode = ExecutionMode::DEPENDENCY;
222 DependencyParams morph_params;
223 morph_params.stages = morph_stages;
224 morph_params.async = true;
225 morph_ctx.parameters = morph_params;
226 const auto result = pixel_ctx.execute(Datum<> {}, morph_ctx);
227 const auto f = result.get_metadata<FenceID>("gpu_fence").value_or(INVALID_FENCE);
228 foundry.wait_for_fence(f);
229 foundry.release_fence(f);
230 }
231
232 if (is_open) {
233 contexts.pass.result.images.open = opened_closed;
234 } else {
235 contexts.pass.result.images.close = opened_closed;
236 }
237 contexts.pass.current = opened_closed;
238 contexts.pass.result.structured = std::monostate {};
239
240 return { .output = opened_closed, .input = morph_input };
241}
float radius
uint32_t h
Definition InkPress.cpp:29
constexpr FenceID INVALID_FENCE
MAYAFLUX_API ShaderFoundry & get_shader_foundry()
Get the global shader compiler instance.
constexpr std::array< uint32_t, 3 > k_wg2d
Standard 2D workgroup used by all pixel-to-pixel vision shaders.
Portal::Graphics::GpuComputeConfig GpuComputeConfig
@ DEPENDENCY
Part of dependency graph.

References MayaFlux::Yantra::DependencyParams::async, MayaFlux::Kinesis::Vision::ImageOutputs::close, MayaFlux::Kinesis::Vision::VisionPass< Handle >::current, MayaFlux::Yantra::DEPENDENCY, MayaFlux::Portal::Graphics::get_shader_foundry(), MayaFlux::Kinesis::Vision::VisionPass< Handle >::h, h, MayaFlux::Portal::Graphics::GpuBufferBinding::IMAGE_STORAGE, MayaFlux::Kinesis::Vision::VisionResult::images, MayaFlux::Portal::Graphics::GpuBufferBinding::INPUT_OUTPUT, MayaFlux::Portal::Graphics::INVALID_FENCE, MayaFlux::Yantra::VisionInternal::k_wg2d, MayaFlux::Yantra::ExecutionContext::mode, MayaFlux::Kinesis::Vision::ImageOutputs::open, MayaFlux::Yantra::ExecutionContext::parameters, MayaFlux::Yantra::VisionGpuContexts::pass, MayaFlux::Yantra::VisionGpuContexts::pixel, radius, MayaFlux::Kinesis::Vision::MorphParams::radius, MayaFlux::Yantra::VisionInternal::MorphPC::radius, MayaFlux::Kinesis::Vision::VisionPass< Handle >::result, MayaFlux::Portal::Graphics::GpuComputeConfig::shader_path, MayaFlux::Yantra::DependencyParams::stages, MayaFlux::Kinesis::Vision::VisionResult::structured, and MayaFlux::Kinesis::Vision::VisionPass< Handle >::w.

+ Here is the call graph for this function: