Skip to main content

CounterSampleBuffer

Struct CounterSampleBuffer 

Source
pub struct CounterSampleBuffer { /* private fields */ }
Expand description

Re-exports the Metal framework surface for this item. Apple’s id<MTLCounterSampleBuffer> — storage for GPU counter samples. Mirrors the Metal framework counterpart for this type.

Implementations§

Source§

impl CounterSampleBuffer

Source

pub const fn as_ptr(&self) -> *mut c_void

Mirrors the Metal framework constant fn.

Source§

impl CounterSampleBuffer

Source

pub fn sample_count(&self) -> usize

Number of samples available in the buffer.

Source

pub fn resolve_range(&self, range: Range<usize>) -> Option<Vec<u8>>

Resolve raw counter bytes for range.

Examples found in repository?
examples/07_advanced_objects.rs (line 98)
11fn main() {
12    let device = MetalDevice::system_default().expect("Metal device available");
13    let queue = device.new_command_queue().expect("command queue");
14    let counter_sets = device.counter_set_names();
15    println!("counter sets: {counter_sets:?}");
16
17    if let Some(event) = device.new_shared_event() {
18        event.set_signaled_value(1);
19        println!("event signaled value={}", event.signaled_value());
20        let signal = queue
21            .new_command_buffer()
22            .expect("event signal command buffer");
23        signal
24            .encode_signal_event(&event, 2)
25            .expect("encode event signal");
26        signal.commit().expect("commit event signal");
27        signal
28            .wait_until_completed()
29            .expect("complete event signal");
30        println!(
31            "event reached value 2: {}",
32            event.wait_until_signaled_value(2, 1_000),
33        );
34
35        let wait = queue
36            .new_command_buffer()
37            .expect("event wait command buffer");
38        wait.encode_wait_for_event(&event, 2)
39            .expect("encode event wait");
40        wait.commit().expect("commit event wait");
41        wait.wait_until_completed().expect("complete event wait");
42    }
43
44    let fence_a = device.new_fence();
45    let fence_b = device.new_fence();
46    let sample_buffer = counter_sets.first().and_then(|name| {
47        if device.supports_counter_sampling(counter_sampling_point::AT_BLIT_BOUNDARY) {
48            device
49                .new_counter_sample_buffer(name, 2, storage_mode::SHARED, Some("example-samples"))
50                .ok()
51        } else {
52            None
53        }
54    });
55
56    let src = device
57        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
58        .expect("source buffer");
59    let dst = device
60        .new_buffer(64, resource_options::STORAGE_MODE_SHARED)
61        .expect("destination buffer");
62    let blit = queue.new_command_buffer().expect("blit command buffer");
63    let mut encoder = blit.new_blit_command_encoder().expect("blit encoder");
64    encoder
65        .fill_buffer(&src, 0..64, b'Q')
66        .expect("fill source buffer");
67    if let Some(fence) = fence_a.as_ref() {
68        encoder.update_fence(fence).expect("update fence");
69    }
70    encoder.end_encoding().expect("end first blit encoder");
71    blit.commit().expect("commit first blit");
72    blit.wait_until_completed().expect("complete first blit");
73
74    let blit = queue
75        .new_command_buffer()
76        .expect("second blit command buffer");
77    let mut encoder = blit
78        .new_blit_command_encoder()
79        .expect("second blit encoder");
80    if let Some(fence) = fence_a.as_ref() {
81        encoder.wait_for_fence(fence).expect("wait for fence");
82    }
83    if let Some(sample_buffer) = sample_buffer.as_ref() {
84        encoder
85            .sample_counters(sample_buffer, 0, false)
86            .expect("sample counters");
87    }
88    encoder
89        .copy_buffer(&src, 0, &dst, 0, 64)
90        .expect("copy buffers");
91    encoder.end_encoding().expect("end second blit encoder");
92    blit.commit().expect("commit second blit");
93    blit.wait_until_completed().expect("complete second blit");
94    if let Some(sample_buffer) = sample_buffer.as_ref() {
95        println!(
96            "resolved counter bytes={}",
97            sample_buffer
98                .resolve_range(0..1)
99                .map_or(0, |bytes| bytes.len())
100        );
101    }
102
103    let library = device
104        .new_library_with_source(common::COMPUTE_SRC)
105        .expect("compile compute library");
106    let increment = library
107        .new_function("increment")
108        .expect("increment function");
109    let pipeline = device
110        .new_compute_pipeline_state(&increment)
111        .expect("compute pipeline");
112    let visible_table = pipeline.new_visible_function_table(1);
113    let intersection_table = if device.supports_raytracing() {
114        pipeline.new_intersection_function_table(1)
115    } else {
116        None
117    };
118    if let Some(table) = intersection_table.as_ref() {
119        table.set_opaque_triangle_intersection_function(intersection_function_signature::NONE, 0);
120    }
121    let acceleration_structure = if device.supports_raytracing() {
122        device.new_acceleration_structure_with_size(256)
123    } else {
124        None
125    };
126
127    let buffer = device
128        .new_buffer(16, resource_options::STORAGE_MODE_SHARED)
129        .expect("compute buffer");
130    common::write_u32_words(&buffer, &[1, 2, 3, 4]);
131    let texture = device
132        .new_texture(apple_metal::TextureDescriptor::new_2d(
133            4,
134            4,
135            apple_metal::pixel_format::BGRA8UNORM,
136        ))
137        .expect("compute texture");
138    let compute = queue.new_command_buffer().expect("compute command buffer");
139    let mut encoder = compute
140        .new_compute_command_encoder()
141        .expect("compute command encoder");
142    encoder
143        .set_compute_pipeline_state(&pipeline)
144        .expect("bind compute pipeline");
145    encoder
146        .set_buffer(&buffer, 0, 0)
147        .expect("bind compute buffer");
148    encoder
149        .set_texture(&texture, 1)
150        .expect("bind compute texture");
151    if let Some(fence) = fence_a.as_ref() {
152        encoder.wait_for_fence(fence).expect("wait for fence");
153    }
154    if let Some(table) = visible_table.as_ref() {
155        encoder
156            .set_visible_function_table(table, 2)
157            .expect("bind visible function table");
158    }
159    if let Some(table) = intersection_table.as_ref() {
160        encoder
161            .set_intersection_function_table(table, 3)
162            .expect("bind intersection function table");
163    }
164    if let Some(acceleration_structure) = acceleration_structure.as_ref() {
165        encoder
166            .set_acceleration_structure(acceleration_structure, 4)
167            .expect("bind acceleration structure");
168    }
169    encoder
170        .dispatch_threadgroups((1, 1, 1), (4, 1, 1))
171        .expect("dispatch compute");
172    if let Some(fence) = fence_b.as_ref() {
173        encoder.update_fence(fence).expect("update fence");
174    }
175    encoder.end_encoding().expect("end compute encoder");
176    compute.commit().expect("commit compute");
177    compute.wait_until_completed().expect("complete compute");
178    println!(
179        "compute buffer after dispatch: {:?}",
180        common::read_u32_words(&buffer, 4)
181    );
182
183    if let Some(indirect) = device.new_indirect_command_buffer(
184        indirect_command_type::CONCURRENT_DISPATCH,
185        1,
186        0,
187        0,
188        4,
189        resource_options::STORAGE_MODE_PRIVATE,
190    ) {
191        indirect.reset_range(0..1);
192        println!("indirect command buffer size={}", indirect.size());
193    }
194
195    if let Some(heap) = device.new_heap(1 << 20, storage_mode::SHARED) {
196        if let Ok(residency_set) = device.new_residency_set(Some("example-residency"), 4) {
197            let heap_buffer = heap
198                .new_buffer(256, resource_options::STORAGE_MODE_SHARED)
199                .expect("heap buffer");
200            residency_set.add_buffer(&heap_buffer);
201            residency_set.add_heap(&heap);
202            residency_set.commit();
203            residency_set.request_residency();
204            queue.add_residency_set(&residency_set);
205            queue.remove_residency_set(&residency_set);
206            residency_set.end_residency();
207            residency_set.remove_all_allocations();
208            residency_set.commit();
209            println!(
210                "residency allocation count={}",
211                residency_set.allocation_count()
212            );
213        } else {
214            println!("residency sets unavailable on this OS");
215        }
216    }
217
218    if let Some(capture_manager) = CaptureManager::shared() {
219        println!(
220            "capture supported for developer tools={} active={}",
221            capture_manager.supports_destination(capture_destination::DEVELOPER_TOOLS),
222            capture_manager.is_capturing(),
223        );
224        if let Some(scope) = capture_manager.new_capture_scope_with_device(&device) {
225            scope.begin();
226            scope.end();
227        }
228        if let Some(scope) = capture_manager.new_capture_scope_with_command_queue(&queue) {
229            scope.begin();
230            scope.end();
231        }
232    }
233}

Trait Implementations§

Source§

impl Drop for CounterSampleBuffer

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl Send for CounterSampleBuffer

Source§

impl Sync for CounterSampleBuffer

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.