use super::{
validate_group_contract, BatchColor, Error, MetalBatchDecoder, MetalBatchGroupCompletion,
MetalImageDestination, PreparedBatchGroup, SubmittedMetalGroupDecodeInto,
};
pub(super) fn validate_consumer_registry_ids(
producer_registry_id: u64,
consumer_registry_id: u64,
) -> Result<(), Error> {
if producer_registry_id == consumer_registry_id {
return Ok(());
}
Err(crate::error::metal_kernel_support_error(
"J2K Metal consumer queue belongs to a different device",
j2k_metal_support::MetalSupportError::MetalImageDeviceMismatch {
image_registry_id: producer_registry_id,
requested_registry_id: consumer_registry_id,
},
))
}
impl MetalBatchDecoder {
#[cfg(target_os = "macos")]
pub fn decode_prepared_group_into(
&mut self,
group: &PreparedBatchGroup,
destination: &MetalImageDestination,
) -> Result<(), Error> {
let fmt = validate_group_contract(group.info())?;
destination
.validate_device(self.backend_session().device())
.and_then(|()| {
destination.validate_batch(group.info().dimensions, fmt, group.images().len())
})
.map_err(|source| {
crate::error::metal_kernel_support_error(
"J2K Metal prepared group destination validation failed",
source,
)
})?;
match group.info().color {
BatchColor::Gray => {
let plans = self.prepared_gray_group_plans(group, fmt, false)?;
let runtime = self.backend_session().runtime()?;
crate::compute::submit_prepared_direct_grayscale_plan_batch_into_group(
runtime,
&plans,
fmt,
destination,
Some(group.source_indices()),
crate::compute::DirectDestinationConsumerOrdering::HostCompletionOnly,
)?
.wait()?;
}
BatchColor::Rgb | BatchColor::Rgba => {
let plans = self.prepared_color_group_plans(group, fmt)?;
let runtime = self.backend_session().runtime()?;
crate::compute::submit_prepared_direct_color_plan_batch_into_group(
runtime,
&plans,
fmt,
group.info().layout,
destination,
Some(group.source_indices()),
crate::compute::DirectDestinationConsumerOrdering::HostCompletionOnly,
)?
.wait()?;
}
_ => {
return Err(Error::UnsupportedMetalRequest {
reason:
"J2K Metal exact external final-store received an unknown color contract",
})
}
}
self.record_submission();
Ok(())
}
#[cfg(target_os = "macos")]
pub fn submit_prepared_group_into(
&mut self,
group: &PreparedBatchGroup,
destination: MetalImageDestination,
) -> Result<SubmittedMetalGroupDecodeInto, Error> {
self.submit_prepared_group_into_with_ordering(
group,
destination,
crate::compute::DirectDestinationConsumerOrdering::Deferred,
)
}
#[cfg(target_os = "macos")]
pub fn submit_prepared_group_into_for_consumer_queue(
&mut self,
group: &PreparedBatchGroup,
destination: MetalImageDestination,
consumer_queue: &metal::CommandQueueRef,
) -> Result<SubmittedMetalGroupDecodeInto, Error> {
let producer_registry_id = self.backend_session().device().registry_id();
let consumer_registry_id = consumer_queue.device().registry_id();
validate_consumer_registry_ids(producer_registry_id, consumer_registry_id)?;
self.submit_prepared_group_into_with_ordering(
group,
destination,
crate::compute::DirectDestinationConsumerOrdering::Known {
consumer_queue: consumer_queue.to_owned(),
timeline: self.backend_session().consumer_event_timeline(),
},
)
}
fn submit_prepared_group_into_with_ordering(
&mut self,
group: &PreparedBatchGroup,
destination: MetalImageDestination,
consumer_ordering: crate::compute::DirectDestinationConsumerOrdering,
) -> Result<SubmittedMetalGroupDecodeInto, Error> {
let fmt = validate_group_contract(group.info())?;
destination
.validate_device(self.backend_session().device())
.and_then(|()| {
destination.validate_batch(group.info().dimensions, fmt, group.images().len())
})
.map_err(|source| {
crate::error::metal_kernel_support_error(
"J2K Metal submitted prepared group destination validation failed",
source,
)
})?;
let runtime = self.backend_session().runtime()?;
let submission =
match group.info().color {
BatchColor::Gray => {
let plans = self.prepared_gray_group_plans(group, fmt, true)?;
crate::compute::submit_prepared_direct_grayscale_plan_batch_into_group(
runtime,
&plans,
fmt,
&destination,
Some(group.source_indices()),
consumer_ordering,
)?
}
BatchColor::Rgb | BatchColor::Rgba => {
let plans = self.prepared_color_group_plans(group, fmt)?;
crate::compute::submit_prepared_direct_color_plan_batch_into_group(
runtime,
&plans,
fmt,
group.info().layout,
&destination,
Some(group.source_indices()),
consumer_ordering,
)?
}
_ => return Err(Error::UnsupportedMetalRequest {
reason:
"J2K Metal exact external final-store received an unknown color contract",
}),
};
self.record_submission();
Ok(SubmittedMetalGroupDecodeInto {
submission,
destination,
completion: MetalBatchGroupCompletion::from_prepared(group)?,
})
}
}