blob: b7b77ebfc33a87c1f5ec7bb94c485e24dbd42a0e [file] [log] [blame]
// Copyright 2022 The piet-gpu authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Also licensed under MIT license, at your choice.
//! The clip processing stage (includes substages).
use piet_gpu_hal::{
include_shader, BindType, Buffer, ComputePass, DescriptorSet, Pipeline, Session,
};
// Note that this isn't the code/stage/binding pattern of most of the other stages
// in the new element processing pipeline. We want to move those temporary buffers
// into common memory and converge on this pattern.
pub struct ClipCode {
reduce_pipeline: Pipeline,
leaf_pipeline: Pipeline,
}
pub struct ClipBinding {
reduce_ds: DescriptorSet,
leaf_ds: DescriptorSet,
}
pub const CLIP_PART_SIZE: u32 = 256;
impl ClipCode {
pub unsafe fn new(session: &Session) -> ClipCode {
let reduce_code = include_shader!(session, "../../shader/gen/clip_reduce");
let reduce_pipeline = session
.create_compute_pipeline(reduce_code, &[BindType::Buffer, BindType::BufReadOnly])
.unwrap();
let leaf_code = include_shader!(session, "../../shader/gen/clip_leaf");
let leaf_pipeline = session
.create_compute_pipeline(leaf_code, &[BindType::Buffer, BindType::BufReadOnly])
.unwrap();
ClipCode {
reduce_pipeline,
leaf_pipeline,
}
}
}
impl ClipBinding {
pub unsafe fn new(
session: &Session,
code: &ClipCode,
config: &Buffer,
memory: &Buffer,
) -> ClipBinding {
let reduce_ds = session
.create_simple_descriptor_set(&code.reduce_pipeline, &[memory, config])
.unwrap();
let leaf_ds = session
.create_simple_descriptor_set(&code.leaf_pipeline, &[memory, config])
.unwrap();
ClipBinding { reduce_ds, leaf_ds }
}
/// Record the clip dispatches.
///
/// Assumes memory barrier on entry. Provides memory barrier on exit.
pub unsafe fn record(&self, pass: &mut ComputePass, code: &ClipCode, n_clip: u32) {
let n_wg_reduce = n_clip.saturating_sub(1) / CLIP_PART_SIZE;
if n_wg_reduce > 0 {
pass.dispatch(
&code.reduce_pipeline,
&self.reduce_ds,
(n_wg_reduce, 1, 1),
(CLIP_PART_SIZE, 1, 1),
);
pass.memory_barrier();
}
let n_wg = (n_clip + CLIP_PART_SIZE - 1) / CLIP_PART_SIZE;
if n_wg > 0 {
pass.dispatch(
&code.leaf_pipeline,
&self.leaf_ds,
(n_wg, 1, 1),
(CLIP_PART_SIZE, 1, 1),
);
pass.memory_barrier();
}
}
}