mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-21 22:33:49 +00:00
Add infrastructure for counting and reporting internal resources (#5708)
* Add an optional system for counting and reporting internal resources and events * Count API objects in wgpu-hal * Expose internal counters in wgpu-core and wgpu.
This commit is contained in:
parent
afc8e38fc1
commit
1de04926b1
@ -32,6 +32,11 @@ ignored = ["cfg_aliases"]
|
|||||||
[lib]
|
[lib]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
## Internally count resources and events for debugging purposes. If the counters
|
||||||
|
## feature is disabled, the counting infrastructure is removed from the build and
|
||||||
|
## the exposed counters always return 0.
|
||||||
|
counters = ["wgt/counters"]
|
||||||
|
|
||||||
## Log all API entry points at info instead of trace level.
|
## Log all API entry points at info instead of trace level.
|
||||||
api_log_info = []
|
api_log_info = []
|
||||||
|
|
||||||
|
@ -2403,6 +2403,21 @@ impl Global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn device_get_internal_counters<A: HalApi>(
|
||||||
|
&self,
|
||||||
|
device_id: DeviceId,
|
||||||
|
) -> wgt::InternalCounters {
|
||||||
|
let hub = A::hub(self);
|
||||||
|
if let Ok(device) = hub.devices.get(device_id) {
|
||||||
|
wgt::InternalCounters {
|
||||||
|
hal: device.get_hal_counters(),
|
||||||
|
core: wgt::CoreCounters {},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn queue_drop<A: HalApi>(&self, queue_id: QueueId) {
|
pub fn queue_drop<A: HalApi>(&self, queue_id: QueueId) {
|
||||||
profiling::scope!("Queue::drop");
|
profiling::scope!("Queue::drop");
|
||||||
api_log!("Queue::drop {queue_id:?}");
|
api_log!("Queue::drop {queue_id:?}");
|
||||||
|
@ -404,6 +404,7 @@ impl<A: HalApi> Device<A> {
|
|||||||
snatch_guard: SnatchGuard,
|
snatch_guard: SnatchGuard,
|
||||||
) -> Result<(UserClosures, bool), WaitIdleError> {
|
) -> Result<(UserClosures, bool), WaitIdleError> {
|
||||||
profiling::scope!("Device::maintain");
|
profiling::scope!("Device::maintain");
|
||||||
|
|
||||||
let fence = fence_guard.as_ref().unwrap();
|
let fence = fence_guard.as_ref().unwrap();
|
||||||
let last_done_index = if maintain.is_wait() {
|
let last_done_index = if maintain.is_wait() {
|
||||||
let index_to_wait_for = match maintain {
|
let index_to_wait_for = match maintain {
|
||||||
@ -3641,6 +3642,13 @@ impl<A: HalApi> Device<A> {
|
|||||||
pub(crate) fn new_usage_scope(&self) -> UsageScope<'_, A> {
|
pub(crate) fn new_usage_scope(&self) -> UsageScope<'_, A> {
|
||||||
UsageScope::new_pooled(&self.usage_scopes, &self.tracker_indices)
|
UsageScope::new_pooled(&self.usage_scopes, &self.tracker_indices)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_hal_counters(&self) -> wgt::HalCounters {
|
||||||
|
self.raw
|
||||||
|
.as_ref()
|
||||||
|
.map(|raw| raw.get_internal_counters())
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: HalApi> Device<A> {
|
impl<A: HalApi> Device<A> {
|
||||||
|
@ -181,6 +181,7 @@ impl super::Device {
|
|||||||
null_rtv_handle,
|
null_rtv_handle,
|
||||||
mem_allocator,
|
mem_allocator,
|
||||||
dxc_container,
|
dxc_container,
|
||||||
|
counters: Default::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,6 +378,8 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { resource.SetName(cwstr.as_ptr()) };
|
unsafe { resource.SetName(cwstr.as_ptr()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.buffers.add(1);
|
||||||
|
|
||||||
Ok(super::Buffer {
|
Ok(super::Buffer {
|
||||||
resource,
|
resource,
|
||||||
size,
|
size,
|
||||||
@ -388,11 +391,14 @@ impl crate::Device for super::Device {
|
|||||||
// Only happens when it's using the windows_rs feature and there's an allocation
|
// Only happens when it's using the windows_rs feature and there's an allocation
|
||||||
if let Some(alloc) = buffer.allocation.take() {
|
if let Some(alloc) = buffer.allocation.take() {
|
||||||
super::suballocation::free_buffer_allocation(
|
super::suballocation::free_buffer_allocation(
|
||||||
|
self,
|
||||||
alloc,
|
alloc,
|
||||||
// SAFETY: for allocations to exist, the allocator must exist
|
// SAFETY: for allocations to exist, the allocator must exist
|
||||||
unsafe { self.mem_allocator.as_ref().unwrap_unchecked() },
|
unsafe { self.mem_allocator.as_ref().unwrap_unchecked() },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.buffers.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn map_buffer(
|
unsafe fn map_buffer(
|
||||||
@ -459,6 +465,8 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { resource.SetName(cwstr.as_ptr()) };
|
unsafe { resource.SetName(cwstr.as_ptr()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.textures.add(1);
|
||||||
|
|
||||||
Ok(super::Texture {
|
Ok(super::Texture {
|
||||||
resource,
|
resource,
|
||||||
format: desc.format,
|
format: desc.format,
|
||||||
@ -473,11 +481,14 @@ impl crate::Device for super::Device {
|
|||||||
unsafe fn destroy_texture(&self, mut texture: super::Texture) {
|
unsafe fn destroy_texture(&self, mut texture: super::Texture) {
|
||||||
if let Some(alloc) = texture.allocation.take() {
|
if let Some(alloc) = texture.allocation.take() {
|
||||||
super::suballocation::free_texture_allocation(
|
super::suballocation::free_texture_allocation(
|
||||||
|
self,
|
||||||
alloc,
|
alloc,
|
||||||
// SAFETY: for allocations to exist, the allocator must exist
|
// SAFETY: for allocations to exist, the allocator must exist
|
||||||
unsafe { self.mem_allocator.as_ref().unwrap_unchecked() },
|
unsafe { self.mem_allocator.as_ref().unwrap_unchecked() },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.textures.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_texture_view(
|
unsafe fn create_texture_view(
|
||||||
@ -487,6 +498,8 @@ impl crate::Device for super::Device {
|
|||||||
) -> Result<super::TextureView, DeviceError> {
|
) -> Result<super::TextureView, DeviceError> {
|
||||||
let view_desc = desc.to_internal(texture);
|
let view_desc = desc.to_internal(texture);
|
||||||
|
|
||||||
|
self.counters.texture_views.add(1);
|
||||||
|
|
||||||
Ok(super::TextureView {
|
Ok(super::TextureView {
|
||||||
raw_format: view_desc.rtv_dsv_format,
|
raw_format: view_desc.rtv_dsv_format,
|
||||||
aspects: view_desc.aspects,
|
aspects: view_desc.aspects,
|
||||||
@ -583,6 +596,7 @@ impl crate::Device for super::Device {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_texture_view(&self, view: super::TextureView) {
|
unsafe fn destroy_texture_view(&self, view: super::TextureView) {
|
||||||
if view.handle_srv.is_some() || view.handle_uav.is_some() {
|
if view.handle_srv.is_some() || view.handle_uav.is_some() {
|
||||||
let mut pool = self.srv_uav_pool.lock();
|
let mut pool = self.srv_uav_pool.lock();
|
||||||
@ -605,6 +619,8 @@ impl crate::Device for super::Device {
|
|||||||
pool.free_handle(handle);
|
pool.free_handle(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.texture_views.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_sampler(
|
unsafe fn create_sampler(
|
||||||
@ -643,10 +659,14 @@ impl crate::Device for super::Device {
|
|||||||
desc.lod_clamp.clone(),
|
desc.lod_clamp.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.counters.samplers.add(1);
|
||||||
|
|
||||||
Ok(super::Sampler { handle })
|
Ok(super::Sampler { handle })
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_sampler(&self, sampler: super::Sampler) {
|
unsafe fn destroy_sampler(&self, sampler: super::Sampler) {
|
||||||
self.sampler_pool.lock().free_handle(sampler.handle);
|
self.sampler_pool.lock().free_handle(sampler.handle);
|
||||||
|
self.counters.samplers.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_command_encoder(
|
unsafe fn create_command_encoder(
|
||||||
@ -663,6 +683,8 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { allocator.SetName(cwstr.as_ptr()) };
|
unsafe { allocator.SetName(cwstr.as_ptr()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.command_encoders.add(1);
|
||||||
|
|
||||||
Ok(super::CommandEncoder {
|
Ok(super::CommandEncoder {
|
||||||
allocator,
|
allocator,
|
||||||
device: self.raw.clone(),
|
device: self.raw.clone(),
|
||||||
@ -675,7 +697,10 @@ impl crate::Device for super::Device {
|
|||||||
end_of_pass_timer_query: None,
|
end_of_pass_timer_query: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_command_encoder(&self, _encoder: super::CommandEncoder) {}
|
|
||||||
|
unsafe fn destroy_command_encoder(&self, _encoder: super::CommandEncoder) {
|
||||||
|
self.counters.command_encoders.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_bind_group_layout(
|
unsafe fn create_bind_group_layout(
|
||||||
&self,
|
&self,
|
||||||
@ -698,6 +723,8 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.bind_group_layouts.add(1);
|
||||||
|
|
||||||
let num_views = num_buffer_views + num_texture_views;
|
let num_views = num_buffer_views + num_texture_views;
|
||||||
Ok(super::BindGroupLayout {
|
Ok(super::BindGroupLayout {
|
||||||
entries: desc.entries.to_vec(),
|
entries: desc.entries.to_vec(),
|
||||||
@ -724,7 +751,10 @@ impl crate::Device for super::Device {
|
|||||||
copy_counts: vec![1; num_views.max(num_samplers) as usize],
|
copy_counts: vec![1; num_views.max(num_samplers) as usize],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_bind_group_layout(&self, _bg_layout: super::BindGroupLayout) {}
|
|
||||||
|
unsafe fn destroy_bind_group_layout(&self, _bg_layout: super::BindGroupLayout) {
|
||||||
|
self.counters.bind_group_layouts.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_pipeline_layout(
|
unsafe fn create_pipeline_layout(
|
||||||
&self,
|
&self,
|
||||||
@ -1063,6 +1093,8 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { raw.SetName(cwstr.as_ptr()) };
|
unsafe { raw.SetName(cwstr.as_ptr()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.pipeline_layouts.add(1);
|
||||||
|
|
||||||
Ok(super::PipelineLayout {
|
Ok(super::PipelineLayout {
|
||||||
shared: super::PipelineLayoutShared {
|
shared: super::PipelineLayoutShared {
|
||||||
signature: raw,
|
signature: raw,
|
||||||
@ -1081,7 +1113,10 @@ impl crate::Device for super::Device {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_pipeline_layout(&self, _pipeline_layout: super::PipelineLayout) {}
|
|
||||||
|
unsafe fn destroy_pipeline_layout(&self, _pipeline_layout: super::PipelineLayout) {
|
||||||
|
self.counters.pipeline_layouts.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_bind_group(
|
unsafe fn create_bind_group(
|
||||||
&self,
|
&self,
|
||||||
@ -1253,12 +1288,15 @@ impl crate::Device for super::Device {
|
|||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.counters.bind_groups.add(1);
|
||||||
|
|
||||||
Ok(super::BindGroup {
|
Ok(super::BindGroup {
|
||||||
handle_views,
|
handle_views,
|
||||||
handle_samplers,
|
handle_samplers,
|
||||||
dynamic_buffers,
|
dynamic_buffers,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_bind_group(&self, group: super::BindGroup) {
|
unsafe fn destroy_bind_group(&self, group: super::BindGroup) {
|
||||||
if let Some(dual) = group.handle_views {
|
if let Some(dual) = group.handle_views {
|
||||||
self.shared.heap_views.free_slice(dual);
|
self.shared.heap_views.free_slice(dual);
|
||||||
@ -1266,6 +1304,8 @@ impl crate::Device for super::Device {
|
|||||||
if let Some(dual) = group.handle_samplers {
|
if let Some(dual) = group.handle_samplers {
|
||||||
self.shared.heap_samplers.free_slice(dual);
|
self.shared.heap_samplers.free_slice(dual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.bind_groups.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_shader_module(
|
unsafe fn create_shader_module(
|
||||||
@ -1273,6 +1313,8 @@ impl crate::Device for super::Device {
|
|||||||
desc: &crate::ShaderModuleDescriptor,
|
desc: &crate::ShaderModuleDescriptor,
|
||||||
shader: crate::ShaderInput,
|
shader: crate::ShaderInput,
|
||||||
) -> Result<super::ShaderModule, crate::ShaderError> {
|
) -> Result<super::ShaderModule, crate::ShaderError> {
|
||||||
|
self.counters.shader_modules.add(1);
|
||||||
|
|
||||||
let raw_name = desc.label.and_then(|label| ffi::CString::new(label).ok());
|
let raw_name = desc.label.and_then(|label| ffi::CString::new(label).ok());
|
||||||
match shader {
|
match shader {
|
||||||
crate::ShaderInput::Naga(naga) => Ok(super::ShaderModule { naga, raw_name }),
|
crate::ShaderInput::Naga(naga) => Ok(super::ShaderModule { naga, raw_name }),
|
||||||
@ -1282,6 +1324,7 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe fn destroy_shader_module(&self, _module: super::ShaderModule) {
|
unsafe fn destroy_shader_module(&self, _module: super::ShaderModule) {
|
||||||
|
self.counters.shader_modules.sub(1);
|
||||||
// just drop
|
// just drop
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1463,6 +1506,8 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { raw.SetName(cwstr.as_ptr()) };
|
unsafe { raw.SetName(cwstr.as_ptr()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.render_pipelines.add(1);
|
||||||
|
|
||||||
Ok(super::RenderPipeline {
|
Ok(super::RenderPipeline {
|
||||||
raw,
|
raw,
|
||||||
layout: desc.layout.shared.clone(),
|
layout: desc.layout.shared.clone(),
|
||||||
@ -1470,7 +1515,9 @@ impl crate::Device for super::Device {
|
|||||||
vertex_strides,
|
vertex_strides,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_render_pipeline(&self, _pipeline: super::RenderPipeline) {}
|
unsafe fn destroy_render_pipeline(&self, _pipeline: super::RenderPipeline) {
|
||||||
|
self.counters.render_pipelines.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_compute_pipeline(
|
unsafe fn create_compute_pipeline(
|
||||||
&self,
|
&self,
|
||||||
@ -1502,12 +1549,17 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { raw.SetName(cwstr.as_ptr()) };
|
unsafe { raw.SetName(cwstr.as_ptr()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.compute_pipelines.add(1);
|
||||||
|
|
||||||
Ok(super::ComputePipeline {
|
Ok(super::ComputePipeline {
|
||||||
raw,
|
raw,
|
||||||
layout: desc.layout.shared.clone(),
|
layout: desc.layout.shared.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_compute_pipeline(&self, _pipeline: super::ComputePipeline) {}
|
|
||||||
|
unsafe fn destroy_compute_pipeline(&self, _pipeline: super::ComputePipeline) {
|
||||||
|
self.counters.compute_pipelines.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_pipeline_cache(
|
unsafe fn create_pipeline_cache(
|
||||||
&self,
|
&self,
|
||||||
@ -1548,9 +1600,14 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { raw.SetName(cwstr.as_ptr()) };
|
unsafe { raw.SetName(cwstr.as_ptr()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.query_sets.add(1);
|
||||||
|
|
||||||
Ok(super::QuerySet { raw, raw_ty })
|
Ok(super::QuerySet { raw, raw_ty })
|
||||||
}
|
}
|
||||||
unsafe fn destroy_query_set(&self, _set: super::QuerySet) {}
|
|
||||||
|
unsafe fn destroy_query_set(&self, _set: super::QuerySet) {
|
||||||
|
self.counters.query_sets.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_fence(&self) -> Result<super::Fence, DeviceError> {
|
unsafe fn create_fence(&self) -> Result<super::Fence, DeviceError> {
|
||||||
let mut raw = d3d12::Fence::null();
|
let mut raw = d3d12::Fence::null();
|
||||||
@ -1565,9 +1622,14 @@ impl crate::Device for super::Device {
|
|||||||
hr.into_device_result("Fence creation")?;
|
hr.into_device_result("Fence creation")?;
|
||||||
null_comptr_check(&raw)?;
|
null_comptr_check(&raw)?;
|
||||||
|
|
||||||
|
self.counters.fences.add(1);
|
||||||
|
|
||||||
Ok(super::Fence { raw })
|
Ok(super::Fence { raw })
|
||||||
}
|
}
|
||||||
unsafe fn destroy_fence(&self, _fence: super::Fence) {}
|
unsafe fn destroy_fence(&self, _fence: super::Fence) {
|
||||||
|
self.counters.fences.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn get_fence_value(
|
unsafe fn get_fence_value(
|
||||||
&self,
|
&self,
|
||||||
fence: &super::Fence,
|
fence: &super::Fence,
|
||||||
@ -1711,4 +1773,8 @@ impl crate::Device for super::Device {
|
|||||||
// Destroy a D3D12 resource as per-usual.
|
// Destroy a D3D12 resource as per-usual.
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_internal_counters(&self) -> wgt::HalCounters {
|
||||||
|
self.counters.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,6 +261,7 @@ pub struct Device {
|
|||||||
null_rtv_handle: descriptor::Handle,
|
null_rtv_handle: descriptor::Handle,
|
||||||
mem_allocator: Option<Mutex<suballocation::GpuAllocatorWrapper>>,
|
mem_allocator: Option<Mutex<suballocation::GpuAllocatorWrapper>>,
|
||||||
dxc_container: Option<Arc<shader_compilation::DxcContainer>>,
|
dxc_container: Option<Arc<shader_compilation::DxcContainer>>,
|
||||||
|
counters: wgt::HalCounters,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Device {}
|
unsafe impl Send for Device {}
|
||||||
|
@ -118,6 +118,11 @@ mod placed {
|
|||||||
|
|
||||||
null_comptr_check(resource)?;
|
null_comptr_check(resource)?;
|
||||||
|
|
||||||
|
device
|
||||||
|
.counters
|
||||||
|
.buffer_memory
|
||||||
|
.add(allocation.size() as isize);
|
||||||
|
|
||||||
Ok((hr, Some(AllocationWrapper { allocation })))
|
Ok((hr, Some(AllocationWrapper { allocation })))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,13 +172,23 @@ mod placed {
|
|||||||
|
|
||||||
null_comptr_check(resource)?;
|
null_comptr_check(resource)?;
|
||||||
|
|
||||||
|
device
|
||||||
|
.counters
|
||||||
|
.texture_memory
|
||||||
|
.add(allocation.size() as isize);
|
||||||
|
|
||||||
Ok((hr, Some(AllocationWrapper { allocation })))
|
Ok((hr, Some(AllocationWrapper { allocation })))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn free_buffer_allocation(
|
pub(crate) fn free_buffer_allocation(
|
||||||
|
device: &crate::dx12::Device,
|
||||||
allocation: AllocationWrapper,
|
allocation: AllocationWrapper,
|
||||||
allocator: &Mutex<GpuAllocatorWrapper>,
|
allocator: &Mutex<GpuAllocatorWrapper>,
|
||||||
) {
|
) {
|
||||||
|
device
|
||||||
|
.counters
|
||||||
|
.buffer_memory
|
||||||
|
.sub(allocation.allocation.size() as isize);
|
||||||
match allocator.lock().allocator.free(allocation.allocation) {
|
match allocator.lock().allocator.free(allocation.allocation) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
// TODO: Don't panic here
|
// TODO: Don't panic here
|
||||||
@ -182,9 +197,14 @@ mod placed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn free_texture_allocation(
|
pub(crate) fn free_texture_allocation(
|
||||||
|
device: &crate::dx12::Device,
|
||||||
allocation: AllocationWrapper,
|
allocation: AllocationWrapper,
|
||||||
allocator: &Mutex<GpuAllocatorWrapper>,
|
allocator: &Mutex<GpuAllocatorWrapper>,
|
||||||
) {
|
) {
|
||||||
|
device
|
||||||
|
.counters
|
||||||
|
.texture_memory
|
||||||
|
.sub(allocation.allocation.size() as isize);
|
||||||
match allocator.lock().allocator.free(allocation.allocation) {
|
match allocator.lock().allocator.free(allocation.allocation) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
// TODO: Don't panic here
|
// TODO: Don't panic here
|
||||||
@ -352,6 +372,7 @@ mod committed {
|
|||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub(crate) fn free_buffer_allocation(
|
pub(crate) fn free_buffer_allocation(
|
||||||
|
_device: &crate::dx12::Device,
|
||||||
_allocation: AllocationWrapper,
|
_allocation: AllocationWrapper,
|
||||||
_allocator: &Mutex<GpuAllocatorWrapper>,
|
_allocator: &Mutex<GpuAllocatorWrapper>,
|
||||||
) {
|
) {
|
||||||
@ -360,6 +381,7 @@ mod committed {
|
|||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub(crate) fn free_texture_allocation(
|
pub(crate) fn free_texture_allocation(
|
||||||
|
_device: &crate::dx12::Device,
|
||||||
_allocation: AllocationWrapper,
|
_allocation: AllocationWrapper,
|
||||||
_allocator: &Mutex<GpuAllocatorWrapper>,
|
_allocator: &Mutex<GpuAllocatorWrapper>,
|
||||||
) {
|
) {
|
||||||
|
@ -276,6 +276,10 @@ impl crate::Device for Context {
|
|||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
unsafe fn destroy_acceleration_structure(&self, _acceleration_structure: Resource) {}
|
unsafe fn destroy_acceleration_structure(&self, _acceleration_structure: Resource) {}
|
||||||
|
|
||||||
|
fn get_internal_counters(&self) -> wgt::HalCounters {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::CommandEncoder for Encoder {
|
impl crate::CommandEncoder for Encoder {
|
||||||
|
@ -967,6 +967,7 @@ impl crate::Adapter for super::Adapter {
|
|||||||
main_vao,
|
main_vao,
|
||||||
#[cfg(all(native, feature = "renderdoc"))]
|
#[cfg(all(native, feature = "renderdoc"))]
|
||||||
render_doc: Default::default(),
|
render_doc: Default::default(),
|
||||||
|
counters: Default::default(),
|
||||||
},
|
},
|
||||||
queue: super::Queue {
|
queue: super::Queue {
|
||||||
shared: Arc::clone(&self.shared),
|
shared: Arc::clone(&self.shared),
|
||||||
|
@ -632,6 +632,8 @@ impl crate::Device for super::Device {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.counters.buffers.add(1);
|
||||||
|
|
||||||
Ok(super::Buffer {
|
Ok(super::Buffer {
|
||||||
raw,
|
raw,
|
||||||
target,
|
target,
|
||||||
@ -640,11 +642,14 @@ impl crate::Device for super::Device {
|
|||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_buffer(&self, buffer: super::Buffer) {
|
unsafe fn destroy_buffer(&self, buffer: super::Buffer) {
|
||||||
if let Some(raw) = buffer.raw {
|
if let Some(raw) = buffer.raw {
|
||||||
let gl = &self.shared.context.lock();
|
let gl = &self.shared.context.lock();
|
||||||
unsafe { gl.delete_buffer(raw) };
|
unsafe { gl.delete_buffer(raw) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.buffers.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn map_buffer(
|
unsafe fn map_buffer(
|
||||||
@ -941,6 +946,8 @@ impl crate::Device for super::Device {
|
|||||||
super::TextureInner::Texture { raw, target }
|
super::TextureInner::Texture { raw, target }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.counters.textures.add(1);
|
||||||
|
|
||||||
Ok(super::Texture {
|
Ok(super::Texture {
|
||||||
inner,
|
inner,
|
||||||
drop_guard: None,
|
drop_guard: None,
|
||||||
@ -951,6 +958,7 @@ impl crate::Device for super::Device {
|
|||||||
copy_size: desc.copy_extent(),
|
copy_size: desc.copy_extent(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_texture(&self, texture: super::Texture) {
|
unsafe fn destroy_texture(&self, texture: super::Texture) {
|
||||||
if texture.drop_guard.is_none() {
|
if texture.drop_guard.is_none() {
|
||||||
let gl = &self.shared.context.lock();
|
let gl = &self.shared.context.lock();
|
||||||
@ -970,6 +978,8 @@ impl crate::Device for super::Device {
|
|||||||
// For clarity, we explicitly drop the drop guard. Although this has no real semantic effect as the
|
// For clarity, we explicitly drop the drop guard. Although this has no real semantic effect as the
|
||||||
// end of the scope will drop the drop guard since this function takes ownership of the texture.
|
// end of the scope will drop the drop guard since this function takes ownership of the texture.
|
||||||
drop(texture.drop_guard);
|
drop(texture.drop_guard);
|
||||||
|
|
||||||
|
self.counters.textures.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_texture_view(
|
unsafe fn create_texture_view(
|
||||||
@ -977,6 +987,7 @@ impl crate::Device for super::Device {
|
|||||||
texture: &super::Texture,
|
texture: &super::Texture,
|
||||||
desc: &crate::TextureViewDescriptor,
|
desc: &crate::TextureViewDescriptor,
|
||||||
) -> Result<super::TextureView, crate::DeviceError> {
|
) -> Result<super::TextureView, crate::DeviceError> {
|
||||||
|
self.counters.texture_views.add(1);
|
||||||
Ok(super::TextureView {
|
Ok(super::TextureView {
|
||||||
//TODO: use `conv::map_view_dimension(desc.dimension)`?
|
//TODO: use `conv::map_view_dimension(desc.dimension)`?
|
||||||
inner: texture.inner.clone(),
|
inner: texture.inner.clone(),
|
||||||
@ -986,7 +997,10 @@ impl crate::Device for super::Device {
|
|||||||
format: texture.format,
|
format: texture.format,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_texture_view(&self, _view: super::TextureView) {}
|
|
||||||
|
unsafe fn destroy_texture_view(&self, _view: super::TextureView) {
|
||||||
|
self.counters.texture_views.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_sampler(
|
unsafe fn create_sampler(
|
||||||
&self,
|
&self,
|
||||||
@ -1080,34 +1094,47 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.samplers.add(1);
|
||||||
|
|
||||||
Ok(super::Sampler { raw })
|
Ok(super::Sampler { raw })
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_sampler(&self, sampler: super::Sampler) {
|
unsafe fn destroy_sampler(&self, sampler: super::Sampler) {
|
||||||
let gl = &self.shared.context.lock();
|
let gl = &self.shared.context.lock();
|
||||||
unsafe { gl.delete_sampler(sampler.raw) };
|
unsafe { gl.delete_sampler(sampler.raw) };
|
||||||
|
self.counters.samplers.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_command_encoder(
|
unsafe fn create_command_encoder(
|
||||||
&self,
|
&self,
|
||||||
_desc: &crate::CommandEncoderDescriptor<super::Api>,
|
_desc: &crate::CommandEncoderDescriptor<super::Api>,
|
||||||
) -> Result<super::CommandEncoder, crate::DeviceError> {
|
) -> Result<super::CommandEncoder, crate::DeviceError> {
|
||||||
|
self.counters.command_encoders.add(1);
|
||||||
|
|
||||||
Ok(super::CommandEncoder {
|
Ok(super::CommandEncoder {
|
||||||
cmd_buffer: super::CommandBuffer::default(),
|
cmd_buffer: super::CommandBuffer::default(),
|
||||||
state: Default::default(),
|
state: Default::default(),
|
||||||
private_caps: self.shared.private_caps,
|
private_caps: self.shared.private_caps,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_command_encoder(&self, _encoder: super::CommandEncoder) {}
|
|
||||||
|
unsafe fn destroy_command_encoder(&self, _encoder: super::CommandEncoder) {
|
||||||
|
self.counters.command_encoders.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_bind_group_layout(
|
unsafe fn create_bind_group_layout(
|
||||||
&self,
|
&self,
|
||||||
desc: &crate::BindGroupLayoutDescriptor,
|
desc: &crate::BindGroupLayoutDescriptor,
|
||||||
) -> Result<super::BindGroupLayout, crate::DeviceError> {
|
) -> Result<super::BindGroupLayout, crate::DeviceError> {
|
||||||
|
self.counters.bind_group_layouts.add(1);
|
||||||
Ok(super::BindGroupLayout {
|
Ok(super::BindGroupLayout {
|
||||||
entries: Arc::from(desc.entries),
|
entries: Arc::from(desc.entries),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_bind_group_layout(&self, _bg_layout: super::BindGroupLayout) {}
|
|
||||||
|
unsafe fn destroy_bind_group_layout(&self, _bg_layout: super::BindGroupLayout) {
|
||||||
|
self.counters.bind_group_layouts.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_pipeline_layout(
|
unsafe fn create_pipeline_layout(
|
||||||
&self,
|
&self,
|
||||||
@ -1184,6 +1211,8 @@ impl crate::Device for super::Device {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.pipeline_layouts.add(1);
|
||||||
|
|
||||||
Ok(super::PipelineLayout {
|
Ok(super::PipelineLayout {
|
||||||
group_infos: group_infos.into_boxed_slice(),
|
group_infos: group_infos.into_boxed_slice(),
|
||||||
naga_options: glsl::Options {
|
naga_options: glsl::Options {
|
||||||
@ -1194,7 +1223,10 @@ impl crate::Device for super::Device {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_pipeline_layout(&self, _pipeline_layout: super::PipelineLayout) {}
|
|
||||||
|
unsafe fn destroy_pipeline_layout(&self, _pipeline_layout: super::PipelineLayout) {
|
||||||
|
self.counters.pipeline_layouts.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_bind_group(
|
unsafe fn create_bind_group(
|
||||||
&self,
|
&self,
|
||||||
@ -1270,17 +1302,24 @@ impl crate::Device for super::Device {
|
|||||||
contents.push(binding);
|
contents.push(binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.bind_groups.add(1);
|
||||||
|
|
||||||
Ok(super::BindGroup {
|
Ok(super::BindGroup {
|
||||||
contents: contents.into_boxed_slice(),
|
contents: contents.into_boxed_slice(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_bind_group(&self, _group: super::BindGroup) {}
|
|
||||||
|
unsafe fn destroy_bind_group(&self, _group: super::BindGroup) {
|
||||||
|
self.counters.bind_groups.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_shader_module(
|
unsafe fn create_shader_module(
|
||||||
&self,
|
&self,
|
||||||
desc: &crate::ShaderModuleDescriptor,
|
desc: &crate::ShaderModuleDescriptor,
|
||||||
shader: crate::ShaderInput,
|
shader: crate::ShaderInput,
|
||||||
) -> Result<super::ShaderModule, crate::ShaderError> {
|
) -> Result<super::ShaderModule, crate::ShaderError> {
|
||||||
|
self.counters.shader_modules.add(1);
|
||||||
|
|
||||||
Ok(super::ShaderModule {
|
Ok(super::ShaderModule {
|
||||||
naga: match shader {
|
naga: match shader {
|
||||||
crate::ShaderInput::SpirV(_) => {
|
crate::ShaderInput::SpirV(_) => {
|
||||||
@ -1292,7 +1331,10 @@ impl crate::Device for super::Device {
|
|||||||
id: self.shared.next_shader_id.fetch_add(1, Ordering::Relaxed),
|
id: self.shared.next_shader_id.fetch_add(1, Ordering::Relaxed),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_shader_module(&self, _module: super::ShaderModule) {}
|
|
||||||
|
unsafe fn destroy_shader_module(&self, _module: super::ShaderModule) {
|
||||||
|
self.counters.shader_modules.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_render_pipeline(
|
unsafe fn create_render_pipeline(
|
||||||
&self,
|
&self,
|
||||||
@ -1341,6 +1383,8 @@ impl crate::Device for super::Device {
|
|||||||
targets.into_boxed_slice()
|
targets.into_boxed_slice()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.counters.render_pipelines.add(1);
|
||||||
|
|
||||||
Ok(super::RenderPipeline {
|
Ok(super::RenderPipeline {
|
||||||
inner,
|
inner,
|
||||||
primitive: desc.primitive,
|
primitive: desc.primitive,
|
||||||
@ -1363,6 +1407,7 @@ impl crate::Device for super::Device {
|
|||||||
alpha_to_coverage_enabled: desc.multisample.alpha_to_coverage_enabled,
|
alpha_to_coverage_enabled: desc.multisample.alpha_to_coverage_enabled,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
|
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
|
||||||
let mut program_cache = self.shared.program_cache.lock();
|
let mut program_cache = self.shared.program_cache.lock();
|
||||||
// If the pipeline only has 2 strong references remaining, they're `pipeline` and `program_cache`
|
// If the pipeline only has 2 strong references remaining, they're `pipeline` and `program_cache`
|
||||||
@ -1377,6 +1422,8 @@ impl crate::Device for super::Device {
|
|||||||
let gl = &self.shared.context.lock();
|
let gl = &self.shared.context.lock();
|
||||||
unsafe { gl.delete_program(pipeline.inner.program) };
|
unsafe { gl.delete_program(pipeline.inner.program) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.render_pipelines.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_compute_pipeline(
|
unsafe fn create_compute_pipeline(
|
||||||
@ -1388,8 +1435,11 @@ impl crate::Device for super::Device {
|
|||||||
shaders.push((naga::ShaderStage::Compute, &desc.stage));
|
shaders.push((naga::ShaderStage::Compute, &desc.stage));
|
||||||
let inner = unsafe { self.create_pipeline(gl, shaders, desc.layout, desc.label, None) }?;
|
let inner = unsafe { self.create_pipeline(gl, shaders, desc.layout, desc.label, None) }?;
|
||||||
|
|
||||||
|
self.counters.compute_pipelines.add(1);
|
||||||
|
|
||||||
Ok(super::ComputePipeline { inner })
|
Ok(super::ComputePipeline { inner })
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
|
unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
|
||||||
let mut program_cache = self.shared.program_cache.lock();
|
let mut program_cache = self.shared.program_cache.lock();
|
||||||
// If the pipeline only has 2 strong references remaining, they're `pipeline` and `program_cache``
|
// If the pipeline only has 2 strong references remaining, they're `pipeline` and `program_cache``
|
||||||
@ -1404,6 +1454,8 @@ impl crate::Device for super::Device {
|
|||||||
let gl = &self.shared.context.lock();
|
let gl = &self.shared.context.lock();
|
||||||
unsafe { gl.delete_program(pipeline.inner.program) };
|
unsafe { gl.delete_program(pipeline.inner.program) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.compute_pipelines.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_pipeline_cache(
|
unsafe fn create_pipeline_cache(
|
||||||
@ -1437,6 +1489,8 @@ impl crate::Device for super::Device {
|
|||||||
queries.push(query);
|
queries.push(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.query_sets.add(1);
|
||||||
|
|
||||||
Ok(super::QuerySet {
|
Ok(super::QuerySet {
|
||||||
queries: queries.into_boxed_slice(),
|
queries: queries.into_boxed_slice(),
|
||||||
target: match desc.ty {
|
target: match desc.ty {
|
||||||
@ -1446,24 +1500,31 @@ impl crate::Device for super::Device {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_query_set(&self, set: super::QuerySet) {
|
unsafe fn destroy_query_set(&self, set: super::QuerySet) {
|
||||||
let gl = &self.shared.context.lock();
|
let gl = &self.shared.context.lock();
|
||||||
for &query in set.queries.iter() {
|
for &query in set.queries.iter() {
|
||||||
unsafe { gl.delete_query(query) };
|
unsafe { gl.delete_query(query) };
|
||||||
}
|
}
|
||||||
|
self.counters.query_sets.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_fence(&self) -> Result<super::Fence, crate::DeviceError> {
|
unsafe fn create_fence(&self) -> Result<super::Fence, crate::DeviceError> {
|
||||||
|
self.counters.fences.add(1);
|
||||||
Ok(super::Fence {
|
Ok(super::Fence {
|
||||||
last_completed: 0,
|
last_completed: 0,
|
||||||
pending: Vec::new(),
|
pending: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_fence(&self, fence: super::Fence) {
|
unsafe fn destroy_fence(&self, fence: super::Fence) {
|
||||||
let gl = &self.shared.context.lock();
|
let gl = &self.shared.context.lock();
|
||||||
for (_, sync) in fence.pending {
|
for (_, sync) in fence.pending {
|
||||||
unsafe { gl.delete_sync(sync) };
|
unsafe { gl.delete_sync(sync) };
|
||||||
}
|
}
|
||||||
|
self.counters.fences.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_fence_value(
|
unsafe fn get_fence_value(
|
||||||
&self,
|
&self,
|
||||||
fence: &super::Fence,
|
fence: &super::Fence,
|
||||||
@ -1542,6 +1603,10 @@ impl crate::Device for super::Device {
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
unsafe fn destroy_acceleration_structure(&self, _acceleration_structure: ()) {}
|
unsafe fn destroy_acceleration_structure(&self, _acceleration_structure: ()) {}
|
||||||
|
|
||||||
|
fn get_internal_counters(&self) -> wgt::HalCounters {
|
||||||
|
self.counters.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(send_sync)]
|
#[cfg(send_sync)]
|
||||||
|
@ -268,6 +268,7 @@ pub struct Device {
|
|||||||
main_vao: glow::VertexArray,
|
main_vao: glow::VertexArray,
|
||||||
#[cfg(all(native, feature = "renderdoc"))]
|
#[cfg(all(native, feature = "renderdoc"))]
|
||||||
render_doc: crate::auxil::renderdoc::RenderDoc,
|
render_doc: crate::auxil::renderdoc::RenderDoc,
|
||||||
|
counters: wgt::HalCounters,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ShaderClearProgram {
|
pub struct ShaderClearProgram {
|
||||||
|
@ -884,6 +884,8 @@ pub trait Device: WasmNotSendSync {
|
|||||||
&self,
|
&self,
|
||||||
acceleration_structure: <Self::A as Api>::AccelerationStructure,
|
acceleration_structure: <Self::A as Api>::AccelerationStructure,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fn get_internal_counters(&self) -> wgt::HalCounters;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Queue: WasmNotSendSync {
|
pub trait Queue: WasmNotSendSync {
|
||||||
|
@ -62,6 +62,7 @@ impl crate::Adapter for super::Adapter {
|
|||||||
device: super::Device {
|
device: super::Device {
|
||||||
shared: Arc::clone(&self.shared),
|
shared: Arc::clone(&self.shared),
|
||||||
features,
|
features,
|
||||||
|
counters: Default::default(),
|
||||||
},
|
},
|
||||||
queue: super::Queue {
|
queue: super::Queue {
|
||||||
raw: Arc::new(Mutex::new(queue)),
|
raw: Arc::new(Mutex::new(queue)),
|
||||||
|
@ -305,6 +305,7 @@ impl super::Device {
|
|||||||
super::Device {
|
super::Device {
|
||||||
shared: Arc::new(super::AdapterShared::new(raw)),
|
shared: Arc::new(super::AdapterShared::new(raw)),
|
||||||
features,
|
features,
|
||||||
|
counters: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,13 +346,16 @@ impl crate::Device for super::Device {
|
|||||||
if let Some(label) = desc.label {
|
if let Some(label) = desc.label {
|
||||||
raw.set_label(label);
|
raw.set_label(label);
|
||||||
}
|
}
|
||||||
|
self.counters.buffers.add(1);
|
||||||
Ok(super::Buffer {
|
Ok(super::Buffer {
|
||||||
raw,
|
raw,
|
||||||
size: desc.size,
|
size: desc.size,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_buffer(&self, _buffer: super::Buffer) {}
|
unsafe fn destroy_buffer(&self, _buffer: super::Buffer) {
|
||||||
|
self.counters.buffers.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn map_buffer(
|
unsafe fn map_buffer(
|
||||||
&self,
|
&self,
|
||||||
@ -418,6 +422,8 @@ impl crate::Device for super::Device {
|
|||||||
raw.set_label(label);
|
raw.set_label(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.textures.add(1);
|
||||||
|
|
||||||
Ok(super::Texture {
|
Ok(super::Texture {
|
||||||
raw,
|
raw,
|
||||||
format: desc.format,
|
format: desc.format,
|
||||||
@ -429,7 +435,9 @@ impl crate::Device for super::Device {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_texture(&self, _texture: super::Texture) {}
|
unsafe fn destroy_texture(&self, _texture: super::Texture) {
|
||||||
|
self.counters.textures.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_texture_view(
|
unsafe fn create_texture_view(
|
||||||
&self,
|
&self,
|
||||||
@ -489,9 +497,14 @@ impl crate::Device for super::Device {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.counters.texture_views.add(1);
|
||||||
|
|
||||||
Ok(super::TextureView { raw, aspects })
|
Ok(super::TextureView { raw, aspects })
|
||||||
}
|
}
|
||||||
unsafe fn destroy_texture_view(&self, _view: super::TextureView) {}
|
|
||||||
|
unsafe fn destroy_texture_view(&self, _view: super::TextureView) {
|
||||||
|
self.counters.texture_views.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_sampler(
|
unsafe fn create_sampler(
|
||||||
&self,
|
&self,
|
||||||
@ -548,15 +561,20 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
let raw = self.shared.device.lock().new_sampler(&descriptor);
|
let raw = self.shared.device.lock().new_sampler(&descriptor);
|
||||||
|
|
||||||
|
self.counters.samplers.add(1);
|
||||||
|
|
||||||
Ok(super::Sampler { raw })
|
Ok(super::Sampler { raw })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_sampler(&self, _sampler: super::Sampler) {}
|
unsafe fn destroy_sampler(&self, _sampler: super::Sampler) {
|
||||||
|
self.counters.samplers.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_command_encoder(
|
unsafe fn create_command_encoder(
|
||||||
&self,
|
&self,
|
||||||
desc: &crate::CommandEncoderDescriptor<super::Api>,
|
desc: &crate::CommandEncoderDescriptor<super::Api>,
|
||||||
) -> Result<super::CommandEncoder, crate::DeviceError> {
|
) -> Result<super::CommandEncoder, crate::DeviceError> {
|
||||||
|
self.counters.command_encoders.add(1);
|
||||||
Ok(super::CommandEncoder {
|
Ok(super::CommandEncoder {
|
||||||
shared: Arc::clone(&self.shared),
|
shared: Arc::clone(&self.shared),
|
||||||
raw_queue: Arc::clone(&desc.queue.raw),
|
raw_queue: Arc::clone(&desc.queue.raw),
|
||||||
@ -565,17 +583,25 @@ impl crate::Device for super::Device {
|
|||||||
temp: super::Temp::default(),
|
temp: super::Temp::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_command_encoder(&self, _encoder: super::CommandEncoder) {}
|
|
||||||
|
unsafe fn destroy_command_encoder(&self, _encoder: super::CommandEncoder) {
|
||||||
|
self.counters.command_encoders.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_bind_group_layout(
|
unsafe fn create_bind_group_layout(
|
||||||
&self,
|
&self,
|
||||||
desc: &crate::BindGroupLayoutDescriptor,
|
desc: &crate::BindGroupLayoutDescriptor,
|
||||||
) -> DeviceResult<super::BindGroupLayout> {
|
) -> DeviceResult<super::BindGroupLayout> {
|
||||||
|
self.counters.bind_group_layouts.add(1);
|
||||||
|
|
||||||
Ok(super::BindGroupLayout {
|
Ok(super::BindGroupLayout {
|
||||||
entries: Arc::from(desc.entries),
|
entries: Arc::from(desc.entries),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_bind_group_layout(&self, _bg_layout: super::BindGroupLayout) {}
|
|
||||||
|
unsafe fn destroy_bind_group_layout(&self, _bg_layout: super::BindGroupLayout) {
|
||||||
|
self.counters.bind_group_layouts.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_pipeline_layout(
|
unsafe fn create_pipeline_layout(
|
||||||
&self,
|
&self,
|
||||||
@ -736,6 +762,8 @@ impl crate::Device for super::Device {
|
|||||||
resources: info.resources,
|
resources: info.resources,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.counters.pipeline_layouts.add(1);
|
||||||
|
|
||||||
Ok(super::PipelineLayout {
|
Ok(super::PipelineLayout {
|
||||||
bind_group_infos,
|
bind_group_infos,
|
||||||
push_constants_infos,
|
push_constants_infos,
|
||||||
@ -744,7 +772,10 @@ impl crate::Device for super::Device {
|
|||||||
per_stage_map,
|
per_stage_map,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_pipeline_layout(&self, _pipeline_layout: super::PipelineLayout) {}
|
|
||||||
|
unsafe fn destroy_pipeline_layout(&self, _pipeline_layout: super::PipelineLayout) {
|
||||||
|
self.counters.pipeline_layouts.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_bind_group(
|
unsafe fn create_bind_group(
|
||||||
&self,
|
&self,
|
||||||
@ -831,16 +862,22 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.bind_groups.add(1);
|
||||||
|
|
||||||
Ok(bg)
|
Ok(bg)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_bind_group(&self, _group: super::BindGroup) {}
|
unsafe fn destroy_bind_group(&self, _group: super::BindGroup) {
|
||||||
|
self.counters.bind_groups.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_shader_module(
|
unsafe fn create_shader_module(
|
||||||
&self,
|
&self,
|
||||||
desc: &crate::ShaderModuleDescriptor,
|
desc: &crate::ShaderModuleDescriptor,
|
||||||
shader: crate::ShaderInput,
|
shader: crate::ShaderInput,
|
||||||
) -> Result<super::ShaderModule, crate::ShaderError> {
|
) -> Result<super::ShaderModule, crate::ShaderError> {
|
||||||
|
self.counters.shader_modules.add(1);
|
||||||
|
|
||||||
match shader {
|
match shader {
|
||||||
crate::ShaderInput::Naga(naga) => Ok(super::ShaderModule {
|
crate::ShaderInput::Naga(naga) => Ok(super::ShaderModule {
|
||||||
naga,
|
naga,
|
||||||
@ -851,7 +888,10 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe fn destroy_shader_module(&self, _module: super::ShaderModule) {}
|
|
||||||
|
unsafe fn destroy_shader_module(&self, _module: super::ShaderModule) {
|
||||||
|
self.counters.shader_modules.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_render_pipeline(
|
unsafe fn create_render_pipeline(
|
||||||
&self,
|
&self,
|
||||||
@ -1094,6 +1134,8 @@ impl crate::Device for super::Device {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
self.counters.render_pipelines.add(1);
|
||||||
|
|
||||||
Ok(super::RenderPipeline {
|
Ok(super::RenderPipeline {
|
||||||
raw,
|
raw,
|
||||||
vs_lib,
|
vs_lib,
|
||||||
@ -1117,7 +1159,10 @@ impl crate::Device for super::Device {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_render_pipeline(&self, _pipeline: super::RenderPipeline) {}
|
|
||||||
|
unsafe fn destroy_render_pipeline(&self, _pipeline: super::RenderPipeline) {
|
||||||
|
self.counters.render_pipelines.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_compute_pipeline(
|
unsafe fn create_compute_pipeline(
|
||||||
&self,
|
&self,
|
||||||
@ -1165,6 +1210,8 @@ impl crate::Device for super::Device {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
self.counters.compute_pipelines.add(1);
|
||||||
|
|
||||||
Ok(super::ComputePipeline {
|
Ok(super::ComputePipeline {
|
||||||
raw,
|
raw,
|
||||||
cs_info,
|
cs_info,
|
||||||
@ -1174,7 +1221,10 @@ impl crate::Device for super::Device {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_compute_pipeline(&self, _pipeline: super::ComputePipeline) {}
|
|
||||||
|
unsafe fn destroy_compute_pipeline(&self, _pipeline: super::ComputePipeline) {
|
||||||
|
self.counters.compute_pipelines.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_pipeline_cache(
|
unsafe fn create_pipeline_cache(
|
||||||
&self,
|
&self,
|
||||||
@ -1237,6 +1287,8 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.counters.query_sets.add(1);
|
||||||
|
|
||||||
Ok(super::QuerySet {
|
Ok(super::QuerySet {
|
||||||
raw_buffer: destination_buffer,
|
raw_buffer: destination_buffer,
|
||||||
counter_sample_buffer: Some(counter_sample_buffer),
|
counter_sample_buffer: Some(counter_sample_buffer),
|
||||||
@ -1249,15 +1301,23 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_query_set(&self, _set: super::QuerySet) {}
|
|
||||||
|
unsafe fn destroy_query_set(&self, _set: super::QuerySet) {
|
||||||
|
self.counters.query_sets.add(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn create_fence(&self) -> DeviceResult<super::Fence> {
|
unsafe fn create_fence(&self) -> DeviceResult<super::Fence> {
|
||||||
|
self.counters.fences.add(1);
|
||||||
Ok(super::Fence {
|
Ok(super::Fence {
|
||||||
completed_value: Arc::new(atomic::AtomicU64::new(0)),
|
completed_value: Arc::new(atomic::AtomicU64::new(0)),
|
||||||
pending_command_buffers: Vec::new(),
|
pending_command_buffers: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
unsafe fn destroy_fence(&self, _fence: super::Fence) {}
|
|
||||||
|
unsafe fn destroy_fence(&self, _fence: super::Fence) {
|
||||||
|
self.counters.fences.sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe fn get_fence_value(&self, fence: &super::Fence) -> DeviceResult<crate::FenceValue> {
|
unsafe fn get_fence_value(&self, fence: &super::Fence) -> DeviceResult<crate::FenceValue> {
|
||||||
let mut max_value = fence.completed_value.load(atomic::Ordering::Acquire);
|
let mut max_value = fence.completed_value.load(atomic::Ordering::Acquire);
|
||||||
for &(value, ref cmd_buf) in fence.pending_command_buffers.iter() {
|
for &(value, ref cmd_buf) in fence.pending_command_buffers.iter() {
|
||||||
@ -1348,4 +1408,8 @@ impl crate::Device for super::Device {
|
|||||||
) {
|
) {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_internal_counters(&self) -> wgt::HalCounters {
|
||||||
|
self.counters.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,6 +339,7 @@ impl Queue {
|
|||||||
pub struct Device {
|
pub struct Device {
|
||||||
shared: Arc<AdapterShared>,
|
shared: Arc<AdapterShared>,
|
||||||
features: wgt::Features,
|
features: wgt::Features,
|
||||||
|
counters: wgt::HalCounters,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Surface {
|
pub struct Surface {
|
||||||
|
@ -1819,6 +1819,7 @@ impl super::Adapter {
|
|||||||
workarounds: self.workarounds,
|
workarounds: self.workarounds,
|
||||||
render_passes: Mutex::new(Default::default()),
|
render_passes: Mutex::new(Default::default()),
|
||||||
framebuffers: Mutex::new(Default::default()),
|
framebuffers: Mutex::new(Default::default()),
|
||||||
|
memory_allocations_counter: Default::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let relay_semaphores = super::RelaySemaphores::new(&shared)?;
|
let relay_semaphores = super::RelaySemaphores::new(&shared)?;
|
||||||
@ -1881,6 +1882,7 @@ impl super::Adapter {
|
|||||||
naga_options,
|
naga_options,
|
||||||
#[cfg(feature = "renderdoc")]
|
#[cfg(feature = "renderdoc")]
|
||||||
render_doc: Default::default(),
|
render_doc: Default::default(),
|
||||||
|
counters: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(crate::OpenDevice { device, queue })
|
Ok(crate::OpenDevice { device, queue })
|
||||||
|
@ -312,7 +312,10 @@ impl gpu_alloc::MemoryDevice<vk::DeviceMemory> for super::DeviceShared {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match unsafe { self.raw.allocate_memory(&info, None) } {
|
match unsafe { self.raw.allocate_memory(&info, None) } {
|
||||||
Ok(memory) => Ok(memory),
|
Ok(memory) => {
|
||||||
|
self.memory_allocations_counter.add(1);
|
||||||
|
Ok(memory)
|
||||||
|
}
|
||||||
Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => {
|
Err(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY) => {
|
||||||
Err(gpu_alloc::OutOfMemory::OutOfDeviceMemory)
|
Err(gpu_alloc::OutOfMemory::OutOfDeviceMemory)
|
||||||
}
|
}
|
||||||
@ -325,6 +328,8 @@ impl gpu_alloc::MemoryDevice<vk::DeviceMemory> for super::DeviceShared {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn deallocate_memory(&self, memory: vk::DeviceMemory) {
|
unsafe fn deallocate_memory(&self, memory: vk::DeviceMemory) {
|
||||||
|
self.memory_allocations_counter.sub(1);
|
||||||
|
|
||||||
unsafe { self.raw.free_memory(memory, None) };
|
unsafe { self.raw.free_memory(memory, None) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -910,6 +915,9 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { self.shared.set_object_name(raw, label) };
|
unsafe { self.shared.set_object_name(raw, label) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.buffer_memory.add(block.size() as isize);
|
||||||
|
self.counters.buffers.add(1);
|
||||||
|
|
||||||
Ok(super::Buffer {
|
Ok(super::Buffer {
|
||||||
raw,
|
raw,
|
||||||
block: Some(Mutex::new(block)),
|
block: Some(Mutex::new(block)),
|
||||||
@ -918,12 +926,12 @@ impl crate::Device for super::Device {
|
|||||||
unsafe fn destroy_buffer(&self, buffer: super::Buffer) {
|
unsafe fn destroy_buffer(&self, buffer: super::Buffer) {
|
||||||
unsafe { self.shared.raw.destroy_buffer(buffer.raw, None) };
|
unsafe { self.shared.raw.destroy_buffer(buffer.raw, None) };
|
||||||
if let Some(block) = buffer.block {
|
if let Some(block) = buffer.block {
|
||||||
unsafe {
|
let block = block.into_inner();
|
||||||
self.mem_allocator
|
self.counters.buffer_memory.sub(block.size() as isize);
|
||||||
.lock()
|
unsafe { self.mem_allocator.lock().dealloc(&*self.shared, block) };
|
||||||
.dealloc(&*self.shared, block.into_inner())
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.buffers.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn map_buffer(
|
unsafe fn map_buffer(
|
||||||
@ -1049,6 +1057,8 @@ impl crate::Device for super::Device {
|
|||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.counters.texture_memory.add(block.size() as isize);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.shared
|
self.shared
|
||||||
.raw
|
.raw
|
||||||
@ -1059,6 +1069,8 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { self.shared.set_object_name(raw, label) };
|
unsafe { self.shared.set_object_name(raw, label) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.textures.add(1);
|
||||||
|
|
||||||
Ok(super::Texture {
|
Ok(super::Texture {
|
||||||
raw,
|
raw,
|
||||||
drop_guard: None,
|
drop_guard: None,
|
||||||
@ -1075,8 +1087,12 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { self.shared.raw.destroy_image(texture.raw, None) };
|
unsafe { self.shared.raw.destroy_image(texture.raw, None) };
|
||||||
}
|
}
|
||||||
if let Some(block) = texture.block {
|
if let Some(block) = texture.block {
|
||||||
|
self.counters.texture_memory.sub(block.size() as isize);
|
||||||
|
|
||||||
unsafe { self.mem_allocator.lock().dealloc(&*self.shared, block) };
|
unsafe { self.mem_allocator.lock().dealloc(&*self.shared, block) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.textures.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_texture_view(
|
unsafe fn create_texture_view(
|
||||||
@ -1126,6 +1142,8 @@ impl crate::Device for super::Device {
|
|||||||
.collect(),
|
.collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.counters.texture_views.add(1);
|
||||||
|
|
||||||
Ok(super::TextureView {
|
Ok(super::TextureView {
|
||||||
raw,
|
raw,
|
||||||
layers,
|
layers,
|
||||||
@ -1143,6 +1161,8 @@ impl crate::Device for super::Device {
|
|||||||
fbuf_lock.retain(|key, _| !key.attachments.iter().any(|at| at.raw == view.raw));
|
fbuf_lock.retain(|key, _| !key.attachments.iter().any(|at| at.raw == view.raw));
|
||||||
}
|
}
|
||||||
unsafe { self.shared.raw.destroy_image_view(view.raw, None) };
|
unsafe { self.shared.raw.destroy_image_view(view.raw, None) };
|
||||||
|
|
||||||
|
self.counters.texture_views.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_sampler(
|
unsafe fn create_sampler(
|
||||||
@ -1184,10 +1204,14 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { self.shared.set_object_name(raw, label) };
|
unsafe { self.shared.set_object_name(raw, label) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.samplers.add(1);
|
||||||
|
|
||||||
Ok(super::Sampler { raw })
|
Ok(super::Sampler { raw })
|
||||||
}
|
}
|
||||||
unsafe fn destroy_sampler(&self, sampler: super::Sampler) {
|
unsafe fn destroy_sampler(&self, sampler: super::Sampler) {
|
||||||
unsafe { self.shared.raw.destroy_sampler(sampler.raw, None) };
|
unsafe { self.shared.raw.destroy_sampler(sampler.raw, None) };
|
||||||
|
|
||||||
|
self.counters.samplers.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_command_encoder(
|
unsafe fn create_command_encoder(
|
||||||
@ -1199,6 +1223,8 @@ impl crate::Device for super::Device {
|
|||||||
.flags(vk::CommandPoolCreateFlags::TRANSIENT);
|
.flags(vk::CommandPoolCreateFlags::TRANSIENT);
|
||||||
let raw = unsafe { self.shared.raw.create_command_pool(&vk_info, None)? };
|
let raw = unsafe { self.shared.raw.create_command_pool(&vk_info, None)? };
|
||||||
|
|
||||||
|
self.counters.command_encoders.add(1);
|
||||||
|
|
||||||
Ok(super::CommandEncoder {
|
Ok(super::CommandEncoder {
|
||||||
raw,
|
raw,
|
||||||
device: Arc::clone(&self.shared),
|
device: Arc::clone(&self.shared),
|
||||||
@ -1219,6 +1245,8 @@ impl crate::Device for super::Device {
|
|||||||
// fields.
|
// fields.
|
||||||
self.shared.raw.destroy_command_pool(cmd_encoder.raw, None);
|
self.shared.raw.destroy_command_pool(cmd_encoder.raw, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.command_encoders.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_bind_group_layout(
|
unsafe fn create_bind_group_layout(
|
||||||
@ -1339,6 +1367,8 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { self.shared.set_object_name(raw, label) };
|
unsafe { self.shared.set_object_name(raw, label) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.bind_group_layouts.add(1);
|
||||||
|
|
||||||
Ok(super::BindGroupLayout {
|
Ok(super::BindGroupLayout {
|
||||||
raw,
|
raw,
|
||||||
desc_count,
|
desc_count,
|
||||||
@ -1352,6 +1382,8 @@ impl crate::Device for super::Device {
|
|||||||
.raw
|
.raw
|
||||||
.destroy_descriptor_set_layout(bg_layout.raw, None)
|
.destroy_descriptor_set_layout(bg_layout.raw, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.counters.bind_group_layouts.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_pipeline_layout(
|
unsafe fn create_pipeline_layout(
|
||||||
@ -1403,6 +1435,8 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.pipeline_layouts.add(1);
|
||||||
|
|
||||||
Ok(super::PipelineLayout {
|
Ok(super::PipelineLayout {
|
||||||
raw,
|
raw,
|
||||||
binding_arrays,
|
binding_arrays,
|
||||||
@ -1414,6 +1448,8 @@ impl crate::Device for super::Device {
|
|||||||
.raw
|
.raw
|
||||||
.destroy_pipeline_layout(pipeline_layout.raw, None)
|
.destroy_pipeline_layout(pipeline_layout.raw, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.counters.pipeline_layouts.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_bind_group(
|
unsafe fn create_bind_group(
|
||||||
@ -1596,14 +1632,20 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe { self.shared.raw.update_descriptor_sets(&writes, &[]) };
|
unsafe { self.shared.raw.update_descriptor_sets(&writes, &[]) };
|
||||||
|
|
||||||
|
self.counters.bind_groups.add(1);
|
||||||
|
|
||||||
Ok(super::BindGroup { set })
|
Ok(super::BindGroup { set })
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_bind_group(&self, group: super::BindGroup) {
|
unsafe fn destroy_bind_group(&self, group: super::BindGroup) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.desc_allocator
|
self.desc_allocator
|
||||||
.lock()
|
.lock()
|
||||||
.free(&*self.shared, Some(group.set))
|
.free(&*self.shared, Some(group.set))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.counters.bind_groups.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_shader_module(
|
unsafe fn create_shader_module(
|
||||||
@ -1661,8 +1703,11 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { self.shared.set_object_name(raw, label) };
|
unsafe { self.shared.set_object_name(raw, label) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.shader_modules.add(1);
|
||||||
|
|
||||||
Ok(super::ShaderModule::Raw(raw))
|
Ok(super::ShaderModule::Raw(raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_shader_module(&self, module: super::ShaderModule) {
|
unsafe fn destroy_shader_module(&self, module: super::ShaderModule) {
|
||||||
match module {
|
match module {
|
||||||
super::ShaderModule::Raw(raw) => {
|
super::ShaderModule::Raw(raw) => {
|
||||||
@ -1670,6 +1715,8 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
super::ShaderModule::Intermediate { .. } => {}
|
super::ShaderModule::Intermediate { .. } => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.shader_modules.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_render_pipeline(
|
unsafe fn create_render_pipeline(
|
||||||
@ -1900,10 +1947,14 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { self.shared.raw.destroy_shader_module(raw_module, None) };
|
unsafe { self.shared.raw.destroy_shader_module(raw_module, None) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.render_pipelines.add(1);
|
||||||
|
|
||||||
Ok(super::RenderPipeline { raw })
|
Ok(super::RenderPipeline { raw })
|
||||||
}
|
}
|
||||||
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
|
unsafe fn destroy_render_pipeline(&self, pipeline: super::RenderPipeline) {
|
||||||
unsafe { self.shared.raw.destroy_pipeline(pipeline.raw, None) };
|
unsafe { self.shared.raw.destroy_pipeline(pipeline.raw, None) };
|
||||||
|
|
||||||
|
self.counters.render_pipelines.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_compute_pipeline(
|
unsafe fn create_compute_pipeline(
|
||||||
@ -1946,10 +1997,15 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { self.shared.raw.destroy_shader_module(raw_module, None) };
|
unsafe { self.shared.raw.destroy_shader_module(raw_module, None) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.compute_pipelines.add(1);
|
||||||
|
|
||||||
Ok(super::ComputePipeline { raw })
|
Ok(super::ComputePipeline { raw })
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
|
unsafe fn destroy_compute_pipeline(&self, pipeline: super::ComputePipeline) {
|
||||||
unsafe { self.shared.raw.destroy_pipeline(pipeline.raw, None) };
|
unsafe { self.shared.raw.destroy_pipeline(pipeline.raw, None) };
|
||||||
|
|
||||||
|
self.counters.compute_pipelines.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_pipeline_cache(
|
unsafe fn create_pipeline_cache(
|
||||||
@ -2001,18 +2057,26 @@ impl crate::Device for super::Device {
|
|||||||
unsafe { self.shared.set_object_name(raw, label) };
|
unsafe { self.shared.set_object_name(raw, label) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.query_sets.add(1);
|
||||||
|
|
||||||
Ok(super::QuerySet { raw })
|
Ok(super::QuerySet { raw })
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn destroy_query_set(&self, set: super::QuerySet) {
|
unsafe fn destroy_query_set(&self, set: super::QuerySet) {
|
||||||
unsafe { self.shared.raw.destroy_query_pool(set.raw, None) };
|
unsafe { self.shared.raw.destroy_query_pool(set.raw, None) };
|
||||||
|
|
||||||
|
self.counters.query_sets.sub(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_fence(&self) -> Result<super::Fence, crate::DeviceError> {
|
unsafe fn create_fence(&self) -> Result<super::Fence, crate::DeviceError> {
|
||||||
|
self.counters.fences.add(1);
|
||||||
|
|
||||||
Ok(if self.shared.private_caps.timeline_semaphores {
|
Ok(if self.shared.private_caps.timeline_semaphores {
|
||||||
let mut sem_type_info =
|
let mut sem_type_info =
|
||||||
vk::SemaphoreTypeCreateInfo::default().semaphore_type(vk::SemaphoreType::TIMELINE);
|
vk::SemaphoreTypeCreateInfo::default().semaphore_type(vk::SemaphoreType::TIMELINE);
|
||||||
let vk_info = vk::SemaphoreCreateInfo::default().push_next(&mut sem_type_info);
|
let vk_info = vk::SemaphoreCreateInfo::default().push_next(&mut sem_type_info);
|
||||||
let raw = unsafe { self.shared.raw.create_semaphore(&vk_info, None) }?;
|
let raw = unsafe { self.shared.raw.create_semaphore(&vk_info, None) }?;
|
||||||
|
|
||||||
super::Fence::TimelineSemaphore(raw)
|
super::Fence::TimelineSemaphore(raw)
|
||||||
} else {
|
} else {
|
||||||
super::Fence::FencePool {
|
super::Fence::FencePool {
|
||||||
@ -2040,6 +2104,8 @@ impl crate::Device for super::Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.counters.fences.sub(1);
|
||||||
}
|
}
|
||||||
unsafe fn get_fence_value(
|
unsafe fn get_fence_value(
|
||||||
&self,
|
&self,
|
||||||
@ -2320,6 +2386,14 @@ impl crate::Device for super::Device {
|
|||||||
.dealloc(&*self.shared, acceleration_structure.block.into_inner());
|
.dealloc(&*self.shared, acceleration_structure.block.into_inner());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_internal_counters(&self) -> wgt::HalCounters {
|
||||||
|
self.counters
|
||||||
|
.memory_allocations
|
||||||
|
.set(self.shared.memory_allocations_counter.read());
|
||||||
|
|
||||||
|
self.counters.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::DeviceShared {
|
impl super::DeviceShared {
|
||||||
|
@ -43,6 +43,7 @@ use std::{
|
|||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use ash::{ext, khr, vk};
|
use ash::{ext, khr, vk};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
|
use wgt::InternalCounter;
|
||||||
|
|
||||||
const MILLIS_TO_NANOS: u64 = 1_000_000;
|
const MILLIS_TO_NANOS: u64 = 1_000_000;
|
||||||
const MAX_TOTAL_ATTACHMENTS: usize = crate::MAX_COLOR_ATTACHMENTS * 2 + 1;
|
const MAX_TOTAL_ATTACHMENTS: usize = crate::MAX_COLOR_ATTACHMENTS * 2 + 1;
|
||||||
@ -527,6 +528,7 @@ struct DeviceShared {
|
|||||||
features: wgt::Features,
|
features: wgt::Features,
|
||||||
render_passes: Mutex<rustc_hash::FxHashMap<RenderPassKey, vk::RenderPass>>,
|
render_passes: Mutex<rustc_hash::FxHashMap<RenderPassKey, vk::RenderPass>>,
|
||||||
framebuffers: Mutex<rustc_hash::FxHashMap<FramebufferKey, vk::Framebuffer>>,
|
framebuffers: Mutex<rustc_hash::FxHashMap<FramebufferKey, vk::Framebuffer>>,
|
||||||
|
memory_allocations_counter: InternalCounter,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Device {
|
pub struct Device {
|
||||||
@ -538,6 +540,7 @@ pub struct Device {
|
|||||||
naga_options: naga::back::spv::Options<'static>,
|
naga_options: naga::back::spv::Options<'static>,
|
||||||
#[cfg(feature = "renderdoc")]
|
#[cfg(feature = "renderdoc")]
|
||||||
render_doc: crate::auxil::renderdoc::RenderDoc,
|
render_doc: crate::auxil::renderdoc::RenderDoc,
|
||||||
|
counters: wgt::HalCounters,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Semaphores for forcing queue submissions to run in order.
|
/// Semaphores for forcing queue submissions to run in order.
|
||||||
|
@ -30,6 +30,8 @@ targets = [
|
|||||||
[features]
|
[features]
|
||||||
strict_asserts = []
|
strict_asserts = []
|
||||||
fragile-send-sync-non-atomic-wasm = []
|
fragile-send-sync-non-atomic-wasm = []
|
||||||
|
# Enables some internal instrumentation for debugging purposes.
|
||||||
|
counters = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "2"
|
bitflags = "2"
|
||||||
|
153
wgpu-types/src/counters.rs
Normal file
153
wgpu-types/src/counters.rs
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
#[cfg(feature = "counters")]
|
||||||
|
use std::sync::atomic::{AtomicIsize, Ordering};
|
||||||
|
|
||||||
|
/// An internal counter for debugging purposes
|
||||||
|
///
|
||||||
|
/// Internally represented as an atomic isize if the `counters` feature is enabled,
|
||||||
|
/// or compiles to nothing otherwise.
|
||||||
|
pub struct InternalCounter {
|
||||||
|
#[cfg(feature = "counters")]
|
||||||
|
value: AtomicIsize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InternalCounter {
|
||||||
|
/// Creates a counter with value 0.
|
||||||
|
#[inline]
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
InternalCounter {
|
||||||
|
#[cfg(feature = "counters")]
|
||||||
|
value: AtomicIsize::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the counter's value.
|
||||||
|
#[cfg(feature = "counters")]
|
||||||
|
#[inline]
|
||||||
|
pub fn read(&self) -> isize {
|
||||||
|
self.value.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the counter's value.
|
||||||
|
///
|
||||||
|
/// Always returns 0 if the `counters` feature is not enabled.
|
||||||
|
#[cfg(not(feature = "counters"))]
|
||||||
|
#[inline]
|
||||||
|
pub fn read(&self) -> isize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get and reset the counter's value.
|
||||||
|
///
|
||||||
|
/// Always returns 0 if the `counters` feature is not enabled.
|
||||||
|
#[cfg(feature = "counters")]
|
||||||
|
#[inline]
|
||||||
|
pub fn take(&self) -> isize {
|
||||||
|
self.value.swap(0, Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get and reset the counter's value.
|
||||||
|
///
|
||||||
|
/// Always returns 0 if the `counters` feature is not enabled.
|
||||||
|
#[cfg(not(feature = "counters"))]
|
||||||
|
#[inline]
|
||||||
|
pub fn take(&self) -> isize {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Increment the counter by the provided amount.
|
||||||
|
#[inline]
|
||||||
|
pub fn add(&self, _val: isize) {
|
||||||
|
#[cfg(feature = "counters")]
|
||||||
|
self.value.fetch_add(_val, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decrement the counter by the provided amount.
|
||||||
|
#[inline]
|
||||||
|
pub fn sub(&self, _val: isize) {
|
||||||
|
#[cfg(feature = "counters")]
|
||||||
|
self.value.fetch_add(-_val, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the counter to the provided value.
|
||||||
|
#[inline]
|
||||||
|
pub fn set(&self, _val: isize) {
|
||||||
|
#[cfg(feature = "counters")]
|
||||||
|
self.value.store(_val, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for InternalCounter {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
InternalCounter {
|
||||||
|
#[cfg(feature = "counters")]
|
||||||
|
value: AtomicIsize::new(self.read()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for InternalCounter {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for InternalCounter {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.read().fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `wgpu-hal`'s internal counters.
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct HalCounters {
|
||||||
|
// API objects
|
||||||
|
///
|
||||||
|
pub buffers: InternalCounter,
|
||||||
|
///
|
||||||
|
pub textures: InternalCounter,
|
||||||
|
///
|
||||||
|
pub texture_views: InternalCounter,
|
||||||
|
///
|
||||||
|
pub bind_groups: InternalCounter,
|
||||||
|
///
|
||||||
|
pub bind_group_layouts: InternalCounter,
|
||||||
|
///
|
||||||
|
pub render_pipelines: InternalCounter,
|
||||||
|
///
|
||||||
|
pub compute_pipelines: InternalCounter,
|
||||||
|
///
|
||||||
|
pub pipeline_layouts: InternalCounter,
|
||||||
|
///
|
||||||
|
pub samplers: InternalCounter,
|
||||||
|
///
|
||||||
|
pub command_encoders: InternalCounter,
|
||||||
|
///
|
||||||
|
pub shader_modules: InternalCounter,
|
||||||
|
///
|
||||||
|
pub query_sets: InternalCounter,
|
||||||
|
///
|
||||||
|
pub fences: InternalCounter,
|
||||||
|
|
||||||
|
// Resources
|
||||||
|
/// Amount of allocated gpu memory attributed to buffers, in bytes.
|
||||||
|
pub buffer_memory: InternalCounter,
|
||||||
|
/// Amount of allocated gpu memory attributed to textures, in bytes.
|
||||||
|
pub texture_memory: InternalCounter,
|
||||||
|
/// Number of gpu memory allocations.
|
||||||
|
pub memory_allocations: InternalCounter,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `wgpu-core`'s internal counters.
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct CoreCounters {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
/// All internal counters, exposed for debugging purposes.
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct InternalCounters {
|
||||||
|
/// `wgpu-core` counters.
|
||||||
|
pub core: CoreCounters,
|
||||||
|
/// `wgpu-hal` counters.
|
||||||
|
pub hal: HalCounters,
|
||||||
|
}
|
@ -18,8 +18,11 @@ use std::path::PathBuf;
|
|||||||
use std::{num::NonZeroU32, ops::Range};
|
use std::{num::NonZeroU32, ops::Range};
|
||||||
|
|
||||||
pub mod assertions;
|
pub mod assertions;
|
||||||
|
mod counters;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
|
|
||||||
|
pub use counters::*;
|
||||||
|
|
||||||
// Use this macro instead of the one provided by the bitflags_serde_shim crate
|
// Use this macro instead of the one provided by the bitflags_serde_shim crate
|
||||||
// because the latter produces an error when deserializing bits that are not
|
// because the latter produces an error when deserializing bits that are not
|
||||||
// specified in the bitflags, while we want deserialization to succeed and
|
// specified in the bitflags, while we want deserialization to succeed and
|
||||||
|
@ -97,6 +97,11 @@ replay = ["serde", "wgc/replay"]
|
|||||||
#! ### Other
|
#! ### Other
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Internally count resources and events for debugging purposes. If the counters
|
||||||
|
## feature is disabled, the counting infrastructure is removed from the build and
|
||||||
|
## the exposed counters always return 0.
|
||||||
|
counters = ["wgc/counters"]
|
||||||
|
|
||||||
## Implement `Send` and `Sync` on Wasm, but only if atomics are not enabled.
|
## Implement `Send` and `Sync` on Wasm, but only if atomics are not enabled.
|
||||||
##
|
##
|
||||||
## WebGL/WebGPU objects can not be shared between threads.
|
## WebGL/WebGPU objects can not be shared between threads.
|
||||||
|
@ -2978,6 +2978,14 @@ impl crate::context::Context for ContextWebGpu {
|
|||||||
fn device_start_capture(&self, _device: &Self::DeviceId, _device_data: &Self::DeviceData) {}
|
fn device_start_capture(&self, _device: &Self::DeviceId, _device_data: &Self::DeviceData) {}
|
||||||
fn device_stop_capture(&self, _device: &Self::DeviceId, _device_data: &Self::DeviceData) {}
|
fn device_stop_capture(&self, _device: &Self::DeviceId, _device_data: &Self::DeviceData) {}
|
||||||
|
|
||||||
|
fn device_get_internal_counters(
|
||||||
|
&self,
|
||||||
|
_device: &Self::DeviceId,
|
||||||
|
_device_data: &Self::DeviceData,
|
||||||
|
) -> wgt::InternalCounters {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
fn pipeline_cache_get_data(
|
fn pipeline_cache_get_data(
|
||||||
&self,
|
&self,
|
||||||
_: &Self::PipelineCacheId,
|
_: &Self::PipelineCacheId,
|
||||||
|
@ -2370,6 +2370,14 @@ impl crate::Context for ContextWgpuCore {
|
|||||||
wgc::gfx_select!(device => self.0.device_stop_capture(*device));
|
wgc::gfx_select!(device => self.0.device_stop_capture(*device));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn device_get_internal_counters(
|
||||||
|
&self,
|
||||||
|
device: &Self::DeviceId,
|
||||||
|
_device_data: &Self::DeviceData,
|
||||||
|
) -> wgt::InternalCounters {
|
||||||
|
wgc::gfx_select!(device => self.0.device_get_internal_counters(*device))
|
||||||
|
}
|
||||||
|
|
||||||
fn pipeline_cache_get_data(
|
fn pipeline_cache_get_data(
|
||||||
&self,
|
&self,
|
||||||
cache: &Self::PipelineCacheId,
|
cache: &Self::PipelineCacheId,
|
||||||
|
@ -611,6 +611,13 @@ pub trait Context: Debug + WasmNotSendSync + Sized {
|
|||||||
|
|
||||||
fn device_start_capture(&self, device: &Self::DeviceId, device_data: &Self::DeviceData);
|
fn device_start_capture(&self, device: &Self::DeviceId, device_data: &Self::DeviceData);
|
||||||
fn device_stop_capture(&self, device: &Self::DeviceId, device_data: &Self::DeviceData);
|
fn device_stop_capture(&self, device: &Self::DeviceId, device_data: &Self::DeviceData);
|
||||||
|
|
||||||
|
fn device_get_internal_counters(
|
||||||
|
&self,
|
||||||
|
device: &Self::DeviceId,
|
||||||
|
_device_data: &Self::DeviceData,
|
||||||
|
) -> wgt::InternalCounters;
|
||||||
|
|
||||||
fn pipeline_cache_get_data(
|
fn pipeline_cache_get_data(
|
||||||
&self,
|
&self,
|
||||||
cache: &Self::PipelineCacheId,
|
cache: &Self::PipelineCacheId,
|
||||||
@ -1604,6 +1611,12 @@ pub(crate) trait DynContext: Debug + WasmNotSendSync {
|
|||||||
fn device_start_capture(&self, device: &ObjectId, data: &crate::Data);
|
fn device_start_capture(&self, device: &ObjectId, data: &crate::Data);
|
||||||
fn device_stop_capture(&self, device: &ObjectId, data: &crate::Data);
|
fn device_stop_capture(&self, device: &ObjectId, data: &crate::Data);
|
||||||
|
|
||||||
|
fn device_get_internal_counters(
|
||||||
|
&self,
|
||||||
|
device: &ObjectId,
|
||||||
|
device_data: &crate::Data,
|
||||||
|
) -> wgt::InternalCounters;
|
||||||
|
|
||||||
fn pipeline_cache_get_data(
|
fn pipeline_cache_get_data(
|
||||||
&self,
|
&self,
|
||||||
cache: &ObjectId,
|
cache: &ObjectId,
|
||||||
@ -3078,6 +3091,16 @@ where
|
|||||||
Context::device_stop_capture(self, &device, device_data)
|
Context::device_stop_capture(self, &device, device_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn device_get_internal_counters(
|
||||||
|
&self,
|
||||||
|
device: &ObjectId,
|
||||||
|
device_data: &crate::Data,
|
||||||
|
) -> wgt::InternalCounters {
|
||||||
|
let device = <T::DeviceId>::from(*device);
|
||||||
|
let device_data = downcast_ref(device_data);
|
||||||
|
Context::device_get_internal_counters(self, &device, device_data)
|
||||||
|
}
|
||||||
|
|
||||||
fn pipeline_cache_get_data(
|
fn pipeline_cache_get_data(
|
||||||
&self,
|
&self,
|
||||||
cache: &ObjectId,
|
cache: &ObjectId,
|
||||||
|
@ -3167,6 +3167,16 @@ impl Device {
|
|||||||
DynContext::device_stop_capture(&*self.context, &self.id, self.data.as_ref())
|
DynContext::device_stop_capture(&*self.context, &self.id, self.data.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Query internal counters from the native backend for debugging purposes.
|
||||||
|
///
|
||||||
|
/// Some backends may not set all counters, or may not set any counter at all.
|
||||||
|
/// The `counters` cargo feature must be enabled for any counter to be set.
|
||||||
|
///
|
||||||
|
/// If a counter is not set, its contains its default value (zero).
|
||||||
|
pub fn get_internal_counters(&self) -> wgt::InternalCounters {
|
||||||
|
DynContext::device_get_internal_counters(&*self.context, &self.id, self.data.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
/// Apply a callback to this `Device`'s underlying backend device.
|
/// Apply a callback to this `Device`'s underlying backend device.
|
||||||
///
|
///
|
||||||
/// If this `Device` is implemented by the backend API given by `A` (Vulkan,
|
/// If this `Device` is implemented by the backend API given by `A` (Vulkan,
|
||||||
|
Loading…
Reference in New Issue
Block a user