Skip to content

Commit 3bfc7f9

Browse files
wip: test timestamping for h264
1 parent 7dc53d8 commit 3bfc7f9

4 files changed

Lines changed: 80 additions & 0 deletions

File tree

‎src/encoder/h264/api.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,15 @@ impl H264Encoder {
9393
self.sps_written = true;
9494
}
9595

96+
let cpu_start = std::time::Instant::now();
9697
encoded_data.extend_from_slice(&self.encode_frame_internal(
9798
gop_position,
9899
frame_num,
99100
pic_order_cnt,
100101
is_idr,
101102
)?);
103+
let cpu_elapsed = cpu_start.elapsed();
104+
debug!("CPU encode wall time: {:.2} µs", cpu_elapsed.as_micros());
102105

103106
self.encode_frame_num += 1;
104107
if is_reference && !is_b_frame {

‎src/encoder/h264/encode.rs‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,22 @@ impl H264Encoder {
6161
)?;
6262
}
6363

64+
// Reset and write start timestamp
65+
unsafe {
66+
self.context.device().cmd_reset_query_pool(
67+
self.encode_command_buffer,
68+
self.timestamp_query_pool,
69+
0,
70+
2,
71+
);
72+
self.context.device().cmd_write_timestamp(
73+
self.encode_command_buffer,
74+
vk::PipelineStageFlags::TOP_OF_PIPE,
75+
self.timestamp_query_pool,
76+
0, // query index 0 = start
77+
);
78+
}
79+
6480
// Transition DPB images for encode.
6581
let ref_dpb_slots: Vec<u8> = self.l0_references.iter().map(|r| r.dpb_slot).collect();
6682
unsafe {
@@ -584,6 +600,16 @@ impl H264Encoder {
584600
);
585601
}
586602

603+
// Write end timestamp
604+
unsafe {
605+
self.context.device().cmd_write_timestamp(
606+
self.encode_command_buffer,
607+
vk::PipelineStageFlags::BOTTOM_OF_PIPE,
608+
self.timestamp_query_pool,
609+
1, // query index 1 = end
610+
);
611+
}
612+
587613
// End query.
588614
unsafe {
589615
self.context
@@ -624,6 +650,25 @@ impl H264Encoder {
624650
)?
625651
};
626652

653+
// Read GPU timestamps (fence already signaled from submit)
654+
unsafe {
655+
let result = self.context.device().get_query_pool_results(
656+
self.timestamp_query_pool,
657+
0, // first_query
658+
&mut self.gpu_timestamps, // data slice (length 2)
659+
vk::QueryResultFlags::WAIT | vk::QueryResultFlags::TYPE_64,
660+
);
661+
if result.is_ok() {
662+
let encode_time_ns = (self.gpu_timestamps[1] - self.gpu_timestamps[0]) as f32
663+
* self.timestamp_period;
664+
debug!(
665+
"GPU encode time: {:.2} µs ({:.2} ms)",
666+
encode_time_ns / 1000.0,
667+
encode_time_ns / 1_000_000.0
668+
);
669+
}
670+
}
671+
627672
// Mark DPB slot as active.
628673
self.dpb_slot_active[self.current_dpb_slot as usize] = true;
629674

‎src/encoder/h264/init.rs‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,26 @@ impl H264Encoder {
524524
}
525525
.map_err(|e| PixelForgeError::QueryPool(e.to_string()))?;
526526

527+
// Create timestamping query pool and resources
528+
let timestamp_query_pool_create_info = vk::QueryPoolCreateInfo::default()
529+
.query_type(vk::QueryType::TIMESTAMP)
530+
.query_count(2); // start and end
531+
532+
let timestamp_query_pool = unsafe {
533+
context
534+
.device()
535+
.create_query_pool(&timestamp_query_pool_create_info, None)
536+
}
537+
.map_err(|e| PixelForgeError::QueryPool(e.to_string()))?;
538+
539+
let timestamp_period = unsafe {
540+
context
541+
.instance()
542+
.get_physical_device_properties(context.physical_device())
543+
.limits
544+
.timestamp_period
545+
};
546+
527547
// Create DPB and GOP structure.
528548
// The DPB size should match the actual number of allocated DPB slots.
529549
let mut dpb = DecodedPictureBuffer::new();
@@ -591,6 +611,9 @@ impl H264Encoder {
591611
encode_command_buffer,
592612
encode_fence,
593613
query_pool,
614+
timestamp_query_pool,
615+
gpu_timestamps: [0; 2],
616+
timestamp_period,
594617
sps_written: false,
595618
// has_reference: false, // removed
596619
// reference_frame_num: 0, // removed

‎src/encoder/h264/mod.rs‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ pub struct H264Encoder {
8585
encode_fence: vk::Fence,
8686
query_pool: vk::QueryPool,
8787

88+
// Timestamping resources
89+
timestamp_query_pool: vk::QueryPool,
90+
gpu_timestamps: [u64; 2], // start and end timestamps
91+
timestamp_period: f32, // nanoseconds per timestamp unit
92+
8893
// SPS/PPS written flag.
8994
sps_written: bool,
9095

@@ -159,6 +164,10 @@ impl Drop for H264Encoder {
159164
if let Some(q) = self.context.video_encode_queue() {
160165
let _ = self.context.device().queue_wait_idle(q);
161166
}
167+
// TODO(dathorse): Move into destroy_encoder_resources as EncoderResources field..
168+
self.context
169+
.device()
170+
.destroy_query_pool(self.timestamp_query_pool, None);
162171
destroy_encoder_resources(
163172
self.context.device(),
164173
&self.video_queue_fn,

0 commit comments

Comments
 (0)