Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clear evicted entries in the texture cache debug display #3321

Merged
merged 2 commits into from Nov 17, 2018
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -2,7 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{DebugCommand, DeviceIntRect, DocumentId, ExternalImageData, ExternalImageId};
use api::{DebugCommand, DocumentId, ExternalImageData, ExternalImageId};
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use api::{ImageFormat, WorldPixel, NotificationRequest};
use device::TextureFilter;
use renderer::PipelineInfo;
@@ -108,6 +109,9 @@ pub enum TextureUpdateSource {
channel_index: u8,
},
Bytes { data: Arc<Vec<u8>> },
/// Clears the target area, rather than uploading any pixels. Used when the
/// texture cache debug display is active.
DebugClear,
}

/// Command to allocate, reallocate, or free a texture for the texture cache.
@@ -183,6 +187,30 @@ impl TextureUpdateList {
self.updates.push(update);
}

/// Sends a command to the Renderer to clear the portion of the shared region
/// we just freed. Used when the texture cache debugger is enabled.
#[cold]
pub fn push_debug_clear(
&mut self,
id: CacheTextureId,
origin: DeviceIntPoint,
width: i32,
height: i32,
layer_index: usize
) {
let size = DeviceIntSize::new(width, height);
let rect = DeviceIntRect::new(origin, size);
self.push_update(TextureCacheUpdate {
id,
rect,
source: TextureUpdateSource::DebugClear,
stride: None,
offset: 0,
layer_index: layer_index as i32,
});
}


/// Pushes an allocation operation onto the list.
pub fn push_alloc(&mut self, id: CacheTextureId, info: TextureCacheAllocInfo) {
debug_assert!(!self.allocations.iter().any(|x| x.id == id));
@@ -947,6 +947,10 @@ impl RenderBackend {
).unwrap();
return true;
}
DebugCommand::SetFlags(flags) => {
self.resource_cache.set_debug_flags(flags);
ResultMsg::DebugCommand(option)
}
_ => ResultMsg::DebugCommand(option),
};
self.result_tx.send(msg).unwrap();
@@ -30,6 +30,7 @@ use api::{MemoryReport, VoidPtrToSizeFn};
use api::{RenderApiSender, RenderNotifier, TexelRect, TextureTarget};
use api::{channel};
use api::DebugCommand;
pub use api::DebugFlags;
use api::channel::PayloadReceiverHelperMethods;
use batch::{BatchKind, BatchTextures, BrushBatchKind};
#[cfg(any(feature = "capture", feature = "replay"))]
@@ -198,6 +199,11 @@ const GPU_SAMPLER_TAG_TRANSPARENT: GpuProfileTag = GpuProfileTag {
color: debug_colors::BLACK,
};

/// The clear color used for the texture cache when the debug display is enabled.
/// We use a shade of blue so that we can still identify completely blue items in
/// the texture cache.
const TEXTURE_CACHE_DBG_CLEAR_COLOR: [f32; 4] = [0.0, 0.0, 0.8, 1.0];

impl BatchKind {
#[cfg(feature = "debugger")]
fn debug_name(&self) -> &'static str {
@@ -237,26 +243,6 @@ impl BatchKind {
}
}

bitflags! {
#[derive(Default)]
pub struct DebugFlags: u32 {
const PROFILER_DBG = 1 << 0;
const RENDER_TARGET_DBG = 1 << 1;
const TEXTURE_CACHE_DBG = 1 << 2;
const GPU_TIME_QUERIES = 1 << 3;
const GPU_SAMPLE_QUERIES = 1 << 4;
const DISABLE_BATCHING = 1 << 5;
const EPOCHS = 1 << 6;
const COMPACT_PROFILER = 1 << 7;
const ECHO_DRIVER_MESSAGES = 1 << 8;
const NEW_FRAME_INDICATOR = 1 << 9;
const NEW_SCENE_INDICATOR = 1 << 10;
const SHOW_OVERDRAW = 1 << 11;
const GPU_CACHE_DBG = 1 << 12;
const SLOW_FRAME_INDICATOR = 1 << 13;
}
}

fn flag_changed(before: DebugFlags, after: DebugFlags, select: DebugFlags) -> Option<bool> {
if before & select != after & select {
Some(after.contains(select))
@@ -2436,6 +2422,9 @@ impl Renderer {
}
}
}
DebugCommand::SetFlags(flags) => {
self.set_debug_flags(flags);
}
}
}

@@ -2839,6 +2828,14 @@ impl Renderer {
if info.is_shared_cache {
texture.flags_mut()
.insert(TextureFlags::IS_SHARED_TEXTURE_CACHE);

// Textures in the cache generally don't need to be cleared,
// but we do so if the debug display is active to make it
// easier to identify unallocated regions.
if self.debug_flags.contains(DebugFlags::TEXTURE_CACHE_DBG) {
self.clear_texture(&texture, TEXTURE_CACHE_DBG_CLEAR_COLOR);
}

}

let old = self.texture_resolver.texture_cache_map.insert(allocation.id, texture);
@@ -2861,20 +2858,25 @@ impl Renderer {
for update in update_list.updates {
let TextureCacheUpdate { id, rect, stride, offset, layer_index, source } = update;
let texture = &self.texture_resolver.texture_cache_map[&id];
let mut uploader = self.device.upload_texture(
texture,
&self.texture_cache_upload_pbo,
0,
);

let bytes_uploaded = match source {
TextureUpdateSource::Bytes { data } => {
let mut uploader = self.device.upload_texture(
texture,
&self.texture_cache_upload_pbo,
0,
);
uploader.upload(
rect, layer_index, stride,
&data[offset as usize ..],
)
}
TextureUpdateSource::External { id, channel_index } => {
let mut uploader = self.device.upload_texture(
texture,
&self.texture_cache_upload_pbo,
0,
);
let handler = self.external_image_handler
.as_mut()
.expect("Found external image, but no handler set!");
@@ -2903,6 +2905,19 @@ impl Renderer {
handler.unlock(id, channel_index);
size
}
TextureUpdateSource::DebugClear => {
self.device.bind_draw_target(DrawTarget::Texture {
texture,
layer: layer_index as usize,
with_depth: false,
});
self.device.clear_target(
Some(TEXTURE_CACHE_DBG_CLEAR_COLOR),
None,
Some(rect.to_i32())
);
0
}
};
self.profile_counters.texture_data_uploaded.add(bytes_uploaded >> 10);
}
@@ -4550,6 +4565,18 @@ impl Renderer {
self.device.set_blend_mode_subpixel_with_bg_color_pass2();
}
}

/// Clears all the layers of a texture with a given color.
fn clear_texture(&mut self, texture: &Texture, color: [f32; 4]) {
for i in 0..texture.get_layer_count() {
self.device.bind_draw_target(DrawTarget::Texture {
texture: &texture,
layer: i as usize,
with_depth: false,
});
self.device.clear_target(Some(color), None, None);
}
}
}

pub enum ExternalImageSource<'a> {
@@ -5,7 +5,7 @@
use api::{AddFont, BlobImageResources, AsyncBlobImageRasterizer, ResourceUpdate};
use api::{BlobImageDescriptor, BlobImageHandler, BlobImageRequest, RasterizedBlobImage};
use api::{ClearCache, ColorF, DevicePoint, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use api::{FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
use api::{DebugFlags, FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
use api::{ExternalImageData, ExternalImageType, BlobImageResult, BlobImageParams};
use api::{FontInstanceData, FontInstanceOptions, FontInstancePlatformOptions, FontVariation};
use api::{GlyphDimensions, IdNamespace};
@@ -1623,6 +1623,10 @@ impl ResourceCache {
self.state = State::Idle;
}

pub fn set_debug_flags(&mut self, flags: DebugFlags) {
self.texture_cache.set_debug_flags(flags);
}

pub fn clear(&mut self, what: ClearCache) {
if what.contains(ClearCache::IMAGES) {
for (_key, mut cached) in self.cached_images.resources.drain() {
@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use api::{DebugFlags, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
use api::{ExternalImageType, ImageData, ImageFormat};
use api::ImageDescriptor;
use device::{TextureFilter, total_gpu_bytes_allocated};
@@ -319,6 +319,9 @@ pub struct TextureCache {
/// Maximum number of texture layers supported by hardware.
max_texture_layers: usize,

/// The current set of debug flags.
debug_flags: DebugFlags,

/// The next unused virtual texture ID. Monotonically increasing.
next_id: CacheTextureId,

@@ -372,6 +375,7 @@ impl TextureCache {
shared_textures: SharedTextures::new(),
max_texture_size,
max_texture_layers,
debug_flags: DebugFlags::empty(),
next_id: CacheTextureId(1),
pending_updates: TextureUpdateList::new(),
frame_id: FrameId::INVALID,
@@ -381,6 +385,10 @@ impl TextureCache {
}
}

pub fn set_debug_flags(&mut self, flags: DebugFlags) {
self.debug_flags = flags;
}

pub fn clear(&mut self) {
let standalone_entry_handles = mem::replace(
&mut self.handles.standalone,
@@ -547,16 +555,6 @@ impl TextureCache {
}
}

// Get a specific region by index from a shared texture array.
fn get_region_mut(&mut self,
format: ImageFormat,
filter: TextureFilter,
layer_index: usize,
) -> &mut TextureRegion {
let texture_array = self.shared_textures.select(format, filter);
&mut texture_array.regions[layer_index]
}

// Check if a given texture handle has a valid allocation
// in the texture cache.
pub fn is_allocated(&self, handle: &TextureCacheHandle) -> bool {
@@ -715,11 +713,20 @@ impl TextureCache {
layer_index,
} => {
// Free the block in the given region.
let region = self.get_region_mut(
entry.format,
entry.filter,
layer_index,
);
let texture_array = self.shared_textures.select(entry.format, entry.filter);
let region = &mut texture_array.regions[layer_index];

if self.debug_flags.contains(
DebugFlags::TEXTURE_CACHE_DBG |
DebugFlags::TEXTURE_CACHE_DBG_CLEAR_EVICTED) {
self.pending_updates.push_debug_clear(
entry.texture_id,
origin,
region.slab_size.width,
region.slab_size.height,
layer_index
);
}
region.free(origin);
}
}
@@ -664,6 +664,9 @@ pub enum DebugCommand {
/// Causes the low priority scene builder to pause for a given amount of miliseconds
/// each time it processes a transaction.
SimulateLongLowPrioritySceneBuild(u32),
/// Sets the provided debug flags. This may overlap with some of the functionality
/// above.
SetFlags(DebugFlags),
}

#[derive(Clone, Deserialize, Serialize)]
@@ -913,7 +916,27 @@ impl RenderApiSender {
next_id: Cell::new(ResourceId(0)),
}
}
}

bitflags! {
#[derive(Default, Deserialize, Serialize)]
pub struct DebugFlags: u32 {
const PROFILER_DBG = 1 << 0;
const RENDER_TARGET_DBG = 1 << 1;
const TEXTURE_CACHE_DBG = 1 << 2;
const GPU_TIME_QUERIES = 1 << 3;
const GPU_SAMPLE_QUERIES = 1 << 4;
const DISABLE_BATCHING = 1 << 5;
const EPOCHS = 1 << 6;
const COMPACT_PROFILER = 1 << 7;
const ECHO_DRIVER_MESSAGES = 1 << 8;
const NEW_FRAME_INDICATOR = 1 << 9;
const NEW_SCENE_INDICATOR = 1 << 10;
const SHOW_OVERDRAW = 1 << 11;
const GPU_CACHE_DBG = 1 << 12;
const SLOW_FRAME_INDICATOR = 1 << 13;
const TEXTURE_CACHE_DBG_CLEAR_EVICTED = 1 << 14;
}
}

pub struct RenderApi {
@@ -1013,6 +1036,11 @@ impl RenderApi {
rx.recv().unwrap()
}

pub fn set_debug_flags(&self, flags: DebugFlags) {
let cmd = DebugCommand::SetFlags(flags);
self.api_sender.send(ApiMsg::DebugCommand(cmd)).unwrap();
}

pub fn shut_down(&self) {
self.api_sender.send(ApiMsg::ShutDown).unwrap();
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.