mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
ability to fetch memory usage by the graphics server
This commit is contained in:
@@ -75,6 +75,7 @@ impl GlBuffer {
|
||||
kind,
|
||||
usage,
|
||||
} = desc;
|
||||
server.memory_usage.borrow_mut().buffers += size;
|
||||
unsafe {
|
||||
let gl_kind = kind.into_gl();
|
||||
let gl_usage = usage.into_gl();
|
||||
@@ -102,6 +103,7 @@ impl Drop for GlBuffer {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if let Some(state) = self.state.upgrade() {
|
||||
state.memory_usage.borrow_mut().buffers -= self.size.get();
|
||||
state.gl.delete_buffer(self.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ use crate::{
|
||||
texture::GlTexture,
|
||||
ToGlConstant,
|
||||
};
|
||||
use fyrox_graphics::server::ServerMemoryUsage;
|
||||
use fyrox_graphics::{
|
||||
buffer::{GpuBuffer, GpuBufferDescriptor},
|
||||
core::{color::Color, log::Log, math::Rect},
|
||||
@@ -267,6 +268,7 @@ impl InnerState {
|
||||
pub struct GlGraphicsServer {
|
||||
pub gl: glow::Context,
|
||||
pub(crate) state: RefCell<InnerState>,
|
||||
pub(crate) memory_usage: RefCell<ServerMemoryUsage>,
|
||||
this: RefCell<Option<Weak<GlGraphicsServer>>>,
|
||||
}
|
||||
|
||||
@@ -578,6 +580,7 @@ impl GlGraphicsServer {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
gl_surface,
|
||||
)),
|
||||
memory_usage: Default::default(),
|
||||
this: Default::default(),
|
||||
};
|
||||
|
||||
@@ -1196,4 +1199,8 @@ impl GraphicsServer for GlGraphicsServer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn memory_usage(&self) -> ServerMemoryUsage {
|
||||
self.memory_usage.borrow().clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ pub struct GlTexture {
|
||||
texture: glow::Texture,
|
||||
kind: Cell<GpuTextureKind>,
|
||||
pixel_kind: Cell<PixelKind>,
|
||||
size_bytes: Cell<usize>,
|
||||
// Force compiler to not implement Send and Sync, because OpenGL is not thread-safe.
|
||||
thread_mark: PhantomData<*const u8>,
|
||||
}
|
||||
@@ -281,10 +282,14 @@ impl GlTexture {
|
||||
texture,
|
||||
kind: desc.kind.into(),
|
||||
pixel_kind: desc.pixel_kind.into(),
|
||||
size_bytes: Cell::new(0),
|
||||
thread_mark: PhantomData,
|
||||
};
|
||||
|
||||
result.set_data(desc.kind, desc.pixel_kind, desc.mip_count, desc.data)?;
|
||||
let byte_count =
|
||||
result.set_data(desc.kind, desc.pixel_kind, desc.mip_count, desc.data)?;
|
||||
|
||||
server.memory_usage.borrow_mut().textures += byte_count;
|
||||
|
||||
let mut binding = result.make_temp_binding();
|
||||
if server.gl.supports_debug() {
|
||||
@@ -332,12 +337,63 @@ impl Drop for GlTexture {
|
||||
fn drop(&mut self) {
|
||||
if let Some(state) = self.state.upgrade() {
|
||||
unsafe {
|
||||
state.memory_usage.borrow_mut().textures -= self.size_bytes.get();
|
||||
state.gl.delete_texture(self.texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn desired_byte_count(kind: GpuTextureKind, mip_count: usize, pixel_kind: PixelKind) -> usize {
|
||||
let mut desired_byte_count = 0;
|
||||
|
||||
'mip_loop: for mip in 0..mip_count {
|
||||
match kind {
|
||||
GpuTextureKind::Line { length } => {
|
||||
if let Some(length) = length.checked_shr(mip as u32) {
|
||||
desired_byte_count += image_1d_size_bytes(pixel_kind, length);
|
||||
} else {
|
||||
break 'mip_loop;
|
||||
}
|
||||
}
|
||||
GpuTextureKind::Rectangle { width, height } => {
|
||||
if let (Some(width), Some(height)) = (
|
||||
width.checked_shr(mip as u32),
|
||||
height.checked_shr(mip as u32),
|
||||
) {
|
||||
desired_byte_count += image_2d_size_bytes(pixel_kind, width, height);
|
||||
} else {
|
||||
break 'mip_loop;
|
||||
}
|
||||
}
|
||||
GpuTextureKind::Cube { size } => {
|
||||
if let Some(size) = size.checked_shr(mip as u32) {
|
||||
desired_byte_count += 6 * image_2d_size_bytes(pixel_kind, size, size);
|
||||
} else {
|
||||
break 'mip_loop;
|
||||
}
|
||||
}
|
||||
GpuTextureKind::Volume {
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
} => {
|
||||
if let (Some(width), Some(height), Some(depth)) = (
|
||||
width.checked_shr(mip as u32),
|
||||
height.checked_shr(mip as u32),
|
||||
depth.checked_shr(mip as u32),
|
||||
) {
|
||||
desired_byte_count += image_3d_size_bytes(pixel_kind, width, height, depth);
|
||||
} else {
|
||||
break 'mip_loop;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
desired_byte_count
|
||||
}
|
||||
|
||||
impl GpuTextureTrait for GlTexture {
|
||||
fn set_data(
|
||||
&self,
|
||||
@@ -345,54 +401,10 @@ impl GpuTextureTrait for GlTexture {
|
||||
pixel_kind: PixelKind,
|
||||
mip_count: usize,
|
||||
data: Option<&[u8]>,
|
||||
) -> Result<(), FrameworkError> {
|
||||
) -> Result<usize, FrameworkError> {
|
||||
let mip_count = mip_count.max(1);
|
||||
|
||||
let mut desired_byte_count = 0;
|
||||
|
||||
'mip_loop: for mip in 0..mip_count {
|
||||
match kind {
|
||||
GpuTextureKind::Line { length } => {
|
||||
if let Some(length) = length.checked_shr(mip as u32) {
|
||||
desired_byte_count += image_1d_size_bytes(pixel_kind, length);
|
||||
} else {
|
||||
break 'mip_loop;
|
||||
}
|
||||
}
|
||||
GpuTextureKind::Rectangle { width, height } => {
|
||||
if let (Some(width), Some(height)) = (
|
||||
width.checked_shr(mip as u32),
|
||||
height.checked_shr(mip as u32),
|
||||
) {
|
||||
desired_byte_count += image_2d_size_bytes(pixel_kind, width, height);
|
||||
} else {
|
||||
break 'mip_loop;
|
||||
}
|
||||
}
|
||||
GpuTextureKind::Cube { size } => {
|
||||
if let Some(size) = size.checked_shr(mip as u32) {
|
||||
desired_byte_count += 6 * image_2d_size_bytes(pixel_kind, size, size);
|
||||
} else {
|
||||
break 'mip_loop;
|
||||
}
|
||||
}
|
||||
GpuTextureKind::Volume {
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
} => {
|
||||
if let (Some(width), Some(height), Some(depth)) = (
|
||||
width.checked_shr(mip as u32),
|
||||
height.checked_shr(mip as u32),
|
||||
depth.checked_shr(mip as u32),
|
||||
) {
|
||||
desired_byte_count += image_3d_size_bytes(pixel_kind, width, height, depth);
|
||||
} else {
|
||||
break 'mip_loop;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
let desired_byte_count = desired_byte_count(kind, mip_count, pixel_kind);
|
||||
|
||||
if let Some(data) = data {
|
||||
let actual_data_size = data.len();
|
||||
@@ -404,6 +416,8 @@ impl GpuTextureTrait for GlTexture {
|
||||
}
|
||||
}
|
||||
|
||||
self.size_bytes.set(desired_byte_count);
|
||||
|
||||
self.kind.set(kind);
|
||||
self.pixel_kind.set(pixel_kind);
|
||||
|
||||
@@ -616,7 +630,7 @@ impl GpuTextureTrait for GlTexture {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(desired_byte_count)
|
||||
}
|
||||
|
||||
fn kind(&self) -> GpuTextureKind {
|
||||
|
||||
@@ -497,14 +497,15 @@ define_as_any_trait!(GpuTextureAsAny => GpuTextureTrait);
|
||||
/// ```
|
||||
pub trait GpuTextureTrait: GpuTextureAsAny {
|
||||
/// Sets the new data of the texture. This method is also able to change the kind of the texture
|
||||
/// and its pixel kind.
|
||||
/// and its pixel kind. Returns the number of bytes occupied by the texture in the video memory.
|
||||
/// If there's no data specified, the texture will still take the space defined by its metrics.
|
||||
fn set_data(
|
||||
&self,
|
||||
kind: GpuTextureKind,
|
||||
pixel_kind: PixelKind,
|
||||
mip_count: usize,
|
||||
data: Option<&[u8]>,
|
||||
) -> Result<(), FrameworkError>;
|
||||
) -> Result<usize, FrameworkError>;
|
||||
|
||||
/// Returns kind of the texture.
|
||||
fn kind(&self) -> GpuTextureKind;
|
||||
|
||||
@@ -51,6 +51,18 @@ pub struct ServerCapabilities {
|
||||
pub max_lod_bias: f32,
|
||||
}
|
||||
|
||||
/// Contains information about used memory per each category of GPU resource. This is not precise
|
||||
/// data; it only calculates total requested memory by the user of a graphics server and does not
|
||||
/// include additional memory overhead in the video driver. Yet this information could still be
|
||||
/// useful.
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct ServerMemoryUsage {
|
||||
/// Total number of bytes used by all textures (including render targets).
|
||||
pub textures: usize,
|
||||
/// Total number of bytes used by all buffers (vertex, index, uniform, etc.)
|
||||
pub buffers: usize,
|
||||
}
|
||||
|
||||
/// A shared reference to a graphics server.
|
||||
pub type SharedGraphicsServer = Rc<dyn GraphicsServer>;
|
||||
|
||||
@@ -168,6 +180,9 @@ pub trait GraphicsServer: GraphicsServerAsAny {
|
||||
/// way of mipmaps generation, depending on the underlying GAPI capabilities.
|
||||
fn generate_mipmap(&self, texture: &GpuTexture);
|
||||
|
||||
/// Fetches the total amount of memory used by the graphics server.
|
||||
fn memory_usage(&self) -> ServerMemoryUsage;
|
||||
|
||||
/// A shortcut for [`Self::create_texture`], that creates a rectangular texture with the given
|
||||
/// size and pixel kind.
|
||||
fn create_2d_render_target(
|
||||
|
||||
Reference in New Issue
Block a user