Skip to content

Commit

Permalink
Merge pull request #181 from linebender/mem2
Browse files Browse the repository at this point in the history
Implement robust dynamic memory
  • Loading branch information
raphlinus authored Jul 14, 2022
2 parents d5b04a6 + 78bdd08 commit bfa4abf
Show file tree
Hide file tree
Showing 22 changed files with 996 additions and 636 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/push-shader.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
git switch main
git config user.name "Commit by GitHub Action"
git config user.email "[email protected]"
git merge dev -m "merge from dev branch"
git merge dev -m "merge from dev branch - ${{ github.ref_name }}"
sed -i '' '/shader\/gen/d' .gitignore
git add .gitignore
git rm -r --ignore-unmatch piet-gpu/shader/gen
Expand Down
68 changes: 27 additions & 41 deletions piet-gpu/bin/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use piet_gpu_hal::{
use piet::kurbo::Point;
use piet::{RenderContext, Text, TextAttribute, TextLayoutBuilder};

use piet_gpu::{test_scenes, PietGpuRenderContext, Renderer};
use piet_gpu::{test_scenes, PietGpuRenderContext, RenderDriver, Renderer};

#[cfg_attr(target_os = "android", ndk_glue::main(backtrace = "on"))]
fn main() {
Expand All @@ -34,12 +34,9 @@ struct MyHandle {
// State required to render and present the contents
struct GfxState {
session: Session,
renderer: Renderer,
render_driver: RenderDriver,
swapchain: Swapchain,
current_frame: usize,
submitted: [Option<SubmittedCmdBuf>; NUM_FRAMES],
cmd_bufs: [Option<CmdBuf>; NUM_FRAMES],
query_pools: Vec<QueryPool>,
present_semaphores: Vec<Semaphore>,
}

Expand Down Expand Up @@ -110,22 +107,15 @@ impl GfxState {
let present_semaphores = (0..NUM_FRAMES)
.map(|_| session.create_semaphore())
.collect::<Result<Vec<_>, Error>>()?;
let query_pools = (0..NUM_FRAMES)
.map(|_| session.create_query_pool(Renderer::QUERY_POOL_SIZE))
.collect::<Result<Vec<_>, Error>>()?;
let submitted = Default::default();
let cmd_bufs = Default::default();

let renderer = Renderer::new(&session, width, height, NUM_FRAMES)?;
let render_driver = RenderDriver::new(&session, NUM_FRAMES, renderer);

Ok(GfxState {
session,
renderer,
render_driver,
swapchain,
current_frame,
submitted,
cmd_bufs,
query_pools,
present_semaphores,
})
}
Expand All @@ -137,51 +127,47 @@ impl GfxState {
let frame_idx = self.current_frame % NUM_FRAMES;
let mut info_string = String::new();

if let Some(submitted) = self.submitted[frame_idx].take() {
self.cmd_bufs[frame_idx] = submitted.wait().unwrap();
let ts = self
.session
.fetch_query_pool(&self.query_pools[frame_idx])
.unwrap();
info_string = format!("{:.1}ms", ts.last().unwrap() * 1e3);
println!("render time: {:?}", ts);
if self.current_frame >= NUM_FRAMES {
let stats = self
.render_driver
.get_timing_stats(&self.session, frame_idx);
info_string = stats.short_summary();
println!("{}", info_string);
}
let mut ctx = PietGpuRenderContext::new();
test_scenes::render_anim_frame(&mut ctx, self.current_frame);
//test_scenes::render_tiger(&mut ctx);
render_info_string(&mut ctx, &info_string);
if let Err(e) = self.renderer.upload_render_ctx(&mut ctx, frame_idx) {
if let Err(e) = self
.render_driver
.upload_render_ctx(&self.session, &mut ctx)
{
println!("error in uploading: {}", e);
}
let (image_idx, acquisition_semaphore) = self.swapchain.next().unwrap();
let swap_image = self.swapchain.image(image_idx);
let query_pool = &self.query_pools[frame_idx];
let mut cmd_buf = self.cmd_bufs[frame_idx]
.take()
.unwrap_or_else(|| self.session.cmd_buf().unwrap());
cmd_buf.begin();
self.renderer.record(&mut cmd_buf, &query_pool, frame_idx);
self.render_driver.run_coarse(&self.session).unwrap();
let target = self.render_driver.record_fine(&self.session).unwrap();
let cmd_buf = target.cmd_buf;

// Image -> Swapchain
cmd_buf.image_barrier(&swap_image, ImageLayout::Undefined, ImageLayout::BlitDst);
cmd_buf.blit_image(&self.renderer.image_dev, &swap_image);
cmd_buf.blit_image(target.image, &swap_image);
cmd_buf.image_barrier(&swap_image, ImageLayout::BlitDst, ImageLayout::Present);
cmd_buf.finish();

self.submitted[frame_idx] = Some(
self.session
.run_cmd_buf(
cmd_buf,
&[&acquisition_semaphore],
&[&self.present_semaphores[frame_idx]],
)
.unwrap(),
);

self.render_driver
.submit(
&self.session,
&[&acquisition_semaphore],
&[&self.present_semaphores[frame_idx]],
)
.unwrap();

self.swapchain
.present(image_idx, &[&self.present_semaphores[frame_idx]])
.unwrap();

self.render_driver.next_buffer();
self.current_frame += 1;
}
}
Expand Down
47 changes: 13 additions & 34 deletions piet-gpu/bin/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use clap::{App, Arg};

use piet_gpu_hal::{BufferUsage, Error, Instance, InstanceFlags, Session};

use piet_gpu::{test_scenes, PicoSvg, PietGpuRenderContext, Renderer};
use piet_gpu::{test_scenes, PicoSvg, PietGpuRenderContext, RenderDriver, Renderer};

const WIDTH: usize = 2048;
const HEIGHT: usize = 1536;
Expand Down Expand Up @@ -231,9 +231,6 @@ fn main() -> Result<(), Error> {
let device = instance.device(None)?;
let session = Session::new(device);

let mut cmd_buf = session.cmd_buf()?;
let query_pool = session.create_query_pool(Renderer::QUERY_POOL_SIZE)?;

let mut ctx = PietGpuRenderContext::new();
if let Some(input) = matches.value_of("INPUT") {
let mut scale = matches
Expand All @@ -253,40 +250,22 @@ fn main() -> Result<(), Error> {
test_scenes::render_blend_grid(&mut ctx);
}

let mut renderer = Renderer::new(&session, WIDTH, HEIGHT, 1)?;
renderer.upload_render_ctx(&mut ctx, 0)?;
let renderer = Renderer::new(&session, WIDTH, HEIGHT, 1)?;
let mut render_driver = RenderDriver::new(&session, 1, renderer);
let start = std::time::Instant::now();
render_driver.upload_render_ctx(&session, &mut ctx)?;
let image_usage = BufferUsage::MAP_READ | BufferUsage::COPY_DST;
let image_buf = session.create_buffer((WIDTH * HEIGHT * 4) as u64, image_usage)?;

cmd_buf.begin();
renderer.record(&mut cmd_buf, &query_pool, 0);
cmd_buf.copy_image_to_buffer(&renderer.image_dev, &image_buf);
cmd_buf.finish_timestamps(&query_pool);
cmd_buf.host_barrier();
cmd_buf.finish();
let start = std::time::Instant::now();
let submitted = session.run_cmd_buf(cmd_buf, &[], &[])?;
submitted.wait()?;
render_driver.run_coarse(&session)?;
let target = render_driver.record_fine(&session)?;
target
.cmd_buf
.copy_image_to_buffer(target.image, &image_buf);
render_driver.submit(&session, &[], &[])?;
render_driver.wait(&session);
println!("elapsed = {:?}", start.elapsed());
let ts = session.fetch_query_pool(&query_pool).unwrap();
if !ts.is_empty() {
println!("Element kernel time: {:.3}ms", ts[0] * 1e3);
println!(
"Tile allocation kernel time: {:.3}ms",
(ts[1] - ts[0]) * 1e3
);
println!("Coarse path kernel time: {:.3}ms", (ts[2] - ts[1]) * 1e3);
println!("Backdrop kernel time: {:.3}ms", (ts[3] - ts[2]) * 1e3);
println!("Binning kernel time: {:.3}ms", (ts[4] - ts[3]) * 1e3);
println!("Coarse raster kernel time: {:.3}ms", (ts[5] - ts[4]) * 1e3);
println!("Render kernel time: {:.3}ms", (ts[6] - ts[5]) * 1e3);
}

/*
let mut data: Vec<u32> = Default::default();
renderer.memory_buf_dev.read(&mut data).unwrap();
piet_gpu::dump_k1_data(&data[2..]);
*/
render_driver.get_timing_stats(&session, 0).print_summary();

let mut img_data: Vec<u8> = Default::default();
// Note: because png can use a `&[u8]` slice, we could avoid an extra copy
Expand Down
63 changes: 19 additions & 44 deletions piet-gpu/bin/winit.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use piet::kurbo::Point;
use piet::{RenderContext, Text, TextAttribute, TextLayoutBuilder};
use piet_gpu_hal::{CmdBuf, Error, ImageLayout, Instance, Session, SubmittedCmdBuf};
use piet_gpu_hal::{Error, ImageLayout, Instance, Session};

use piet_gpu::{test_scenes, PicoSvg, PietGpuRenderContext, Renderer};
use piet_gpu::{test_scenes, PicoSvg, PietGpuRenderContext, RenderDriver, Renderer};

use clap::{App, Arg};

Expand Down Expand Up @@ -69,13 +69,9 @@ fn main() -> Result<(), Error> {
let present_semaphores = (0..NUM_FRAMES)
.map(|_| session.create_semaphore())
.collect::<Result<Vec<_>, Error>>()?;
let query_pools = (0..NUM_FRAMES)
.map(|_| session.create_query_pool(Renderer::QUERY_POOL_SIZE))
.collect::<Result<Vec<_>, Error>>()?;
let mut cmd_bufs: [Option<CmdBuf>; NUM_FRAMES] = Default::default();
let mut submitted: [Option<SubmittedCmdBuf>; NUM_FRAMES] = Default::default();

let mut renderer = Renderer::new(&session, WIDTH, HEIGHT, NUM_FRAMES)?;
let renderer = Renderer::new(&session, WIDTH, HEIGHT, NUM_FRAMES)?;
let mut render_driver = RenderDriver::new(&session, NUM_FRAMES, renderer);
let mut mode = 0usize;

event_loop.run(move |event, _, control_flow| {
Expand Down Expand Up @@ -106,26 +102,13 @@ fn main() -> Result<(), Error> {
Event::RedrawRequested(window_id) if window_id == window.id() => {
let frame_idx = current_frame % NUM_FRAMES;

if let Some(submitted) = submitted[frame_idx].take() {
cmd_bufs[frame_idx] = submitted.wait().unwrap();
let ts = session.fetch_query_pool(&query_pools[frame_idx]).unwrap();
if !ts.is_empty() {
info_string = format!(
"{:.3}ms :: e:{:.3}ms|alloc:{:.3}ms|cp:{:.3}ms|bd:{:.3}ms|bin:{:.3}ms|cr:{:.3}ms|r:{:.3}ms",
ts[10] * 1e3,
ts[0] * 1e3,
(ts[1] - ts[0]) * 1e3,
(ts[2] - ts[1]) * 1e3,
(ts[4] - ts[3]) * 1e3,
(ts[6] - ts[5]) * 1e3,
(ts[8] - ts[7]) * 1e3,
(ts[10] - ts[9]) * 1e3,
);
}
if current_frame >= NUM_FRAMES {
let stats = render_driver.get_timing_stats(&session, frame_idx);
info_string = stats.short_summary();
}

let mut ctx = PietGpuRenderContext::new();
let test_blend = true;
let test_blend = false;
if let Some(svg) = &svg {
test_scenes::render_svg(&mut ctx, svg);
} else if test_blend {
Expand Down Expand Up @@ -168,49 +151,41 @@ fn main() -> Result<(), Error> {
test_scenes::render_anim_frame(&mut ctx, current_frame);
}
render_info_string(&mut ctx, &info_string);
if let Err(e) = renderer.upload_render_ctx(&mut ctx, frame_idx) {
if let Err(e) = render_driver.upload_render_ctx(&session, &mut ctx) {
println!("error in uploading: {}", e);
}

let (image_idx, acquisition_semaphore) = swapchain.next().unwrap();
let swap_image = swapchain.image(image_idx);
let query_pool = &query_pools[frame_idx];
let mut cmd_buf = cmd_bufs[frame_idx].take().unwrap_or_else(|| session.cmd_buf().unwrap());
cmd_buf.begin();
renderer.record(&mut cmd_buf, &query_pool, frame_idx);
render_driver.run_coarse(&session).unwrap();
let target = render_driver.record_fine(&session).unwrap();
let cmd_buf = target.cmd_buf;

// Image -> Swapchain
cmd_buf.image_barrier(
&swap_image,
ImageLayout::Undefined,
ImageLayout::BlitDst,
);
cmd_buf.blit_image(&renderer.image_dev, &swap_image);
cmd_buf.blit_image(target.image, &swap_image);
cmd_buf.image_barrier(&swap_image, ImageLayout::BlitDst, ImageLayout::Present);
cmd_buf.finish();

submitted[frame_idx] = Some(session
.run_cmd_buf(
cmd_buf,
render_driver
.submit(
&session,
&[&acquisition_semaphore],
&[&present_semaphores[frame_idx]],
)
.unwrap());
.unwrap();

swapchain
.present(image_idx, &[&present_semaphores[frame_idx]])
.unwrap();

render_driver.next_buffer();
current_frame += 1;
}
Event::LoopDestroyed => {
for cmd_buf in &mut submitted {
// Wait for command list submission, otherwise dropping of renderer may
// cause validation errors (and possibly crashes).
if let Some(cmd_buf) = cmd_buf.take() {
cmd_buf.wait().unwrap();
}
}
render_driver.wait_all(&session);
}
_ => (),
}
Expand Down
9 changes: 6 additions & 3 deletions piet-gpu/shader/backdrop.comp
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,15 @@ shared Alloc sh_row_alloc[BACKDROP_WG];
shared uint sh_row_width[BACKDROP_WG];

void main() {
if (!check_deps(STAGE_BINNING | STAGE_TILE_ALLOC | STAGE_PATH_COARSE)) {
return;
}

uint th_ix = gl_LocalInvocationIndex;
uint element_ix = gl_GlobalInvocationID.x;

// Work assignment: 1 thread : 1 path element
uint row_count = 0;
bool mem_ok = mem_error == NO_ERROR;
if (gl_LocalInvocationID.y == 0) {
if (element_ix < conf.n_elements) {
// Possible TODO: it's not necessary to process backdrops of stroked paths.
Expand All @@ -68,7 +71,7 @@ void main() {
row_count = 0;
}
Alloc path_alloc = new_alloc(
path.tiles.offset, (path.bbox.z - path.bbox.x) * (path.bbox.w - path.bbox.y) * Tile_size, mem_ok);
path.tiles.offset, (path.bbox.z - path.bbox.x) * (path.bbox.w - path.bbox.y) * Tile_size, true);
sh_row_alloc[th_ix] = path_alloc;
}
sh_row_count[th_ix] = row_count;
Expand Down Expand Up @@ -98,7 +101,7 @@ void main() {
}
}
uint width = sh_row_width[el_ix];
if (width > 0 && mem_ok) {
if (width > 0) {
// Process one row sequentially
// Read backdrop value per tile and prefix sum it
Alloc tiles_alloc = sh_row_alloc[el_ix];
Expand Down
Loading

0 comments on commit bfa4abf

Please sign in to comment.