Skip to content

Commit 30f6405

Browse files
committed
multigpu: Lift some unnecessary R-constraints
1 parent 0f68962 commit 30f6405

File tree

1 file changed

+113
-35
lines changed
  • src/backend/renderer/multigpu

1 file changed

+113
-35
lines changed

src/backend/renderer/multigpu/mod.rs

Lines changed: 113 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -801,15 +801,14 @@ impl<'render, 'target, R: GraphicsApi, T: GraphicsApi> MultiRenderer<'render, 't
801801
}
802802

803803
/// A Framebuffer of a [`MultiRenderer`].
804-
pub struct MultiFramebuffer<'buffer, R: GraphicsApi, T: GraphicsApi>(MultiFramebufferInternal<'buffer, R, T>);
805-
enum MultiFramebufferInternal<'buffer, R: GraphicsApi, T: GraphicsApi> {
806-
Render(<<R::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>),
804+
pub struct MultiFramebuffer<'buffer, T: GraphicsApi>(MultiFramebufferInternal<'buffer, T>);
805+
enum MultiFramebufferInternal<'buffer, T: GraphicsApi> {
806+
Render(<<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>),
807807
Target(<<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>),
808808
}
809809

810-
impl<'buffer, R: GraphicsApi, T: GraphicsApi> fmt::Debug for MultiFramebuffer<'buffer, R, T>
810+
impl<'buffer, T: GraphicsApi> fmt::Debug for MultiFramebuffer<'buffer, T>
811811
where
812-
<<R::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>: fmt::Debug,
813812
<<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>: fmt::Debug,
814813
{
815814
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -820,7 +819,7 @@ where
820819
}
821820
}
822821

823-
impl<R: GraphicsApi, T: GraphicsApi> Texture for MultiFramebuffer<'_, R, T> {
822+
impl<T: GraphicsApi> Texture for MultiFramebuffer<'_, T> {
824823
fn size(&self) -> Size<i32, BufferCoords> {
825824
match &self.0 {
826825
MultiFramebufferInternal::Render(framebuffer) => framebuffer.size(),
@@ -850,6 +849,28 @@ impl<R: GraphicsApi, T: GraphicsApi> Texture for MultiFramebuffer<'_, R, T> {
850849
}
851850
}
852851

852+
impl<'a, T: GraphicsApi> AsRef<<<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'a>>
853+
for MultiFramebuffer<'a, T>
854+
{
855+
fn as_ref(&self) -> &<<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'a> {
856+
match &self.0 {
857+
MultiFramebufferInternal::Render(fb) => fb,
858+
MultiFramebufferInternal::Target(fb) => fb,
859+
}
860+
}
861+
}
862+
863+
impl<'a, T: GraphicsApi> AsMut<<<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'a>>
864+
for MultiFramebuffer<'a, T>
865+
{
866+
fn as_mut(&mut self) -> &mut <<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'a> {
867+
match &mut self.0 {
868+
MultiFramebufferInternal::Render(fb) => fb,
869+
MultiFramebufferInternal::Target(fb) => fb,
870+
}
871+
}
872+
}
873+
853874
/// [`Frame`] implementation of a [`MultiRenderer`].
854875
///
855876
/// Leaking the frame will potentially keep it from doing necessary copies
@@ -993,10 +1014,8 @@ where
9931014
impl<R: GraphicsApi, T: GraphicsApi, Target> Offscreen<Target> for MultiRenderer<'_, '_, R, T>
9941015
where
9951016
<T::Device as ApiDevice>::Renderer: Offscreen<Target>,
996-
<R::Device as ApiDevice>::Renderer: Offscreen<Target>,
9971017
// We need these because the Bind-impl does and Offscreen requires Bind
9981018
<T::Device as ApiDevice>::Renderer: Bind<Target>,
999-
<R::Device as ApiDevice>::Renderer: Bind<Target>,
10001019
// We need these because the Renderer-impl does and Offscreen requires Bind, which requires Unbind, which requires Renderer
10011020
R: 'static,
10021021
R::Error: 'static,
@@ -1021,18 +1040,21 @@ where
10211040
.create_buffer(format, size)
10221041
.map_err(Error::Target)
10231042
} else {
1024-
self.render
1025-
.renderer_mut()
1026-
.create_buffer(format, size)
1027-
.map_err(Error::Render)
1043+
// SAFETY: We know this is safe, because `self.target` can only be `None` if R == T.
1044+
let renderer = unsafe {
1045+
std::mem::transmute::<
1046+
&mut <R::Device as ApiDevice>::Renderer,
1047+
&mut <T::Device as ApiDevice>::Renderer,
1048+
>(self.render.renderer_mut())
1049+
};
1050+
renderer.create_buffer(format, size).map_err(Error::Target)
10281051
}
10291052
}
10301053
}
10311054

10321055
impl<R: GraphicsApi, T: GraphicsApi, Target> Bind<Target> for MultiRenderer<'_, '_, R, T>
10331056
where
10341057
<T::Device as ApiDevice>::Renderer: Bind<Target>,
1035-
<R::Device as ApiDevice>::Renderer: Bind<Target>,
10361058
// We need this because the Renderer-impl does and Bind requires Unbind, which requires Renderer
10371059
R: 'static,
10381060
R::Error: 'static,
@@ -1058,20 +1080,32 @@ where
10581080
.map(MultiFramebuffer)
10591081
.map_err(Error::Target)
10601082
} else {
1061-
self.render
1062-
.renderer_mut()
1083+
// SAFETY: We know this is safe, because `self.target` can only be `None` if R == T.
1084+
let renderer = unsafe {
1085+
std::mem::transmute::<
1086+
&mut <R::Device as ApiDevice>::Renderer,
1087+
&mut <T::Device as ApiDevice>::Renderer,
1088+
>(self.render.renderer_mut())
1089+
};
1090+
renderer
10631091
.bind(bind)
10641092
.map(MultiFramebufferInternal::Render)
10651093
.map(MultiFramebuffer)
1066-
.map_err(Error::Render)
1094+
.map_err(Error::Target)
10671095
}
10681096
}
10691097

10701098
fn supported_formats(&self) -> Option<FormatSet> {
10711099
if let Some(target) = self.target.as_ref() {
10721100
Bind::<Target>::supported_formats(target.device.renderer())
10731101
} else {
1074-
Bind::<Target>::supported_formats(self.render.renderer())
1102+
// SAFETY: We know this is safe, because `self.target` can only be `None` if R == T.
1103+
let renderer = unsafe {
1104+
std::mem::transmute::<&<R::Device as ApiDevice>::Renderer, &<T::Device as ApiDevice>::Renderer>(
1105+
self.render.renderer(),
1106+
)
1107+
};
1108+
Bind::<Target>::supported_formats(renderer)
10751109
}
10761110
}
10771111
}
@@ -1091,7 +1125,7 @@ where
10911125
{
10921126
type Error = Error<R, T>;
10931127
type TextureId = MultiTexture;
1094-
type Framebuffer<'buffer> = MultiFramebuffer<'buffer, R, T>;
1128+
type Framebuffer<'buffer> = MultiFramebuffer<'buffer, T>;
10951129
type Frame<'frame, 'buffer>
10961130
= MultiFrame<'render, 'target, 'frame, 'buffer, R, T>
10971131
where
@@ -1228,11 +1262,19 @@ where
12281262
let mut target = None;
12291263
let mut new_framebuffer = None;
12301264
let frame = match &mut framebuffer.0 {
1231-
MultiFramebufferInternal::Render(framebuffer) => self
1232-
.render
1233-
.renderer_mut()
1234-
.render(framebuffer, size, dst_transform)
1235-
.map_err(Error::Render)?,
1265+
MultiFramebufferInternal::Render(framebuffer) => {
1266+
// SAFETY: We know this is fine, because target can only be `None` (and thus this framebuffer be of variant `Render`), if R == T.
1267+
let framebuffer = unsafe {
1268+
std::mem::transmute::<
1269+
&mut <<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>,
1270+
&mut <<R::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'buffer>,
1271+
>(framebuffer)
1272+
};
1273+
self.render
1274+
.renderer_mut()
1275+
.render(framebuffer, size, dst_transform)
1276+
.map_err(Error::Render)?
1277+
}
12361278
MultiFramebufferInternal::Target(target_framebuffer) => {
12371279
let (target_device, render_framebuffer, texture, format) = target_state.unwrap();
12381280
target = Some(TargetFrameData {
@@ -2792,7 +2834,7 @@ where
27922834
#[profiling::function]
27932835
fn copy_framebuffer(
27942836
&mut self,
2795-
framebuffer: &MultiFramebuffer<'_, R, T>,
2837+
framebuffer: &MultiFramebuffer<'_, T>,
27962838
region: Rectangle<i32, BufferCoords>,
27972839
format: Fourcc,
27982840
) -> Result<Self::TextureMapping, <Self as RendererSuper>::Error> {
@@ -2806,12 +2848,20 @@ where
28062848
.map(|mapping| MultiTextureMapping(TextureMappingInternal::Either(mapping)))
28072849
.map_err(Error::Target)
28082850
}
2809-
MultiFramebufferInternal::Render(fb) => self
2810-
.render
2811-
.renderer_mut()
2812-
.copy_framebuffer(fb, region, format)
2813-
.map(|mapping| MultiTextureMapping(TextureMappingInternal::Or(mapping)))
2814-
.map_err(Error::Render),
2851+
MultiFramebufferInternal::Render(fb) => {
2852+
// SAFETY: We know this is fine, because target can only be `None` (and thus this framebuffer be of variant `Render`), if R == T.
2853+
let fb = unsafe {
2854+
std::mem::transmute::<
2855+
&<<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'_>,
2856+
&<<R::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'_>,
2857+
>(fb)
2858+
};
2859+
self.render
2860+
.renderer_mut()
2861+
.copy_framebuffer(fb, region, format)
2862+
.map(|mapping| MultiTextureMapping(TextureMappingInternal::Or(mapping)))
2863+
.map_err(Error::Render)
2864+
}
28152865
}
28162866
}
28172867

@@ -2867,7 +2917,7 @@ where
28672917
}
28682918
}
28692919

2870-
impl<'frame, 'buffer, R: GraphicsApi, T: GraphicsApi> BlitFrame<MultiFramebuffer<'buffer, R, T>>
2920+
impl<'frame, 'buffer, R: GraphicsApi, T: GraphicsApi> BlitFrame<MultiFramebuffer<'buffer, T>>
28712921
for MultiFrame<'_, '_, 'frame, 'buffer, R, T>
28722922
where
28732923
<<R::Device as ApiDevice>::Renderer as RendererSuper>::Frame<'frame, 'buffer>:
@@ -2886,7 +2936,7 @@ where
28862936
#[profiling::function]
28872937
fn blit_to(
28882938
&mut self,
2889-
to: &mut MultiFramebuffer<'buffer, R, T>,
2939+
to: &mut MultiFramebuffer<'buffer, T>,
28902940
src: Rectangle<i32, Physical>,
28912941
dst: Rectangle<i32, Physical>,
28922942
filter: TextureFilter,
@@ -2907,6 +2957,13 @@ where
29072957
let MultiFramebufferInternal::Render(ref mut to_fb) = &mut to.0 else {
29082958
unreachable!()
29092959
};
2960+
// SAFETY: We know this is fine, because target can only be `None` (and thus this framebuffer be of variant `Render`), if R == T.
2961+
let to_fb = unsafe {
2962+
std::mem::transmute::<
2963+
&mut <<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'_>,
2964+
&mut <<R::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'_>,
2965+
>(to_fb)
2966+
};
29102967
self.frame
29112968
.as_mut()
29122969
.unwrap()
@@ -2919,7 +2976,7 @@ where
29192976
#[profiling::function]
29202977
fn blit_from(
29212978
&mut self,
2922-
from: &MultiFramebuffer<'buffer, R, T>,
2979+
from: &MultiFramebuffer<'buffer, T>,
29232980
src: Rectangle<i32, Physical>,
29242981
dst: Rectangle<i32, Physical>,
29252982
filter: TextureFilter,
@@ -2940,6 +2997,13 @@ where
29402997
let MultiFramebufferInternal::Render(ref from_fb) = &from.0 else {
29412998
unreachable!()
29422999
};
3000+
// SAFETY: We know this is fine, because target can only be `None` (and thus this framebuffer be of variant `Render`), if R == T.
3001+
let from_fb = unsafe {
3002+
std::mem::transmute::<
3003+
&<<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'_>,
3004+
&<<R::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'_>,
3005+
>(from_fb)
3006+
};
29433007
self.frame
29443008
.as_mut()
29453009
.unwrap()
@@ -2967,8 +3031,8 @@ where
29673031
#[profiling::function]
29683032
fn blit(
29693033
&mut self,
2970-
from: &MultiFramebuffer<'_, R, T>,
2971-
to: &mut MultiFramebuffer<'_, R, T>,
3034+
from: &MultiFramebuffer<'_, T>,
3035+
to: &mut MultiFramebuffer<'_, T>,
29723036
src: Rectangle<i32, Physical>,
29733037
dst: Rectangle<i32, Physical>,
29743038
filter: TextureFilter,
@@ -2992,6 +3056,20 @@ where
29923056
let MultiFramebufferInternal::Render(ref mut to_fb) = &mut to.0 else {
29933057
unreachable!()
29943058
};
3059+
// SAFETY: We know this is fine, because target can only be `None` (and thus this framebuffer be of variant `Render`), if R == T.
3060+
let from_fb = unsafe {
3061+
std::mem::transmute::<
3062+
&<<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'_>,
3063+
&<<R::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'_>,
3064+
>(from_fb)
3065+
};
3066+
// SAFETY: We know this is fine, because target can only be `None` (and thus this framebuffer be of variant `Render`), if R == T.
3067+
let to_fb = unsafe {
3068+
std::mem::transmute::<
3069+
&mut <<T::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'_>,
3070+
&mut <<R::Device as ApiDevice>::Renderer as RendererSuper>::Framebuffer<'_>,
3071+
>(to_fb)
3072+
};
29953073
self.render
29963074
.renderer_mut()
29973075
.blit(from_fb, to_fb, src, dst, filter)

0 commit comments

Comments
 (0)