j2k-cuda 0.8.0

CUDA adapter for resident HTJ2K decode/encode and shared JPEG 2000 stages
Documentation
// SPDX-License-Identifier: MIT OR Apache-2.0

mod component;
mod surface;

use self::{
    component::{finish_color_components, run_pending_color_idwt},
    surface::{finalize_color_surface, FinalizeColorSurfaceRequest},
};
use super::{
    cuda_error, dispatch_color_store, host_owners, pooled_cuda_buffer, profile, run_color_mct,
    ColorStoreInputs, CudaBufferPool, CudaComponentDecodeWork, CudaHtj2kColorDecodePlans,
    CudaHtj2kProfileReport, CudaQueuedIdwtBatch, Error, PixelFormat, Surface,
};

pub(super) fn finish_color_cuda_resident_surface_with_component_work(
    request: FinishColorCudaResidentSurfaceRequest<'_>,
) -> Result<(Surface, CudaHtj2kProfileReport), Error> {
    let FinishColorCudaResidentSurfaceRequest {
        context,
        pool,
        fmt,
        mut color,
        mut component_work,
        wall_started,
        collect_stage_timings,
        run_idwt,
        emit_report,
    } = request;
    let mut host_budget =
        host_owners::color_work_budget(&color, &component_work, "j2k CUDA color completion graph")?;
    let pending_idwt_batch = if run_idwt {
        run_pending_color_idwt(
            context,
            &color,
            &mut component_work,
            pool,
            collect_stage_timings,
            &mut host_budget,
        )?
    } else {
        None
    };
    let completion_result = (|| {
        let prepared = finish_color_components(component_work, &mut color)?;
        let inputs = ColorStoreInputs {
            context,
            buffers: [
                pooled_cuda_buffer(&prepared.components[0].buffer)?,
                pooled_cuda_buffer(&prepared.components[1].buffer)?,
                pooled_cuda_buffer(&prepared.components[2].buffer)?,
            ],
            stores: [
                &prepared.components[0].store,
                &prepared.components[1].store,
                &prepared.components[2].store,
            ],
            bit_depths: color.rgb_bit_depths(),
        };
        let mct = run_color_mct(
            inputs,
            color.mct_dimensions,
            color.mct,
            color.transform,
            collect_stage_timings,
        )?;
        let dispatches = prepared.dispatches.saturating_add(mct.kernel_dispatches);
        let decode_dispatches = prepared
            .decode_dispatches
            .saturating_add(mct.decode_kernel_dispatches);
        color.report.mct_us = color.report.mct_us.saturating_add(mct.elapsed_us);
        color.report.detail.mct_dispatch_count = color
            .report
            .detail
            .mct_dispatch_count
            .saturating_add(mct.kernel_dispatches);
        let (store_output, store_us) = context
            .time_default_stream_named_us_if(
                collect_stage_timings,
                "j2k.htj2k.decode.store.color",
                || dispatch_color_store(inputs, mct, fmt),
            )
            .map_err(cuda_error)?;
        let (surface_buffer, store_stats) = store_output.into_parts();
        // Both runtime paths synchronize their kernel launch before success.
        let completion_established =
            mct.kernel_dispatches != 0 || store_stats.kernel_dispatches() != 0;
        let output = finalize_color_surface(FinalizeColorSurfaceRequest {
            fmt,
            color,
            surface_buffer,
            dispatches,
            decode_dispatches,
            store_stats,
            store_us,
            wall_started,
            emit_report,
        });
        Ok((output, completion_established))
    })();
    CudaQueuedIdwtBatch::resolve_optional_after_completed_work(
        pending_idwt_batch,
        completion_result,
    )
}

#[cfg(feature = "cuda-runtime")]
pub(super) struct FinishColorCudaResidentSurfaceRequest<'a> {
    pub(super) context: &'a j2k_cuda_runtime::CudaContext,
    pub(super) pool: &'a CudaBufferPool,
    pub(super) fmt: PixelFormat,
    pub(super) color: CudaHtj2kColorDecodePlans,
    pub(super) component_work: Vec<CudaComponentDecodeWork>,
    pub(super) wall_started: Option<profile::ProfileInstant>,
    pub(super) collect_stage_timings: bool,
    pub(super) run_idwt: bool,
    pub(super) emit_report: bool,
}