Bevy: Allow bevy to own rendering resources to avoid locking.

Created on 23 Aug 2020  路  4Comments  路  Source: bevyengine/bevy

Goals:

Avoid locking to access resources when rendering. WGPU allows you to wrap all rendering resources in Arc which means we can avoid locks by directly storing data in bevy vs having the WGPU plugin store data.

Solution A:

Remove Arc<RwLock<HashMap<ResourceId, Resource>>>. Introduce WGPU types directly into bevy_render while also maintaining the abstraction layer. We can accomplish this by using enums instead.

Pros:

  1. Supports multiple rendering API backend's
  2. Easy to implement and understand.
  3. You can iteratively add new rendering API's to bevy.

Cons:

  1. Makes bevy less modular.
  2. Matching might have an impact on performance although it seems small.

Example:

use std::sync::Arc;

mod wgpu {
    pub struct Texture {

    }
}

mod other {
    pub struct Texture {

    }
}

pub enum Texture {
    Wgpu(wgpu::Texture),
    Other(other::Texture),
}

pub trait RenderContext {
    fn create_texture(&self) -> Arc<Texture>;
}

pub struct WgpuRenderContext;

impl RenderContext for WgpuRenderContext {
    fn create_texture(&self) -> Arc<Texture> {
        Arc::new(Texture::Wgpu(wgpu::Texture { }))
    }
}

pub struct OtherRenderContext;

impl RenderContext for OtherRenderContext {
    fn create_texture(&self) -> Arc<Texture> {
        Arc::new(Texture::Other(other::Texture { }))
    }
}

fn main() {
    let wgpu_render_context = WgpuRenderContext {
    };
    wgpu_render_context.create_texture();

    let other_render_context = OtherRenderContext {
    };
    other_render_context.create_texture();
}

Playground Link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b184ea7b5338a23971d5bd51ba66e489

enhancement

Most helpful comment

Did you forget solution B?

All 4 comments

Did you forget solution B?

I was kinda hoping someone else would present a Solution B! 馃槃 You could use generics, but that gets overly complex in a lot of cases. @aclysma also suggested using box/downcast. It might be a better soultion. I think some sort of benchmark test between the two options might be a good way to move forward.

I've opened a draft PR with a partial implementation with Textures here:
https://github.com/bevyengine/bevy/pull/302

Some challenges I encountered:

  1. Bevy currently doesn't let you have multiple texture views.
  2. The swap chain also use texture id's which is a bit weird.
  3. wgpu diagnostics can't keep track of total views/textures. I think we can fix that though.

You noted that performance might suffer, but actually, from my experience, performance will increase (though probably stay the same because the bottleneck here isn't calling wgpu apis). Matching on enums let's the compiler do a lot more inlining, whereas a dynamic trait call doesn't allow that.

Was this page helpful?
0 / 5 - 0 ratings