Add generic Bound<T> type for grouping consts/other bindable things with bind groups

This commit is contained in:
Imbris 2020-12-04 22:56:10 -05:00 committed by Avi Weinstock
parent 455082a7af
commit 49cb1520ca
15 changed files with 125 additions and 99 deletions

View File

@ -3413,7 +3413,7 @@ impl Hud {
span!(_guard, "render", "Hud::render");
// Don't show anything if the UI is toggled off.
if self.show.ui {
self.ui.render(renderer, Some(globals));
//self.ui.render(renderer, Some(globals));
}
}

View File

@ -224,15 +224,25 @@ impl PlayState for CharSelectionState {
fn name(&self) -> &'static str { "Character Selection" }
fn render(&mut self, renderer: &mut Renderer, _: &Settings) {
let mut drawer = match renderer
.start_recording_frame(self.scene.global_bind_group())
.unwrap()
{
Some(d) => d,
// Couldn't get swap chain texture this fime
None => return,
};
let client = self.client.borrow();
let (humanoid_body, loadout) =
Self::get_humanoid_body_inventory(&self.char_selection_ui, &client);
// Render the scene.
self.scene
.render(renderer, client.get_tick(), humanoid_body, loadout);
//self.scene
// .render(renderer, client.get_tick(), humanoid_body, loadout);
// Draw the UI to the screen.
self.char_selection_ui.render(renderer);
self.char_selection_ui
.render(&mut drawer.third_pass().draw_ui());
}
}

View File

@ -1,6 +1,6 @@
use crate::{
i18n::{Localization, LocalizationHandle},
render::Renderer,
render::UiDrawer,
ui::{
self,
fonts::IcedFonts as Fonts,
@ -1583,9 +1583,7 @@ impl CharSelectionUi {
events
}
// TODO: do we need globals?
pub fn render(&self, renderer: &mut Renderer) { /* self.ui.render(renderer);*/
}
pub fn render<'a>(&'a self, drawer: &mut UiDrawer<'_, 'a>) { self.ui.render(drawer); }
}
#[derive(Default)]

View File

@ -346,7 +346,6 @@ impl PlayState for MainMenuState {
fn name(&self) -> &'static str { "Title" }
fn render(&mut self, renderer: &mut Renderer, _: &Settings) {
// TODO: maybe the drawer should be passed in from above?
let mut drawer = match renderer
.start_recording_frame(self.scene.global_bind_group())
.unwrap()

View File

@ -3,8 +3,6 @@ use crate::render::{
};
pub struct Scene {
// global_data: GlobalModel,
// lod_data: LodData,
bind_group: GlobalsBindGroup,
}

View File

@ -0,0 +1,14 @@
pub struct Bound<T> {
pub(super) bind_group: wgpu::BindGroup,
pub(super) with: T,
}
impl<T> std::ops::Deref for Bound<T> {
type Target = T;
fn deref(&self) -> &Self::Target { &self.with }
}
impl<T> std::ops::DerefMut for Bound<T> {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.with }
}

View File

@ -1,3 +1,4 @@
pub mod bound;
mod buffer;
#[allow(clippy::single_component_path_imports)] // TODO: Pending review in #587
pub mod consts;
@ -11,6 +12,7 @@ pub mod texture;
// Reexports
pub use self::{
bound::Bound,
consts::Consts,
error::RenderError,
instances::Instances,
@ -37,7 +39,7 @@ pub use self::{
ui::{
create_quad as create_ui_quad,
create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri,
Locals as UiLocals, LocalsBindGroup as UiLocalsBindGroup, Mode as UiMode,
BoundLocals as UiBoundLocals, Locals as UiLocals, Mode as UiMode,
TextureBindGroup as UiTextureBindGroup, Vertex as UiVertex,
},
GlobalModel, Globals, GlobalsBindGroup, GlobalsLayouts, Light, Shadow,

View File

@ -1,4 +1,4 @@
use super::super::{AaMode, Consts, GlobalsLayouts, Quad, Texture, Tri};
use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Quad, Texture, Tri};
use bytemuck::{Pod, Zeroable};
use vek::*;
@ -80,9 +80,7 @@ impl Mode {
}
}
pub struct LocalsBindGroup {
pub(in super::super) bind_group: wgpu::BindGroup,
}
pub type BoundLocals = Bound<Consts<Locals>>;
pub struct TextureBindGroup {
pub(in super::super) bind_group: wgpu::BindGroup,
@ -136,7 +134,7 @@ impl UiLayout {
}
}
pub fn bind_locals(&self, device: &wgpu::Device, locals: &Consts<Locals>) -> LocalsBindGroup {
pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts<Locals>) -> BoundLocals {
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: None,
layout: &self.locals,
@ -146,7 +144,10 @@ impl UiLayout {
}],
});
LocalsBindGroup { bind_group }
BoundLocals {
bind_group,
with: locals,
}
}
pub fn bind_texture(&self, device: &wgpu::Device, texture: &Texture) -> TextureBindGroup {

View File

@ -1,4 +1,4 @@
mod bind_group;
mod binding;
mod drawer;
pub use drawer::{Drawer, UiDrawer};

View File

@ -8,6 +8,7 @@ use super::{
};
impl Renderer {
// TODO: rework this to use the Bound type?
pub fn bind_globals(
&self,
global_model: &GlobalModel,
@ -28,7 +29,8 @@ impl Renderer {
)
}
pub fn ui_bind_locals(&self, locals: &Consts<ui::Locals>) -> ui::LocalsBindGroup {
pub fn create_ui_bound_locals(&mut self, vals: &[ui::Locals]) -> ui::BoundLocals {
let locals = self.create_consts(vals);
self.layouts.ui.bind_locals(&self.device, locals)
}

View File

@ -104,12 +104,7 @@ impl<'a> Drawer<'a> {
attachment: &self.tex.view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 1.0,
g: 0.25,
b: 0.5,
a: 0.5,
}),
load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT),
store: true,
},
}],
@ -310,7 +305,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> {
/// set with every draw call
pub fn prepare<'data: 'pass>(
&mut self,
locals: &'data ui::LocalsBindGroup,
locals: &'data ui::BoundLocals,
//texture: &'b ui::TextureBindGroup,
buf: &'data DynamicModel<ui::Vertex>,
scissor: Aabr<u16>,
@ -331,7 +326,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> {
}
impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> {
pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::LocalsBindGroup) {
pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::BoundLocals) {
self.render_pass.set_bind_group(1, &locals.bind_group, &[]);
}
@ -345,12 +340,12 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> {
pub fn set_scissor<'data: 'pass>(&mut self, scissor: Aabr<u16>) {
let Aabr { min, max } = scissor;
//self.render_pass.set_scissor_rect(
// min.x as u32,
// min.y as u32,
// (max.x - min.x) as u32,
// (max.y - min.y) as u32,
//);
self.render_pass.set_scissor_rect(
min.x as u32,
min.y as u32,
(max.x - min.x) as u32,
(max.y - min.y) as u32,
);
}
pub fn draw<'data: 'pass>(&mut self, texture: &'data ui::TextureBindGroup, verts: Range<u32>) {

View File

@ -2,9 +2,9 @@ use crate::{
mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain},
render::{
create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals,
CloudsVertex, Consts, FigureModel, GlobalModel, Globals, Light, LodData, Mesh, Model,
PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals, SkyboxVertex,
TerrainVertex,
CloudsVertex, Consts, FigureModel, GlobalModel, Globals, GlobalsBindGroup, Light, LodData,
Mesh, Model, PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals,
SkyboxVertex, TerrainVertex,
},
scene::{
camera::{self, Camera, CameraMode},
@ -69,6 +69,7 @@ struct Clouds {
pub struct Scene {
data: GlobalModel,
globals_bind_group: GlobalsBindGroup,
camera: Camera,
skybox: Skybox,
@ -117,14 +118,19 @@ impl Scene {
let mut col_lights = FigureColLights::new(renderer);
Self {
data: GlobalModel {
globals: renderer.create_consts(&[Globals::default()]),
lights: renderer.create_consts(&[Light::default(); 32]),
shadows: renderer.create_consts(&[Shadow::default(); 32]),
shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]),
},
let data = GlobalModel {
globals: renderer.create_consts(&[Globals::default()]),
lights: renderer.create_consts(&[Light::default(); 32]),
shadows: renderer.create_consts(&[Shadow::default(); 32]),
shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]),
};
let lod = LodData::dummy(renderer);
let globals_bind_group = renderer.bind_globals(&data, &lod);
Self {
data,
globals_bind_group,
skybox: Skybox {
model: renderer.create_model(&create_skybox_mesh()).unwrap(),
},
@ -136,7 +142,7 @@ impl Scene {
model: renderer.create_model(&create_pp_mesh()).unwrap(),
locals: renderer.create_consts(&[PostProcessLocals::default()]),
},
lod: LodData::dummy(renderer),
lod,
map_bounds,
figure_model_cache: FigureModelCache::new(),
@ -359,6 +365,8 @@ impl Scene {
}
}
pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group }
pub fn render(
&mut self,
renderer: &mut Renderer,

View File

@ -1,6 +1,6 @@
use super::graphic::{Graphic, GraphicCache, Id as GraphicId};
use crate::{
render::{Mesh, Renderer, Texture, UiVertex},
render::{Mesh, Renderer, Texture, UiTextureBindGroup, UiVertex},
Error,
};
use conrod_core::{text::GlyphCache, widget::Id};
@ -19,7 +19,7 @@ pub struct Cache {
// Map from text ids to their positioned glyphs.
text_cache: TextCache,
glyph_cache: GlyphCache<'static>,
glyph_cache_tex: Texture,
glyph_cache_tex: (Texture, UiTextureBindGroup),
graphic_cache: GraphicCache,
}
@ -33,6 +33,12 @@ impl Cache {
let glyph_cache_dims =
Vec2::new(w, h).map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size).max(512));
let glyph_cache_tex = {
let tex = renderer.create_dynamic_texture(glyph_cache_dims);
let bind = renderer.ui_bind_texture(&tex);
(tex, bind)
};
Ok(Self {
text_cache: Default::default(),
glyph_cache: GlyphCache::builder()
@ -40,12 +46,12 @@ impl Cache {
.scale_tolerance(SCALE_TOLERANCE)
.position_tolerance(POSITION_TOLERANCE)
.build(),
glyph_cache_tex: renderer.create_dynamic_texture(glyph_cache_dims),
glyph_cache_tex,
graphic_cache: GraphicCache::new(renderer),
})
}
pub fn glyph_cache_tex(&self) -> &Texture { &self.glyph_cache_tex }
pub fn glyph_cache_tex(&self) -> &(Texture, UiTextureBindGroup) { &self.glyph_cache_tex }
pub fn cache_mut_and_tex(
&mut self,
@ -53,7 +59,7 @@ impl Cache {
&mut GraphicCache,
&mut TextCache,
&mut GlyphCache<'static>,
&Texture,
&(Texture, UiTextureBindGroup),
) {
(
&mut self.graphic_cache,
@ -89,7 +95,11 @@ impl Cache {
.scale_tolerance(SCALE_TOLERANCE)
.position_tolerance(POSITION_TOLERANCE)
.build();
self.glyph_cache_tex = renderer.create_dynamic_texture(cache_dims);
self.glyph_cache_tex = {
let tex = renderer.create_dynamic_texture(cache_dims);
let bind = renderer.ui_bind_texture(&tex);
(tex, bind)
};
Ok(())
}
}

View File

@ -16,7 +16,7 @@ use super::{
use crate::{
render::{
create_ui_quad, create_ui_quad_vert_gradient, Consts, DynamicModel, Mesh, Renderer,
UiDrawer, UiLocals, UiLocalsBindGroup, UiMode, UiVertex,
UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex,
},
Error,
};
@ -85,10 +85,9 @@ pub struct IcedRenderer {
// Model for drawing the ui
model: DynamicModel<UiVertex>,
// Consts to specify positions of ingame elements (e.g. Nametags)
ingame_locals: Vec<(Consts<UiLocals>, UiLocalsBindGroup)>,
ingame_locals: Vec<UiBoundLocals>,
// Consts for default ui drawing position (ie the interface)
interface_locals: (Consts<UiLocals>, UiLocalsBindGroup),
//default_globals: Consts<Globals>,
interface_locals: UiBoundLocals,
// Used to delay cache resizing until after current frame is drawn
//need_cache_resize: bool,
@ -125,18 +124,13 @@ impl IcedRenderer {
let (half_res, align, p_scale) =
Self::calculate_resolution_dependents(physical_resolution, scaled_resolution);
let interface_locals = {
let locals = renderer.create_consts(&[UiLocals::default()]);
let bind = renderer.ui_bind_locals(&locals);
(locals, bind)
};
let interface_locals = renderer.create_ui_bound_locals(&[UiLocals::default()]);
Ok(Self {
cache: Cache::new(renderer, default_font)?,
draw_commands: Vec::new(),
model: renderer.create_dynamic_model(100),
interface_locals,
//default_globals: renderer.create_consts(&[Globals::default()]),
ingame_locals: Vec::new(),
mesh: Mesh::new(),
glyphs: Vec::new(),
@ -770,15 +764,9 @@ impl IcedRenderer {
}
}
pub fn render<'pass_ref, 'pass: 'pass_ref, 'data: 'pass>(
&'data self,
drawer: &mut UiDrawer<'pass_ref, 'pass>, /* maybe_globals: Option<&Consts<Globals>> */
) {
pub fn render<'pass, 'data: 'pass>(&'data self, drawer: &mut UiDrawer<'_, 'pass>) {
span!(_guard, "render", "IcedRenderer::render");
let mut drawer = drawer.prepare(&self.interface_locals.1, &self.model, self.window_scissor);
//let mut scissor = self.window_scissor;
//let globals = maybe_globals.unwrap_or(&self.default_globals);
//let mut locals = &self.interface_locals.1;
let mut drawer = drawer.prepare(&self.interface_locals, &self.model, self.window_scissor);
for draw_command in self.draw_commands.iter() {
match draw_command {
DrawCommand::Scissor(new_scissor) => {
@ -786,11 +774,11 @@ impl IcedRenderer {
},
DrawCommand::WorldPos(index) => {
drawer.set_locals(
index.map_or(&self.interface_locals.1, |i| &self.ingame_locals[i].1),
index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]),
);
},
DrawCommand::Draw { kind, verts } => {
// TODO: don't make these assert!(!verts.is_empty());
// TODO: don't make these: assert!(!verts.is_empty());
let tex = match kind {
DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id),
DrawKind::Plain => self.cache.glyph_cache_tex(),

View File

@ -26,7 +26,7 @@ pub use widgets::{
use crate::{
render::{
create_ui_quad, create_ui_tri, Consts, DynamicModel, Globals, Mesh, RenderError, Renderer,
UiLocals, UiMode, UiVertex,
UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex,
},
window::Window,
Error,
@ -111,10 +111,9 @@ pub struct Ui {
// Model for drawing the ui
model: DynamicModel<UiVertex>,
// Consts for default ui drawing position (ie the interface)
interface_locals: Consts<UiLocals>,
default_globals: Consts<Globals>,
interface_locals: UiBoundLocals,
// Consts to specify positions of ingame elements (e.g. Nametags)
ingame_locals: Vec<Consts<UiLocals>>,
ingame_locals: Vec<UiBoundLocals>,
// Window size for updating scaling
window_resized: Option<Vec2<f64>>,
// Scale factor changed
@ -127,12 +126,15 @@ pub struct Ui {
tooltip_manager: TooltipManager,
// Item tooltips manager
item_tooltip_manager: ItemTooltipManager,
// Scissor for the whole window
window_scissor: Aabr<u16>,
}
impl Ui {
pub fn new(window: &mut Window) -> Result<Self, Error> {
let scale = Scale::new(window, ScaleMode::Absolute(1.0), 1.0);
let win_dims = scale.scaled_resolution().into_array();
let physical_resolution = scale.physical_resolution();
let renderer = window.renderer_mut();
@ -156,6 +158,8 @@ impl Ui {
scale.scale_factor_logical(),
);
let interface_locals = renderer.create_ui_bound_locals(&[UiLocals::default()]);
Ok(Self {
ui,
image_map: Map::new(),
@ -163,8 +167,7 @@ impl Ui {
draw_commands: Vec::new(),
mesh: Mesh::new(),
model: renderer.create_dynamic_model(100),
interface_locals: renderer.create_consts(&[UiLocals::default()]),
default_globals: renderer.create_consts(&[Globals::default()]),
interface_locals,
ingame_locals: Vec::new(),
window_resized: None,
scale_factor_changed: None,
@ -172,6 +175,7 @@ impl Ui {
scale,
tooltip_manager,
item_tooltip_manager,
window_scissor: default_scissor(physical_resolution),
})
}
@ -329,6 +333,7 @@ impl Ui {
self.scale.window_resized(new_dims);
let (w, h) = self.scale.scaled_resolution().into_tuple();
self.ui.handle_event(Input::Resize(w, h));
self.window_scissor = default_scissor(self.scale.physical_resolution());
// Avoid panic in graphic cache when minimizing.
// Avoid resetting cache if window size didn't change
@ -568,7 +573,7 @@ impl Ui {
.map(|x| [255, 255, 255, *x])
.collect::<Vec<[u8; 4]>>();
renderer.update_texture(cache_tex, offset, size, &new_data);
renderer.update_texture(&cache_tex.0, offset, size, &new_data);
}) {
// FIXME: If we actually hit this error, it's still possible we could salvage
// things in various ways (for instance, the current queue might have extra
@ -604,7 +609,7 @@ impl Ui {
let mut current_state = State::Plain;
let mut start = 0;
let window_scissor = default_scissor(renderer);
let window_scissor = self.window_scissor;
let mut current_scissor = window_scissor;
let mut ingame_local_index = 0;
@ -954,7 +959,7 @@ impl Ui {
)
} else {
self.ingame_locals
.push(renderer.create_consts(&[world_pos.into()]));
.push(renderer.create_ui_bound_locals(&[world_pos.into()]));
}
self.draw_commands
.push(DrawCommand::WorldPos(Some(ingame_local_index)));
@ -1006,42 +1011,38 @@ impl Ui {
renderer.update_model(&self.model, &self.mesh, 0);
}
pub fn render(&self, renderer: &mut Renderer, maybe_globals: Option<&Consts<Globals>>) {
pub fn render<'pass, 'data: 'pass>(&'data self, drawer: &mut UiDrawer<'_, 'pass>) {
span!(_guard, "render", "Ui::render");
let mut scissor = default_scissor(renderer);
let globals = maybe_globals.unwrap_or(&self.default_globals);
let mut locals = &self.interface_locals;
let mut drawer = drawer.prepare(&self.interface_locals, &self.model, self.window_scissor);
for draw_command in self.draw_commands.iter() {
match draw_command {
DrawCommand::Scissor(new_scissor) => {
scissor = *new_scissor;
drawer.set_scissor(*new_scissor);
},
DrawCommand::WorldPos(index) => {
locals = index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]);
drawer.set_locals(
index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]),
);
},
DrawCommand::Draw { kind, verts } => {
//let tex = match kind {
// DrawKind::Image(tex_id) =>
// self.cache.graphic_cache().get_tex(*tex_id),
// DrawKind::Plain => self.cache.glyph_cache_tex(),
//};
//let model = self.model.submodel(verts.clone());
// TODO
//renderer.render_ui_element(model, tex, scissor, globals,
// locals);
let tex = match kind {
DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id),
DrawKind::Plain => self.cache.glyph_cache_tex(),
};
drawer.draw(&tex.1, verts.clone()); // Note: trivial clone
},
}
}
}
}
fn default_scissor(renderer: &Renderer) -> Aabr<u16> {
let (screen_w, screen_h) = renderer.resolution().into_tuple();
fn default_scissor(physical_resolution: Vec2<u16>) -> Aabr<u16> {
let (screen_w, screen_h) = physical_resolution.into_tuple();
Aabr {
min: Vec2 { x: 0, y: 0 },
max: Vec2 {
x: screen_w as u16,
y: screen_h as u16,
x: screen_w,
y: screen_h,
},
}
}