mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Make terrain compression a checkbox instead of a bandwidth (throughput?) heuristic.
This commit is contained in:
parent
f0824af80a
commit
be39054767
@ -53,6 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Custom map markers can be placed now
|
||||
- Fundamentals/prototype for wiring system
|
||||
- Mountain peak and lake markers on the map
|
||||
- There's now a checkbox in the graphics tab to opt-in to receiving lossily-compressed terrain colors.
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -77,6 +77,7 @@
|
||||
"hud.settings.fullscreen_mode.exclusive": "Exclusive",
|
||||
"hud.settings.fullscreen_mode.borderless": "Borderless",
|
||||
"hud.settings.particles": "Particles",
|
||||
"hud.settings.lossy_terrain_compression": "Lossy terrain compression",
|
||||
"hud.settings.resolution": "Resolution",
|
||||
"hud.settings.bit_depth": "Bit Depth",
|
||||
"hud.settings.refresh_rate": "Refresh Rate",
|
||||
|
@ -800,7 +800,10 @@ impl Client {
|
||||
| ClientGeneral::RefundSkill(_)
|
||||
| ClientGeneral::RequestSiteInfo(_)
|
||||
| ClientGeneral::UnlockSkillGroup(_)
|
||||
| ClientGeneral::RequestPlayerPhysics { .. } => &mut self.in_game_stream,
|
||||
| ClientGeneral::RequestPlayerPhysics { .. }
|
||||
| ClientGeneral::RequestLossyTerrainCompression { .. } => {
|
||||
&mut self.in_game_stream
|
||||
},
|
||||
//Only in game, terrain
|
||||
ClientGeneral::TerrainChunkRequest { .. } => &mut self.terrain_stream,
|
||||
//Always possible
|
||||
@ -820,6 +823,12 @@ impl Client {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn request_lossy_terrain_compression(&mut self, lossy_terrain_compression: bool) {
|
||||
self.send_msg(ClientGeneral::RequestLossyTerrainCompression {
|
||||
lossy_terrain_compression,
|
||||
})
|
||||
}
|
||||
|
||||
fn send_msg<S>(&mut self, msg: S)
|
||||
where
|
||||
S: Into<ClientMsg>,
|
||||
|
@ -84,6 +84,9 @@ pub enum ClientGeneral {
|
||||
RequestPlayerPhysics {
|
||||
server_authoritative: bool,
|
||||
},
|
||||
RequestLossyTerrainCompression {
|
||||
lossy_terrain_compression: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl ClientMsg {
|
||||
@ -121,7 +124,8 @@ impl ClientMsg {
|
||||
| ClientGeneral::RefundSkill(_)
|
||||
| ClientGeneral::RequestSiteInfo(_)
|
||||
| ClientGeneral::UnlockSkillGroup(_)
|
||||
| ClientGeneral::RequestPlayerPhysics { .. } => {
|
||||
| ClientGeneral::RequestPlayerPhysics { .. }
|
||||
| ClientGeneral::RequestLossyTerrainCompression { .. } => {
|
||||
c_type == ClientType::Game && presence.is_some()
|
||||
},
|
||||
//Always possible
|
||||
|
@ -15,7 +15,7 @@ pub use self::{
|
||||
server::{
|
||||
CharacterInfo, DisconnectReason, InviteAnswer, Notification, PlayerInfo, PlayerListUpdate,
|
||||
RegisterError, SerializedTerrainChunk, ServerGeneral, ServerInfo, ServerInit, ServerMsg,
|
||||
ServerRegisterAnswer, TERRAIN_LOW_BANDWIDTH,
|
||||
ServerRegisterAnswer,
|
||||
},
|
||||
world_msg::WorldMapMsg,
|
||||
};
|
||||
|
@ -73,13 +73,9 @@ pub enum SerializedTerrainChunk {
|
||||
TriPng(WireChonk<TriPngEncoding<false>, WidePacking<true>, TerrainChunkMeta, TerrainChunkSize>),
|
||||
}
|
||||
|
||||
/// If someone has less than this number of bytes per second of bandwidth, spend
|
||||
/// more CPU generating a smaller encoding of terrain data.
|
||||
pub const TERRAIN_LOW_BANDWIDTH: f32 = 500_000.0;
|
||||
|
||||
impl SerializedTerrainChunk {
|
||||
pub fn via_heuristic(chunk: &TerrainChunk, low_bandwidth: bool) -> Self {
|
||||
if low_bandwidth && (chunk.get_max_z() - chunk.get_min_z() <= 128) {
|
||||
pub fn via_heuristic(chunk: &TerrainChunk, lossy_compression: bool) -> Self {
|
||||
if lossy_compression && (chunk.get_max_z() - chunk.get_min_z() <= 128) {
|
||||
Self::quadpng(chunk)
|
||||
} else {
|
||||
Self::deflate(chunk)
|
||||
|
@ -34,8 +34,8 @@ pub struct NetworkRequestMetrics {
|
||||
pub chunks_request_dropped: IntCounter,
|
||||
pub chunks_served_from_memory: IntCounter,
|
||||
pub chunks_generation_triggered: IntCounter,
|
||||
pub chunks_served_lo_bandwidth: IntCounter,
|
||||
pub chunks_served_hi_bandwidth: IntCounter,
|
||||
pub chunks_served_lossy: IntCounter,
|
||||
pub chunks_served_lossless: IntCounter,
|
||||
}
|
||||
|
||||
pub struct ChunkGenMetrics {
|
||||
@ -189,29 +189,27 @@ impl NetworkRequestMetrics {
|
||||
"chunks_generation_triggered",
|
||||
"number of all chunks that were requested and needs to be generated",
|
||||
))?;
|
||||
let chunks_served_lo_bandwidth = IntCounter::with_opts(Opts::new(
|
||||
"chunks_served_lo_bandwidth",
|
||||
"number of chunks that were sent with compression setting by the low bandwidth \
|
||||
heuristic",
|
||||
let chunks_served_lossy = IntCounter::with_opts(Opts::new(
|
||||
"chunks_served_lossy",
|
||||
"number of chunks that were sent with lossy compression requested",
|
||||
))?;
|
||||
let chunks_served_hi_bandwidth = IntCounter::with_opts(Opts::new(
|
||||
"chunks_served_hi_bandwidth",
|
||||
"number of chunks that were sent with compression setting by the high bandwidth \
|
||||
heuristic",
|
||||
let chunks_served_lossless = IntCounter::with_opts(Opts::new(
|
||||
"chunks_served_lossless",
|
||||
"number of chunks that were sent with lossless compression requested",
|
||||
))?;
|
||||
|
||||
registry.register(Box::new(chunks_request_dropped.clone()))?;
|
||||
registry.register(Box::new(chunks_served_from_memory.clone()))?;
|
||||
registry.register(Box::new(chunks_generation_triggered.clone()))?;
|
||||
registry.register(Box::new(chunks_served_lo_bandwidth.clone()))?;
|
||||
registry.register(Box::new(chunks_served_hi_bandwidth.clone()))?;
|
||||
registry.register(Box::new(chunks_served_lossy.clone()))?;
|
||||
registry.register(Box::new(chunks_served_lossless.clone()))?;
|
||||
|
||||
Ok(Self {
|
||||
chunks_request_dropped,
|
||||
chunks_served_from_memory,
|
||||
chunks_generation_triggered,
|
||||
chunks_served_lo_bandwidth,
|
||||
chunks_served_hi_bandwidth,
|
||||
chunks_served_lossy,
|
||||
chunks_served_lossless,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ use vek::*;
|
||||
pub struct Presence {
|
||||
pub view_distance: u32,
|
||||
pub kind: PresenceKind,
|
||||
pub lossy_terrain_compression: bool,
|
||||
}
|
||||
|
||||
impl Presence {
|
||||
@ -16,6 +17,7 @@ impl Presence {
|
||||
Self {
|
||||
view_distance,
|
||||
kind,
|
||||
lossy_terrain_compression: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -253,6 +253,11 @@ impl Sys {
|
||||
setting.client_optin = server_authoritative;
|
||||
}
|
||||
},
|
||||
ClientGeneral::RequestLossyTerrainCompression {
|
||||
lossy_terrain_compression,
|
||||
} => {
|
||||
presence.lossy_terrain_compression = lossy_terrain_compression;
|
||||
},
|
||||
_ => tracing::error!("not a client_in_game msg"),
|
||||
}
|
||||
Ok(())
|
||||
|
@ -6,9 +6,7 @@ use common::{
|
||||
vol::RectVolSize,
|
||||
};
|
||||
use common_ecs::{Job, Origin, ParMode, Phase, System};
|
||||
use common_net::msg::{
|
||||
ClientGeneral, SerializedTerrainChunk, ServerGeneral, TERRAIN_LOW_BANDWIDTH,
|
||||
};
|
||||
use common_net::msg::{ClientGeneral, SerializedTerrainChunk, ServerGeneral};
|
||||
use rayon::iter::ParallelIterator;
|
||||
use specs::{Entities, Join, ParJoin, Read, ReadExpect, ReadStorage};
|
||||
use tracing::{debug, trace};
|
||||
@ -79,21 +77,17 @@ impl<'a> System<'a> for Sys {
|
||||
match terrain.get_key_arc(key) {
|
||||
Some(chunk) => {
|
||||
network_metrics.chunks_served_from_memory.inc();
|
||||
if let Some(participant) = &client.participant {
|
||||
let low_bandwidth =
|
||||
participant.bandwidth() < TERRAIN_LOW_BANDWIDTH;
|
||||
client.send(ServerGeneral::TerrainChunkUpdate {
|
||||
key,
|
||||
chunk: Ok(SerializedTerrainChunk::via_heuristic(
|
||||
&chunk,
|
||||
low_bandwidth,
|
||||
)),
|
||||
})?;
|
||||
if low_bandwidth {
|
||||
network_metrics.chunks_served_lo_bandwidth.inc();
|
||||
} else {
|
||||
network_metrics.chunks_served_hi_bandwidth.inc();
|
||||
}
|
||||
client.send(ServerGeneral::TerrainChunkUpdate {
|
||||
key,
|
||||
chunk: Ok(SerializedTerrainChunk::via_heuristic(
|
||||
&chunk,
|
||||
presence.lossy_terrain_compression,
|
||||
)),
|
||||
})?;
|
||||
if presence.lossy_terrain_compression {
|
||||
network_metrics.chunks_served_lossy.inc();
|
||||
} else {
|
||||
network_metrics.chunks_served_lossless.inc();
|
||||
}
|
||||
},
|
||||
None => {
|
||||
|
@ -14,7 +14,7 @@ use common::{
|
||||
LoadoutBuilder, SkillSetBuilder,
|
||||
};
|
||||
use common_ecs::{Job, Origin, Phase, System};
|
||||
use common_net::msg::{SerializedTerrainChunk, ServerGeneral, TERRAIN_LOW_BANDWIDTH};
|
||||
use common_net::msg::{SerializedTerrainChunk, ServerGeneral};
|
||||
use common_state::TerrainChanges;
|
||||
use comp::Behavior;
|
||||
use specs::{Join, Read, ReadExpect, ReadStorage, Write, WriteExpect};
|
||||
@ -43,34 +43,35 @@ impl LazyTerrainMessage {
|
||||
&mut self,
|
||||
network_metrics: &NetworkRequestMetrics,
|
||||
client: &Client,
|
||||
presence: &Presence,
|
||||
chunk_key: &vek::Vec2<i32>,
|
||||
generate_chunk: F,
|
||||
) -> Result<(), A> {
|
||||
if let Some(participant) = &client.participant {
|
||||
let low_bandwidth = participant.bandwidth() < TERRAIN_LOW_BANDWIDTH;
|
||||
let lazy_msg = if low_bandwidth {
|
||||
&mut self.lazy_msg_lo
|
||||
} else {
|
||||
&mut self.lazy_msg_hi
|
||||
};
|
||||
if lazy_msg.is_none() {
|
||||
*lazy_msg = Some(client.prepare(ServerGeneral::TerrainChunkUpdate {
|
||||
key: *chunk_key,
|
||||
chunk: Ok(match generate_chunk() {
|
||||
Ok(chunk) => SerializedTerrainChunk::via_heuristic(&chunk, low_bandwidth),
|
||||
Err(e) => return Err(e),
|
||||
}),
|
||||
}));
|
||||
}
|
||||
lazy_msg.as_ref().map(|ref msg| {
|
||||
let _ = client.send_prepared(&msg);
|
||||
if low_bandwidth {
|
||||
network_metrics.chunks_served_lo_bandwidth.inc();
|
||||
} else {
|
||||
network_metrics.chunks_served_hi_bandwidth.inc();
|
||||
}
|
||||
});
|
||||
let lazy_msg = if presence.lossy_terrain_compression {
|
||||
&mut self.lazy_msg_lo
|
||||
} else {
|
||||
&mut self.lazy_msg_hi
|
||||
};
|
||||
if lazy_msg.is_none() {
|
||||
*lazy_msg = Some(client.prepare(ServerGeneral::TerrainChunkUpdate {
|
||||
key: *chunk_key,
|
||||
chunk: Ok(match generate_chunk() {
|
||||
Ok(chunk) => SerializedTerrainChunk::via_heuristic(
|
||||
&chunk,
|
||||
presence.lossy_terrain_compression,
|
||||
),
|
||||
Err(e) => return Err(e),
|
||||
}),
|
||||
}));
|
||||
}
|
||||
lazy_msg.as_ref().map(|ref msg| {
|
||||
let _ = client.send_prepared(&msg);
|
||||
if presence.lossy_terrain_compression {
|
||||
network_metrics.chunks_served_lossy.inc();
|
||||
} else {
|
||||
network_metrics.chunks_served_lossless.inc();
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -293,9 +294,13 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
if adjusted_dist_sqr <= presence.view_distance.pow(2) {
|
||||
lazy_msg
|
||||
.prepare_and_send::<!, _>(&network_metrics, &client, &key, || {
|
||||
Ok(&*chunk)
|
||||
})
|
||||
.prepare_and_send::<!, _>(
|
||||
&network_metrics,
|
||||
&client,
|
||||
&presence,
|
||||
&key,
|
||||
|| Ok(&*chunk),
|
||||
)
|
||||
.into_ok();
|
||||
}
|
||||
});
|
||||
|
@ -35,11 +35,13 @@ impl<'a> System<'a> for Sys {
|
||||
for (presence, pos, client) in (&presences, &positions, &clients).join() {
|
||||
if super::terrain::chunk_in_vd(pos.0, *chunk_key, &terrain, presence.view_distance)
|
||||
{
|
||||
if let Err(()) =
|
||||
lazy_msg.prepare_and_send(&network_metrics, &client, chunk_key, || {
|
||||
terrain.get_key(*chunk_key).ok_or(())
|
||||
})
|
||||
{
|
||||
if let Err(()) = lazy_msg.prepare_and_send(
|
||||
&network_metrics,
|
||||
&client,
|
||||
&presence,
|
||||
chunk_key,
|
||||
|| terrain.get_key(*chunk_key).ok_or(()),
|
||||
) {
|
||||
break 'chunk;
|
||||
}
|
||||
}
|
||||
|
@ -82,6 +82,8 @@ widget_ids! {
|
||||
//
|
||||
particles_button,
|
||||
particles_label,
|
||||
lossy_terrain_compression_button,
|
||||
lossy_terrain_compression_label,
|
||||
//
|
||||
fullscreen_button,
|
||||
fullscreen_label,
|
||||
@ -874,6 +876,42 @@ impl<'a> Widget for Video<'a> {
|
||||
events.push(ToggleParticlesEnabled(particles_enabled));
|
||||
}
|
||||
|
||||
// Lossy terrain compression
|
||||
Text::new(
|
||||
&self
|
||||
.localized_strings
|
||||
.get("hud.settings.lossy_terrain_compression"),
|
||||
)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.right_from(state.ids.particles_label, 64.0)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.lossy_terrain_compression_label, ui);
|
||||
|
||||
let lossy_terrain_compression = ToggleButton::new(
|
||||
self.global_state
|
||||
.settings
|
||||
.graphics
|
||||
.lossy_terrain_compression,
|
||||
self.imgs.checkbox,
|
||||
self.imgs.checkbox_checked,
|
||||
)
|
||||
.w_h(18.0, 18.0)
|
||||
.right_from(state.ids.lossy_terrain_compression_label, 10.0)
|
||||
.hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
|
||||
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
|
||||
.set(state.ids.lossy_terrain_compression_button, ui);
|
||||
|
||||
if self
|
||||
.global_state
|
||||
.settings
|
||||
.graphics
|
||||
.lossy_terrain_compression
|
||||
!= lossy_terrain_compression
|
||||
{
|
||||
events.push(ToggleLossyTerrainCompression(lossy_terrain_compression));
|
||||
}
|
||||
|
||||
// Resolution
|
||||
let resolutions: Vec<[u16; 2]> = state
|
||||
.video_modes
|
||||
|
@ -88,9 +88,13 @@ impl SessionState {
|
||||
scene
|
||||
.camera_mut()
|
||||
.set_fov_deg(global_state.settings.graphics.fov);
|
||||
client
|
||||
.borrow_mut()
|
||||
.request_player_physics(global_state.settings.gameplay.player_physics_behavior);
|
||||
{
|
||||
let mut client = client.borrow_mut();
|
||||
client.request_player_physics(global_state.settings.gameplay.player_physics_behavior);
|
||||
client.request_lossy_terrain_compression(
|
||||
global_state.settings.graphics.lossy_terrain_compression,
|
||||
);
|
||||
}
|
||||
let hud = Hud::new(global_state, &client.borrow());
|
||||
let walk_forward_dir = scene.camera().forward_xy();
|
||||
let walk_right_dir = scene.camera().right_xy();
|
||||
|
@ -71,6 +71,7 @@ pub enum Graphics {
|
||||
|
||||
ChangeFullscreenMode(FullScreenSettings),
|
||||
ToggleParticlesEnabled(bool),
|
||||
ToggleLossyTerrainCompression(bool),
|
||||
AdjustWindowSize([u16; 2]),
|
||||
|
||||
ResetGraphicsSettings,
|
||||
@ -329,6 +330,13 @@ impl SettingsChange {
|
||||
Graphics::ToggleParticlesEnabled(particles_enabled) => {
|
||||
settings.graphics.particles_enabled = particles_enabled;
|
||||
},
|
||||
Graphics::ToggleLossyTerrainCompression(lossy_terrain_compression) => {
|
||||
settings.graphics.lossy_terrain_compression = lossy_terrain_compression;
|
||||
session_state
|
||||
.client
|
||||
.borrow_mut()
|
||||
.request_lossy_terrain_compression(lossy_terrain_compression);
|
||||
},
|
||||
Graphics::AdjustWindowSize(new_size) => {
|
||||
global_state.window.set_size(new_size.into());
|
||||
settings.graphics.window_size = new_size;
|
||||
|
@ -32,6 +32,7 @@ pub struct GraphicsSettings {
|
||||
pub view_distance: u32,
|
||||
pub sprite_render_distance: u32,
|
||||
pub particles_enabled: bool,
|
||||
pub lossy_terrain_compression: bool,
|
||||
pub figure_lod_render_distance: u32,
|
||||
pub max_fps: Fps,
|
||||
pub fov: u16,
|
||||
@ -50,6 +51,7 @@ impl Default for GraphicsSettings {
|
||||
view_distance: 10,
|
||||
sprite_render_distance: 100,
|
||||
particles_enabled: true,
|
||||
lossy_terrain_compression: false,
|
||||
figure_lod_render_distance: 300,
|
||||
max_fps: Fps::Max(60),
|
||||
fov: 70,
|
||||
|
@ -563,7 +563,7 @@ fn main() {
|
||||
.unwrap(),
|
||||
));
|
||||
|
||||
const SKIP_DEFLATE_2_5: bool = true;
|
||||
const SKIP_DEFLATE_2_5: bool = false;
|
||||
const SKIP_DYNA: bool = true;
|
||||
const SKIP_IMAGECHONK: bool = true;
|
||||
const SKIP_MIXED: bool = true;
|
||||
@ -701,6 +701,42 @@ fn main() {
|
||||
("deflate4chonk", (deflate4chonk_post - deflate4chonk_pre).subsec_nanos()),
|
||||
("deflate5chonk", (deflate5chonk_post - deflate5chonk_pre).subsec_nanos()),
|
||||
]);
|
||||
{
|
||||
let bucket = z_buckets
|
||||
.entry("deflate2")
|
||||
.or_default()
|
||||
.entry(chunk.get_max_z() - chunk.get_min_z())
|
||||
.or_insert((0, 0.0));
|
||||
bucket.0 += 1;
|
||||
bucket.1 += (deflate2chonk_post - deflate2chonk_pre).subsec_nanos() as f32;
|
||||
}
|
||||
{
|
||||
let bucket = z_buckets
|
||||
.entry("deflate3")
|
||||
.or_default()
|
||||
.entry(chunk.get_max_z() - chunk.get_min_z())
|
||||
.or_insert((0, 0.0));
|
||||
bucket.0 += 1;
|
||||
bucket.1 += (deflate3chonk_post - deflate3chonk_pre).subsec_nanos() as f32;
|
||||
}
|
||||
{
|
||||
let bucket = z_buckets
|
||||
.entry("deflate4")
|
||||
.or_default()
|
||||
.entry(chunk.get_max_z() - chunk.get_min_z())
|
||||
.or_insert((0, 0.0));
|
||||
bucket.0 += 1;
|
||||
bucket.1 += (deflate4chonk_post - deflate4chonk_pre).subsec_nanos() as f32;
|
||||
}
|
||||
{
|
||||
let bucket = z_buckets
|
||||
.entry("deflate5")
|
||||
.or_default()
|
||||
.entry(chunk.get_max_z() - chunk.get_min_z())
|
||||
.or_insert((0, 0.0));
|
||||
bucket.0 += 1;
|
||||
bucket.1 += (deflate5chonk_post - deflate5chonk_pre).subsec_nanos() as f32;
|
||||
}
|
||||
}
|
||||
|
||||
if !SKIP_DYNA {
|
||||
@ -886,7 +922,7 @@ fn main() {
|
||||
("tripngaverage", (tripngaverage_post - tripngaverage_pre).subsec_nanos()),
|
||||
("tripngconst", (tripngconst_post - tripngconst_pre).subsec_nanos()),
|
||||
]);
|
||||
{
|
||||
if false {
|
||||
let bucket = z_buckets
|
||||
.entry("quadpngquarttall")
|
||||
.or_default()
|
||||
@ -906,7 +942,7 @@ fn main() {
|
||||
bucket.1 +=
|
||||
(quadpngquartwide_post - quadpngquartwide_pre).subsec_nanos() as f32;
|
||||
}
|
||||
if true {
|
||||
if false {
|
||||
let bucket = z_buckets
|
||||
.entry("tripngaverage")
|
||||
.or_default()
|
||||
|
Loading…
Reference in New Issue
Block a user