Skip to content

Commit

Permalink
Update to latest rework
Browse files Browse the repository at this point in the history
  • Loading branch information
dcvz committed Jul 6, 2023
1 parent 78d07ad commit d815828
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 149 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name = "helix"
crate-type = ["lib", "staticlib"]

[features]
default = ["f3dex2", "opengl_renderer"]
default = ["f3dex2", "wgpu_renderer"]

# Graphics Features
f3dex2 = ["fast3d/f3dex2"]
Expand Down Expand Up @@ -47,6 +47,7 @@ arie = "0.2.0"
fast3d = { version = "0.3.1", default-features = false }
fast3d-glium-renderer = { version = "0.3.1", optional = true }
fast3d-wgpu-renderer = { version = "0.3.1", optional = true }
rustc-hash = "1.1.0"

[patch.crates-io]
#fast3d = { path = "../../fast3d-rs/fast3d" }
Expand Down
18 changes: 8 additions & 10 deletions src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,14 +224,7 @@ impl<'a> Gui<'a> {
// Grab the frame
let mut frame = self.gfx_renderer.get_current_texture().unwrap();

// Render RCP output
self.gfx_renderer.process_rcp_output(
&mut frame,
&mut self.rcp_output,
&self.rcp.rdp.output_dimensions,
)?;

// Render ImGui on top of any game content
// Draw the UI
let ui = self.imgui.new_frame();
ui.main_menu_bar(|| (self.draw_menu_callback)(ui));
(self.draw_windows_callback)(ui);
Expand All @@ -241,9 +234,14 @@ impl<'a> Gui<'a> {
self.gfx_renderer.prepare_render(&mut self.platform, ui);
}

// Render RCPOutput and ImGui content
let draw_data = self.imgui.render();
self.gfx_renderer
.draw_imgui_content(&mut frame, draw_data)?;
self.gfx_renderer.draw_content(
&mut frame,
&mut self.rcp_output,
&self.rcp.rdp.output_dimensions,
draw_data,
)?;

// Clear the draw calls
self.rcp_output.clear_draw_calls();
Expand Down
16 changes: 4 additions & 12 deletions src/gui/glium_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,33 +97,25 @@ impl<'a> Renderer<'a> {
Some(frame)
}

pub fn process_rcp_output(
pub fn draw_content(
&mut self,
frame: &mut Frame,
rcp_output: &mut RCPOutput,
output_size: &OutputDimensions,
imgui_draw_data: &imgui::DrawData,
) -> anyhow::Result<()> {
// Prepare the context device
self.graphics_device.start_frame(frame);

// Process the RCP output
self.render_game(frame, rcp_output, output_size)?;

// Finish rendering
self.graphics_device.end_frame();
// Render the ImGui content
self.renderer.render(frame, imgui_draw_data)?;

Ok(())
}

pub fn draw_imgui_content(
&mut self,
frame: &mut Frame,
draw_data: &imgui::DrawData,
) -> anyhow::Result<()> {
self.renderer.render(frame, draw_data)?;
Ok(())
}

pub fn finish_render(&mut self, frame: Frame) -> anyhow::Result<()> {
frame.finish()?;
Ok(())
Expand Down
206 changes: 80 additions & 126 deletions src/gui/wgpu_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,39 @@ use fast3d::rdp::OutputDimensions;
use fast3d_wgpu_renderer::defines::{PipelineConfig, PipelineId};
use fast3d_wgpu_renderer::wgpu_device::WgpuGraphicsDevice;

const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;

fn create_depth_texture(
config: &wgpu::SurfaceConfiguration,
device: &wgpu::Device,
) -> wgpu::TextureView {
let depth_texture = device.create_texture(&wgpu::TextureDescriptor {
size: wgpu::Extent3d {
width: config.width,
height: config.height,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: DEPTH_FORMAT,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
label: None,
view_formats: &[],
});

depth_texture.create_view(&wgpu::TextureViewDescriptor::default())
}

pub struct Renderer<'a> {
window: winit::window::Window,
surface: wgpu::Surface,
device: wgpu::Device,
queue: wgpu::Queue,
surface_config: wgpu::SurfaceConfiguration,
depth_texture: wgpu::TextureView,
renderer: imgui_wgpu::Renderer,
graphics_device: WgpuGraphicsDevice<'a>,
current_frame_texture: Option<wgpu::TextureView>,
}

impl<'a> Renderer<'a> {
Expand Down Expand Up @@ -66,12 +90,13 @@ impl<'a> Renderer<'a> {
let mut surface_config = surface
.get_default_config(&adapter, size.width, size.height)
.ok_or(anyhow::anyhow!("Failed to get default surface config"))?;

let surface_view_format = surface_config.format.add_srgb_suffix();
surface_config.view_formats.push(surface_view_format);
surface_config.format = wgpu::TextureFormat::Bgra8Unorm;

surface.configure(&device, &surface_config);

// Create the depth texture
let depth_texture = create_depth_texture(&surface_config, &device);

// Create Renderer
let renderer_config = imgui_wgpu::RendererConfig {
texture_format: surface_config.format,
Expand All @@ -81,17 +106,17 @@ impl<'a> Renderer<'a> {
let renderer = imgui_wgpu::Renderer::new(imgui, &device, &queue, renderer_config);

// Create graphics device
let graphics_device = WgpuGraphicsDevice::new(&surface_config, &device);
let graphics_device = WgpuGraphicsDevice::new(&device);

Ok(Self {
window,
surface,
device,
queue,
surface_config,
depth_texture,
renderer,
graphics_device,
current_frame_texture: None,
})
}

Expand Down Expand Up @@ -152,6 +177,7 @@ impl<'a> Renderer<'a> {
self.surface_config.width = width.max(1);
self.surface_config.height = height.max(1);
self.surface.configure(&self.device, &self.surface_config);
self.depth_texture = create_depth_texture(&self.surface_config, &self.device);
self.graphics_device
.resize(&self.surface_config, &self.device);
}
Expand All @@ -165,62 +191,79 @@ impl<'a> Renderer<'a> {
}
};

self.current_frame_texture = Some(
frame
.texture
.create_view(&wgpu::TextureViewDescriptor::default()),
);

Some(frame)
}

pub fn process_rcp_output(
pub fn draw_content(
&mut self,
_frame: &mut Frame,
frame: &mut Frame,
rcp_output: &mut RCPOutput,
output_size: &OutputDimensions,
imgui_draw_data: &imgui::DrawData,
) -> anyhow::Result<()> {
// Prepare the context device
self.graphics_device.update_frame_count();
let frame_texture = frame
.texture
.create_view(&wgpu::TextureViewDescriptor::default());

// Setup encoder that the RDP will use
let mut encoder: wgpu::CommandEncoder =
self.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Game Draw Command Encoder"),
label: Some("Game Render Pass Command Encoder"),
});

let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Game Render Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &frame_texture,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
store: true,
},
})],
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
view: &self.depth_texture,
depth_ops: Some(wgpu::Operations {
load: wgpu::LoadOp::Clear(1.0),
store: true,
}),
stencil_ops: None,
}),
});

// Prepare the context device
self.graphics_device.update_frame_count();

// Process the RCP output
self.render_game(&mut encoder, rcp_output, output_size)?;
self.graphics_device
.process_rcp_output(&self.device, &self.queue, self.surface_config.format, rcp_output);

// Finish game encoding and submit
self.queue.submit(Some(encoder.finish()));
// Draw the RCP output
self.graphics_device.draw(output_size, &mut rpass);

Ok(())
}
// Drop the render pass
drop(rpass);

// Finish encoding and submit
self.queue.submit(Some(encoder.finish()));

pub fn draw_imgui_content(
&mut self,
_frame: &mut Frame,
draw_data: &imgui::DrawData,
) -> anyhow::Result<()> {
// due to bug in macos or imgui-wgpu, we need to check for wrong texture size
let fb_width = draw_data.display_size[0] * draw_data.framebuffer_scale[0];
let fb_height = draw_data.display_size[1] * draw_data.framebuffer_scale[1];
let fb_width = imgui_draw_data.display_size[0] * imgui_draw_data.framebuffer_scale[0];
let fb_height = imgui_draw_data.display_size[1] * imgui_draw_data.framebuffer_scale[1];
if fb_width as u32 == u32::MAX || fb_height as u32 == u32::MAX {
return Ok(());
}

let mut encoder: wgpu::CommandEncoder =
self.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("ImGui Command Encoder"),
label: Some("ImGui Render Pass Command Encoder"),
});

let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("ImGui Render Pass"),
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
view: &self.current_frame_texture.as_ref().unwrap(),
view: &frame_texture,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load,
Expand All @@ -230,110 +273,21 @@ impl<'a> Renderer<'a> {
depth_stencil_attachment: None,
});

// Render the ImGui content
self.renderer
.render(draw_data, &self.queue, &self.device, &mut rpass)?;
.render(imgui_draw_data, &self.queue, &self.device, &mut rpass)?;

// Drop the render pass
drop(rpass);

// Finish encoding and submit
self.queue.submit(Some(encoder.finish()));

Ok(())
}

pub fn finish_render(&mut self, frame: Frame) -> anyhow::Result<()> {
frame.present();
self.current_frame_texture = None;
Ok(())
}

// MARK: - Helpers

fn render_game(
&mut self,
encoder: &mut wgpu::CommandEncoder,
rcp_output: &mut RCPOutput,
output_size: &OutputDimensions,
) -> anyhow::Result<()> {
// omit the last draw call, because we know we that's an extra from the last flush
// for draw_call in &self.rcp_output.draw_calls[..self.rcp_output.draw_calls.len() - 1] {
for (index, draw_call) in rcp_output
.draw_calls
.iter()
.take(rcp_output.draw_calls.len() - 1)
.enumerate()
{
assert!(!draw_call.vbo.vbo.is_empty());

self.graphics_device
.update_current_height(draw_call.viewport.w as i32);

// loop through textures and bind them
for (index, tex_cache_id) in draw_call.texture_indices.iter().enumerate() {
let sampler = draw_call.samplers[index];
assert_eq!(tex_cache_id.is_none(), sampler.is_none());

if let Some(tex_cache_id) = tex_cache_id {
let texture = rcp_output.texture_cache.get_mut(*tex_cache_id).unwrap();
let sampler = sampler.unwrap();

self.graphics_device.bind_texture(
&self.device,
&self.queue,
index,
texture,
&sampler,
);
}
}

// select shader program
self.graphics_device.select_program(
&self.device,
draw_call.shader_id,
draw_call.shader_config,
);

// set uniforms
self.graphics_device.update_uniforms(
&self.queue,
draw_call.projection_matrix,
&draw_call.fog,
&draw_call.uniforms,
);

// create pipeline
let pipeline_config = PipelineConfig {
shader: draw_call.shader_id,
blend_state: draw_call.blend_state,
cull_mode: draw_call.cull_mode,
depth_stencil: draw_call.stencil,
};
let pipeline_id = PipelineId(pipeline_config);

self.graphics_device.configure_pipeline(
&self.device,
self.surface_config.format,
pipeline_id,
draw_call.blend_state,
draw_call.cull_mode,
draw_call.stencil,
);

// render triangles to texture
self.graphics_device.draw_triangles(
index,
&self.current_frame_texture.as_ref().unwrap(),
&self.device,
&self.queue,
encoder,
pipeline_id,
output_size,
&draw_call.viewport,
draw_call.scissor,
&draw_call.vbo.vbo,
draw_call.vbo.num_tris,
);
}

Ok(())
}
}

0 comments on commit d815828

Please sign in to comment.