Track GPU use of compute and render pipelines (#534)

This commit is contained in:
Dzmitry Malyshau 2020-03-24 19:28:26 -04:00 committed by GitHub
parent 0a30cf4b46
commit 5e2f200223
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 150 additions and 12 deletions

View File

@ -142,7 +142,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
} }
} }
ComputeCommand::SetPipeline(pipeline_id) => { ComputeCommand::SetPipeline(pipeline_id) => {
let pipeline = &pipeline_guard[pipeline_id]; let pipeline = cmb.trackers
.compute_pipes
.use_extend(&*pipeline_guard, pipeline_id, (), ())
.unwrap();
unsafe { unsafe {
raw.bind_compute_pipeline(&pipeline.raw); raw.bind_compute_pipeline(&pipeline.raw);

View File

@ -183,6 +183,8 @@ impl<B: GfxBackend> CommandBuffer<B> {
base.views.merge_extend(&head.views).unwrap(); base.views.merge_extend(&head.views).unwrap();
base.bind_groups.merge_extend(&head.bind_groups).unwrap(); base.bind_groups.merge_extend(&head.bind_groups).unwrap();
base.samplers.merge_extend(&head.samplers).unwrap(); base.samplers.merge_extend(&head.samplers).unwrap();
base.compute_pipes.merge_extend(&head.compute_pipes).unwrap();
base.render_pipes.merge_extend(&head.render_pipes).unwrap();
let stages = all_buffer_stages() | all_image_stages(); let stages = all_buffer_stages() | all_image_stages();
unsafe { unsafe {

View File

@ -851,7 +851,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}; };
} }
RenderCommand::SetPipeline(pipeline_id) => { RenderCommand::SetPipeline(pipeline_id) => {
let pipeline = &pipeline_guard[pipeline_id]; let pipeline = trackers
.render_pipes
.use_extend(&*pipeline_guard, pipeline_id, (), ())
.unwrap();
assert!( assert!(
context.compatible(&pipeline.pass_context), context.compatible(&pipeline.pass_context),

View File

@ -34,6 +34,8 @@ pub struct SuspectedResources {
pub(crate) texture_views: Vec<id::TextureViewId>, pub(crate) texture_views: Vec<id::TextureViewId>,
pub(crate) samplers: Vec<id::SamplerId>, pub(crate) samplers: Vec<id::SamplerId>,
pub(crate) bind_groups: Vec<id::BindGroupId>, pub(crate) bind_groups: Vec<id::BindGroupId>,
pub(crate) compute_pipelines: Vec<id::ComputePipelineId>,
pub(crate) render_pipelines: Vec<id::RenderPipelineId>,
} }
impl SuspectedResources { impl SuspectedResources {
@ -43,6 +45,8 @@ impl SuspectedResources {
self.texture_views.clear(); self.texture_views.clear();
self.samplers.clear(); self.samplers.clear();
self.bind_groups.clear(); self.bind_groups.clear();
self.compute_pipelines.clear();
self.render_pipelines.clear();
} }
pub fn extend(&mut self, other: &Self) { pub fn extend(&mut self, other: &Self) {
@ -51,6 +55,8 @@ impl SuspectedResources {
self.texture_views.extend_from_slice(&other.texture_views); self.texture_views.extend_from_slice(&other.texture_views);
self.samplers.extend_from_slice(&other.samplers); self.samplers.extend_from_slice(&other.samplers);
self.bind_groups.extend_from_slice(&other.bind_groups); self.bind_groups.extend_from_slice(&other.bind_groups);
self.compute_pipelines.extend_from_slice(&other.compute_pipelines);
self.render_pipelines.extend_from_slice(&other.render_pipelines);
} }
} }
@ -65,6 +71,8 @@ struct NonReferencedResources<B: hal::Backend> {
samplers: Vec<B::Sampler>, samplers: Vec<B::Sampler>,
framebuffers: Vec<B::Framebuffer>, framebuffers: Vec<B::Framebuffer>,
desc_sets: Vec<DescriptorSet<B>>, desc_sets: Vec<DescriptorSet<B>>,
compute_pipes: Vec<B::ComputePipeline>,
graphics_pipes: Vec<B::GraphicsPipeline>,
} }
impl<B: hal::Backend> NonReferencedResources<B> { impl<B: hal::Backend> NonReferencedResources<B> {
@ -76,6 +84,8 @@ impl<B: hal::Backend> NonReferencedResources<B> {
samplers: Vec::new(), samplers: Vec::new(),
framebuffers: Vec::new(), framebuffers: Vec::new(),
desc_sets: Vec::new(), desc_sets: Vec::new(),
compute_pipes: Vec::new(),
graphics_pipes: Vec::new(),
} }
} }
@ -86,6 +96,8 @@ impl<B: hal::Backend> NonReferencedResources<B> {
self.samplers.extend(other.samplers); self.samplers.extend(other.samplers);
self.framebuffers.extend(other.framebuffers); self.framebuffers.extend(other.framebuffers);
self.desc_sets.extend(other.desc_sets); self.desc_sets.extend(other.desc_sets);
self.compute_pipes.extend(other.compute_pipes);
self.graphics_pipes.extend(other.graphics_pipes);
} }
unsafe fn clean( unsafe fn clean(
@ -124,6 +136,13 @@ impl<B: hal::Backend> NonReferencedResources<B> {
.lock() .lock()
.free(self.desc_sets.drain(..)); .free(self.desc_sets.drain(..));
} }
for raw in self.compute_pipes.drain(..) {
device.destroy_compute_pipeline(raw);
}
for raw in self.graphics_pipes.drain(..) {
device.destroy_graphics_pipeline(raw);
}
} }
} }
@ -386,6 +405,44 @@ impl<B: GfxBackend> LifetimeTracker<B> {
} }
} }
} }
if !self.suspected_resources.compute_pipelines.is_empty() {
let mut trackers = trackers.lock();
let (mut guard, _) = hub.compute_pipelines.write(token);
for id in self.suspected_resources.compute_pipelines.drain(..) {
if trackers.compute_pipes.remove_abandoned(id) {
hub.compute_pipelines.free_id(id);
let res = guard.remove(id).unwrap();
let submit_index = res.life_guard.submission_index.load(Ordering::Acquire);
self.active
.iter_mut()
.find(|a| a.index == submit_index)
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
.compute_pipes.push(res.raw);
}
}
}
if !self.suspected_resources.render_pipelines.is_empty() {
let mut trackers = trackers.lock();
let (mut guard, _) = hub.render_pipelines.write(token);
for id in self.suspected_resources.render_pipelines.drain(..) {
if trackers.render_pipes.remove_abandoned(id) {
hub.render_pipelines.free_id(id);
let res = guard.remove(id).unwrap();
let submit_index = res.life_guard.submission_index.load(Ordering::Acquire);
self.active
.iter_mut()
.find(|a| a.index == submit_index)
.map_or(&mut self.free_resources, |a| &mut a.last_resources)
.graphics_pipes.push(res.raw);
}
}
}
} }
pub(crate) fn triage_mapped<G: GlobalIdentityHandlerFactory>( pub(crate) fn triage_mapped<G: GlobalIdentityHandlerFactory>(

View File

@ -1292,6 +1292,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
// that it references for destruction in the next GC pass. // that it references for destruction in the next GC pass.
{ {
let (bind_group_guard, mut token) = hub.bind_groups.read(&mut token); let (bind_group_guard, mut token) = hub.bind_groups.read(&mut token);
let (compute_pipe_guard, mut token) = hub.compute_pipelines.read(&mut token);
let (render_pipe_guard, mut token) = hub.render_pipelines.read(&mut token);
let (buffer_guard, mut token) = hub.buffers.read(&mut token); let (buffer_guard, mut token) = hub.buffers.read(&mut token);
let (texture_guard, mut token) = hub.textures.read(&mut token); let (texture_guard, mut token) = hub.textures.read(&mut token);
let (texture_view_guard, mut token) = hub.texture_views.read(&mut token); let (texture_view_guard, mut token) = hub.texture_views.read(&mut token);
@ -1322,6 +1324,16 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device.temp_suspected.samplers.push(id); device.temp_suspected.samplers.push(id);
} }
} }
for id in comb.trackers.compute_pipes.used() {
if compute_pipe_guard[id].life_guard.ref_count.is_none() {
device.temp_suspected.compute_pipelines.push(id);
}
}
for id in comb.trackers.render_pipes.used() {
if render_pipe_guard[id].life_guard.ref_count.is_none() {
device.temp_suspected.render_pipelines.push(id);
}
}
} }
device device
@ -1357,6 +1369,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let (mut swap_chain_guard, mut token) = hub.swap_chains.write(&mut token); let (mut swap_chain_guard, mut token) = hub.swap_chains.write(&mut token);
let (mut command_buffer_guard, mut token) = hub.command_buffers.write(&mut token); let (mut command_buffer_guard, mut token) = hub.command_buffers.write(&mut token);
let (bind_group_guard, mut token) = hub.bind_groups.read(&mut token); let (bind_group_guard, mut token) = hub.bind_groups.read(&mut token);
let (compute_pipe_guard, mut token) = hub.compute_pipelines.read(&mut token);
let (render_pipe_guard, mut token) = hub.render_pipelines.read(&mut token);
let (buffer_guard, mut token) = hub.buffers.read(&mut token); let (buffer_guard, mut token) = hub.buffers.read(&mut token);
let (texture_guard, mut token) = hub.textures.read(&mut token); let (texture_guard, mut token) = hub.textures.read(&mut token);
let (texture_view_guard, mut token) = hub.texture_views.read(&mut token); let (texture_view_guard, mut token) = hub.texture_views.read(&mut token);
@ -1415,6 +1429,16 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device.temp_suspected.samplers.push(id); device.temp_suspected.samplers.push(id);
} }
} }
for id in comb.trackers.compute_pipes.used() {
if !compute_pipe_guard[id].life_guard.use_at(submit_index) {
device.temp_suspected.compute_pipelines.push(id);
}
}
for id in comb.trackers.render_pipes.used() {
if !render_pipe_guard[id].life_guard.use_at(submit_index) {
device.temp_suspected.render_pipelines.push(id);
}
}
// execute resource transitions // execute resource transitions
let mut transit = device.com_allocator.extend(comb); let mut transit = device.com_allocator.extend(comb);
@ -1745,6 +1769,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
index_format: desc.vertex_state.index_format, index_format: desc.vertex_state.index_format,
vertex_strides, vertex_strides,
sample_count: sc, sample_count: sc,
life_guard: LifeGuard::new(),
}; };
hub.render_pipelines hub.render_pipelines
@ -1754,9 +1779,18 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn render_pipeline_destroy<B: GfxBackend>(&self, render_pipeline_id: id::RenderPipelineId) { pub fn render_pipeline_destroy<B: GfxBackend>(&self, render_pipeline_id: id::RenderPipelineId) {
let hub = B::hub(self); let hub = B::hub(self);
let mut token = Token::root(); let mut token = Token::root();
let (_, mut token) = hub.devices.read(&mut token); let (device_guard, mut token) = hub.devices.read(&mut token);
//TODO: track usage by GPU
hub.render_pipelines.unregister(render_pipeline_id, &mut token); let device_id = {
let (mut pipeline_guard, _) = hub.render_pipelines.write(&mut token);
let pipeline = &mut pipeline_guard[render_pipeline_id];
pipeline.life_guard.ref_count.take();
pipeline.device_id.value
};
device_guard[device_id]
.lock_life(&mut token)
.suspected_resources.render_pipelines.push(render_pipeline_id);
} }
pub fn device_create_compute_pipeline<B: GfxBackend>( pub fn device_create_compute_pipeline<B: GfxBackend>(
@ -1812,6 +1846,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
value: device_id, value: device_id,
ref_count: device.life_guard.add_ref(), ref_count: device.life_guard.add_ref(),
}, },
life_guard: LifeGuard::new(),
}; };
hub.compute_pipelines hub.compute_pipelines
.register_identity(id_in, pipeline, &mut token) .register_identity(id_in, pipeline, &mut token)
@ -1820,9 +1855,19 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn compute_pipeline_destroy<B: GfxBackend>(&self, compute_pipeline_id: id::ComputePipelineId) { pub fn compute_pipeline_destroy<B: GfxBackend>(&self, compute_pipeline_id: id::ComputePipelineId) {
let hub = B::hub(self); let hub = B::hub(self);
let mut token = Token::root(); let mut token = Token::root();
let (_, mut token) = hub.devices.read(&mut token); let (device_guard, mut token) = hub.devices.read(&mut token);
//TODO: track usage by GPU
hub.compute_pipelines.unregister(compute_pipeline_id, &mut token); let device_id = {
let (mut pipeline_guard, _) = hub.compute_pipelines.write(&mut token);
let pipeline = &mut pipeline_guard[compute_pipeline_id];
pipeline.life_guard.ref_count.take();
pipeline.device_id.value
};
device_guard[device_id]
.lock_life(&mut token)
.suspected_resources.compute_pipelines.push(compute_pipeline_id);
} }
pub fn device_create_swap_chain<B: GfxBackend>( pub fn device_create_swap_chain<B: GfxBackend>(

View File

@ -184,6 +184,7 @@ impl<B: hal::Backend> Access<ComputePipeline<B>> for Device<B> {}
impl<B: hal::Backend> Access<ComputePipeline<B>> for BindGroup<B> {} impl<B: hal::Backend> Access<ComputePipeline<B>> for BindGroup<B> {}
impl<B: hal::Backend> Access<RenderPipeline<B>> for Device<B> {} impl<B: hal::Backend> Access<RenderPipeline<B>> for Device<B> {}
impl<B: hal::Backend> Access<RenderPipeline<B>> for BindGroup<B> {} impl<B: hal::Backend> Access<RenderPipeline<B>> for BindGroup<B> {}
impl<B: hal::Backend> Access<RenderPipeline<B>> for ComputePipeline<B> {}
impl<B: hal::Backend> Access<ShaderModule<B>> for Device<B> {} impl<B: hal::Backend> Access<ShaderModule<B>> for Device<B> {}
impl<B: hal::Backend> Access<ShaderModule<B>> for PipelineLayout<B> {} impl<B: hal::Backend> Access<ShaderModule<B>> for PipelineLayout<B> {}
impl<B: hal::Backend> Access<Buffer<B>> for Root {} impl<B: hal::Backend> Access<Buffer<B>> for Root {}

View File

@ -5,11 +5,14 @@
use crate::{ use crate::{
device::RenderPassContext, device::RenderPassContext,
id::{DeviceId, PipelineLayoutId, ShaderModuleId}, id::{DeviceId, PipelineLayoutId, ShaderModuleId},
LifeGuard,
RawString, RawString,
RefCount,
Stored, Stored,
U32Array U32Array
}; };
use wgt::{BufferAddress, ColorStateDescriptor, DepthStencilStateDescriptor, IndexFormat, InputStepMode, PrimitiveTopology, RasterizationStateDescriptor, VertexAttributeDescriptor}; use wgt::{BufferAddress, ColorStateDescriptor, DepthStencilStateDescriptor, IndexFormat, InputStepMode, PrimitiveTopology, RasterizationStateDescriptor, VertexAttributeDescriptor};
use std::borrow::Borrow;
#[repr(C)] #[repr(C)]
#[derive(Debug)] #[derive(Debug)]
@ -59,6 +62,13 @@ pub struct ComputePipeline<B: hal::Backend> {
pub(crate) raw: B::ComputePipeline, pub(crate) raw: B::ComputePipeline,
pub(crate) layout_id: PipelineLayoutId, pub(crate) layout_id: PipelineLayoutId,
pub(crate) device_id: Stored<DeviceId>, pub(crate) device_id: Stored<DeviceId>,
pub(crate) life_guard: LifeGuard,
}
impl<B: hal::Backend> Borrow<RefCount> for ComputePipeline<B> {
fn borrow(&self) -> &RefCount {
self.life_guard.ref_count.as_ref().unwrap()
}
} }
#[repr(C)] #[repr(C)]
@ -96,4 +106,11 @@ pub struct RenderPipeline<B: hal::Backend> {
pub(crate) index_format: IndexFormat, pub(crate) index_format: IndexFormat,
pub(crate) sample_count: u8, pub(crate) sample_count: u8,
pub(crate) vertex_strides: Vec<(BufferAddress, InputStepMode)>, pub(crate) vertex_strides: Vec<(BufferAddress, InputStepMode)>,
pub(crate) life_guard: LifeGuard,
}
impl<B: hal::Backend> Borrow<RefCount> for RenderPipeline<B> {
fn borrow(&self) -> &RefCount {
self.life_guard.ref_count.as_ref().unwrap()
}
} }

View File

@ -9,7 +9,7 @@ mod texture;
use crate::{ use crate::{
conv, conv,
hub::Storage, hub::Storage,
id::{BindGroupId, SamplerId, TextureViewId, TypedId}, id::{self, TypedId},
resource, resource,
Epoch, Epoch,
FastHashMap, FastHashMap,
@ -464,9 +464,11 @@ pub const DUMMY_SELECTOR: () = ();
pub struct TrackerSet { pub struct TrackerSet {
pub buffers: ResourceTracker<BufferState>, pub buffers: ResourceTracker<BufferState>,
pub textures: ResourceTracker<TextureState>, pub textures: ResourceTracker<TextureState>,
pub views: ResourceTracker<PhantomData<TextureViewId>>, pub views: ResourceTracker<PhantomData<id::TextureViewId>>,
pub bind_groups: ResourceTracker<PhantomData<BindGroupId>>, pub bind_groups: ResourceTracker<PhantomData<id::BindGroupId>>,
pub samplers: ResourceTracker<PhantomData<SamplerId>>, pub samplers: ResourceTracker<PhantomData<id::SamplerId>>,
pub compute_pipes: ResourceTracker<PhantomData<id::ComputePipelineId>>,
pub render_pipes: ResourceTracker<PhantomData<id::RenderPipelineId>>,
} }
impl TrackerSet { impl TrackerSet {
@ -478,6 +480,8 @@ impl TrackerSet {
views: ResourceTracker::new(backend), views: ResourceTracker::new(backend),
bind_groups: ResourceTracker::new(backend), bind_groups: ResourceTracker::new(backend),
samplers: ResourceTracker::new(backend), samplers: ResourceTracker::new(backend),
compute_pipes: ResourceTracker::new(backend),
render_pipes: ResourceTracker::new(backend),
} }
} }
@ -488,6 +492,8 @@ impl TrackerSet {
self.views.clear(); self.views.clear();
self.bind_groups.clear(); self.bind_groups.clear();
self.samplers.clear(); self.samplers.clear();
self.compute_pipes.clear();
self.render_pipes.clear();
} }
/// Try to optimize the tracking representation. /// Try to optimize the tracking representation.
@ -497,6 +503,8 @@ impl TrackerSet {
self.views.optimize(); self.views.optimize();
self.bind_groups.optimize(); self.bind_groups.optimize();
self.samplers.optimize(); self.samplers.optimize();
self.compute_pipes.optimize();
self.render_pipes.optimize();
} }
/// Merge all the trackers of another instance by extending /// Merge all the trackers of another instance by extending
@ -507,6 +515,8 @@ impl TrackerSet {
self.views.merge_extend(&other.views).unwrap(); self.views.merge_extend(&other.views).unwrap();
self.bind_groups.merge_extend(&other.bind_groups).unwrap(); self.bind_groups.merge_extend(&other.bind_groups).unwrap();
self.samplers.merge_extend(&other.samplers).unwrap(); self.samplers.merge_extend(&other.samplers).unwrap();
self.compute_pipes.merge_extend(&other.compute_pipes).unwrap();
self.render_pipes.merge_extend(&other.render_pipes).unwrap();
} }
pub fn backend(&self) -> wgt::Backend { pub fn backend(&self) -> wgt::Backend {