>
>
>-----Original Message-----
>From: Ceraolo Spurio, Daniele 
>Sent: Monday, March 14, 2016 12:16 PM
>To: Morton, Derek J <derek.j.mor...@intel.com>; intel-gfx@lists.freedesktop.org
>Subject: Re: [PATCH i-g-t v3 2/6] lib/intel_batchbuffer: Add functions to be 
>used in the scheduler test
>
>
>
>On 10/03/16 11:03, Derek Morton wrote:
>> Adds functions to create a number of different batch buffers to 
>> perform several functions including:
>> Batch buffer which will run for a long duration to provide a delay on 
>> a specified ring.
>> Function to calibrate the delay batch buffer to run for a specified 
>> period of time.
>> Function to create a batch buffer which writes timestamps to a buffer object.
>> Function to compare timestamps allowing for wrapping of the values.
>>
>> v2: Moved code to intel_batchbuffer (Daniel Vetter)
>>      Addressed review comments from Daniele Ceraolo Spurio
>>
>> Signed-off-by: Derek Morton <derek.j.mor...@intel.com>
>> ---
>>   lib/intel_batchbuffer.c | 384 
>> +++++++++++++++++++++++++++++++++++++++++++++++-
>>   lib/intel_batchbuffer.h |  14 ++
>>   2 files changed, 393 insertions(+), 5 deletions(-)
>>
>> diff --git a/lib/intel_batchbuffer.c b/lib/intel_batchbuffer.c index 
>> 692521f..30e78c5 100644
>> --- a/lib/intel_batchbuffer.c
>> +++ b/lib/intel_batchbuffer.c
>> @@ -1,8 +1,8 @@
>>   
>> /*********************************************************************
>> *****
>> - *
>> + *
>>    * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
>>    * All Rights Reserved.
>> - *
>> + *
>>    * Permission is hereby granted, free of charge, to any person obtaining a
>>    * copy of this software and associated documentation files (the
>>    * "Software"), to deal in the Software without restriction, 
>> including @@ -10,11 +10,11 @@
>>    * distribute, sub license, and/or sell copies of the Software, and to
>>    * permit persons to whom the Software is furnished to do so, subject to
>>    * the following conditions:
>> - *
>> + *
>>    * The above copyright notice and this permission notice (including the
>>    * next paragraph) shall be included in all copies or substantial portions
>>    * of the Software.
>> - *
>> + *
>>    * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
>>    * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>>    * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
>> @@ -22,7 +22,7 @@
>>    * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
>>    * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
>>    * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
>> - *
>> + *
>>    
>> **********************************************************************
>> ****/
>>   
>>   #include <inttypes.h>
>> @@ -30,6 +30,8 @@
>>   #include <stdio.h>
>>   #include <string.h>
>>   #include <assert.h>
>> +#include <stdint.h>
>> +#include <time.h>
>>   
>>   #include "drm.h"
>>   #include "drmtest.h"
>> @@ -42,6 +44,7 @@
>>   #include "ioctl_wrappers.h"
>>   #include "media_spin.h"
>>   #include "gpgpu_fill.h"
>> +#include "igt_gt.h"
>>   
>>   #include <i915_drm.h>
>>   
>> @@ -817,3 +820,374 @@ igt_media_spinfunc_t igt_get_media_spinfunc(int 
>> devid)
>>   
>>      return spin;
>>   }
>> +
>> +#define SEC_TO_NSEC (1000 * 1000 * 1000) #define DWORDS_TO_BYTES(x) 
>> +((x)*4)
>> +
>> +#define MI_STORE_REGISTER_MEM(LENGTH)   ((0x024 << 23) | ((LENGTH - 2) & 
>> 0xff))
>> +#define MI_MATH(NrInst)                 ((0x01A << 23) | ((NrInst - 1) & 
>> 0x3f))
>> +#define MI_CONDITIONAL_BATCH_BUFFER_END ((0x036 << 23) | (1 << 21) | 2)
>> +#define MI_COPY_MEM_MEM                 ((0x02E << 23) | (3))
>> +
>> +#define ALU_LOAD(TO, FROM)  ((0x080 << 20) | ((TO) << 10) | (FROM))
>> +#define ALU_SUB             ( 0x101 << 20)
>> +#define ALU_STORE(TO, FROM) ((0x180 << 20) | ((TO) << 10) | (FROM))
>> +
>> +#define TIMESTAMP_offset      (0x358) /* Elapsed time from system start */
>> +#define CTX_TIMESTAMP_offset  (0x3A8) /* Elapsed Time from context 
>> +creation */ #define ALU_GPU_R0_LSB_offset (0x600) #define 
>> +ALU_GPU_R0_MSB_offset (0x604) #define ALU_GPU_R1_LSB_offset (0x608) 
>> +#define ALU_GPU_R1_MSB_offset (0x60C) #define ALU_GPU_R2_LSB_offset 
>> +(0x610) #define ALU_GPU_R2_MSB_offset (0x614)
>> +
>> +#define ALU_R0_ENCODING   (0x00)
>> +#define ALU_R1_ENCODING   (0x01)
>> +#define ALU_SRCA_ENCODING (0x20)
>> +#define ALU_SRCB_ENCODING (0x21)
>> +#define ALU_ACCU_ENCODING (0x31)
>> +
>> +static int bb_address_size_dw(int fd) {
>> +    if (intel_gen(intel_get_drm_devid(fd)) >= 8)
>> +            return 2;
>> +    else
>> +            return 1;
>> +}
>> +
>> +static uint32_t get_mmio_base(int ringid) {
>> +    switch (ringid) {
>> +    case I915_EXEC_RENDER:
>> +            return 0x02000;
>> +    case I915_EXEC_BSD:
>> +    case I915_EXEC_BSD | 1<<13: /* BSD1 */
>> +            return 0x12000;
>> +    case I915_EXEC_BSD | 2<<13: /* BSD2 */
>> +            return 0x1c000;
>> +    case I915_EXEC_BLT:
>> +            return 0x22000;
>> +    case I915_EXEC_VEBOX:
>> +            return 0x1A000;
>> +    default:
>> +            igt_assert_f(0, "Invalid ringid %d passed to 
>> get_mmio_base()\n", ringid);
>> +    }
>> +}
>> +
>> +/**
>> + * igt_batch_used
>> + * @batch batchbuffer to get offset from
>> + *
>> + * This returns the number of bytes of the batchbuffer that have been used.
>> + * e.g. The offset into the batchbuffer that the next OUT_BATCH would write 
>> to.
>> + *
>> + * Returns:
>> + * The number of bytes of the batchbuffer that have been used.
>> + */
>> +uint32_t igt_batch_used(struct intel_batchbuffer *batch) {
>> +    return batch->ptr - batch->buffer;
>> +}
>> +
>> +/**
>> + * igt_create_delay_bb:
>> + * @fd: file descriptor for i915 driver instance
>> + * @batch: Batch buffer to write to
>> + * ringid: Ring to create batch buffer for. e.g. I915_EXEC_RENDER
>
>ringid is the execution flag of the ring

Ok

>
>> + * loops: Number of times to loop
>> + * dest: Buffer to use for saving the current loop count and timestamp.
>> + *
>> + * This creates a batch buffer which will iterate a loop a specified 
>> +number
>> + * of times. Intended for creating batch buffers which take an 
>> +arbitarily
>> + * long time to execute. This can be useful to keep a ring busy while
>> + * constructing a test scenario.
>> + *
>> + * The dest buffer will have a number of Dwords written by the batch 
>> +buffer
>> + * when it runs. They are:
>> + * DW0 & DW1 - These are loaded with the value of 'loops' and are 
>> decremented
>> + *             as the batch buffer executes. They will be 0 after the batch
>> + *             buffer completes if it finished succesfully.
>> + * DW2 Timestamp - An indication of when the batch buffer ran allowing a
>> + *                 comparison between batch buffers to show execution order.
>> + *                 May wrap so igt_compare_timestamps() should be used to
>> + *                 compare timestamps.
>> + *                 The timestamp will wrap every few minutes.
>> + *
>> + */
>> +void igt_create_delay_bb(int fd, struct intel_batchbuffer *batch,
>
>Now that you're passing the batch from the outside you're only using the fd to 
>get the gen. However, the gen is already saved inside the batch so you could 
>get it from there and drop the fd parameter. the bb_address_size_dw would need 
>to be modified to get the batch or the gen as a parameter, but it looks like 
>an ok change to me. Same reasoning applies to other functions you've added.

Ok

>
>> +                         int ringid, uint32_t loops, drm_intel_bo 
>> +*dest) {
>> +    int addr_size_dw;
>> +    uint32_t mmio_base, jump_offset;
>> +
>> +    /* CMD parser blocks reading TIMESTAMP register on gen 7.5 */
>> +    igt_require(intel_gen(intel_get_drm_devid(fd)) >= 8);
>> +
>> +    addr_size_dw = bb_address_size_dw(fd);
>> +    mmio_base = get_mmio_base(ringid);
>> +    igt_assert(batch);
>> +    BEGIN_BATCH(32, 5);
>> +
>> +    /* store current timestamp in DW2 */
>> +    OUT_BATCH(MI_STORE_REGISTER_MEM(addr_size_dw + 2));
>> +    OUT_BATCH(mmio_base + TIMESTAMP_offset);
>> +    OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, 
>> +I915_GEM_DOMAIN_INSTRUCTION, DWORDS_TO_BYTES(2));
>> +
>> +    /* Load R0 with loops */
>> +    OUT_BATCH(MI_LOAD_REGISTER_IMM);
>> +    OUT_BATCH(mmio_base + ALU_GPU_R0_LSB_offset);
>> +    OUT_BATCH(loops);
>> +    OUT_BATCH(MI_LOAD_REGISTER_IMM);
>> +    OUT_BATCH(mmio_base + ALU_GPU_R0_MSB_offset);
>> +    OUT_BATCH(0x00000000);
>> +    /* Load R1 with 1 */
>> +    OUT_BATCH(MI_LOAD_REGISTER_IMM);
>> +    OUT_BATCH(mmio_base + ALU_GPU_R1_LSB_offset);
>> +    OUT_BATCH(0x00000001);
>> +    OUT_BATCH(MI_LOAD_REGISTER_IMM);
>> +    OUT_BATCH(mmio_base + ALU_GPU_R1_MSB_offset);
>> +    OUT_BATCH(0x00000000);
>> +    /* Copy R0 / R1 into SRCA / SRCB, Perform R0 - R1, Store result in R0 */
>> +    /* e.g. R0 -= 1 */
>> +    jump_offset=igt_batch_used(batch);
>
>for clarity the sampling of jump offset could go above the ALU comment (and 
>have a comment of its own)

Ok

>
>> +    OUT_BATCH(MI_MATH(4));
>> +    OUT_BATCH(ALU_LOAD(ALU_SRCA_ENCODING, ALU_R0_ENCODING));
>> +    OUT_BATCH(ALU_LOAD(ALU_SRCB_ENCODING, ALU_R1_ENCODING));
>> +    OUT_BATCH(ALU_SUB);
>> +    OUT_BATCH(ALU_STORE(ALU_R0_ENCODING, ALU_ACCU_ENCODING));
>> +    /* Copy R0 to dest
>> +     * On Gen8 MI_CONDITIONAL_BATCH_BUFFER_END BSD ring Compare address
>> +     * points to 2 Dwords, a mask (DW0) and data (DW1) which are ANDed
>> +     * together.
>> +     * On Gen9+, and the other rings on Gen8 Compare address points to
>> +     * just Data (DW0). For simplicity always copy R0 LSB to DW0 and DW1.
>> +     */
>> +    OUT_BATCH(MI_STORE_REGISTER_MEM(addr_size_dw + 2));
>> +    OUT_BATCH(mmio_base + ALU_GPU_R0_LSB_offset);
>> +    OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, 
>> I915_GEM_DOMAIN_INSTRUCTION, 0);
>> +    OUT_BATCH(MI_STORE_REGISTER_MEM(addr_size_dw + 2));
>> +    OUT_BATCH(mmio_base + ALU_GPU_R0_LSB_offset);
>> +    OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, 
>> I915_GEM_DOMAIN_INSTRUCTION, DWORDS_TO_BYTES(1));
>> +    /* Repeat until R0 == 0 */
>> +    OUT_BATCH(MI_CONDITIONAL_BATCH_BUFFER_END);
>> +    OUT_BATCH(0x00000000);
>> +    OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, 
>> I915_GEM_DOMAIN_INSTRUCTION, 0);
>> +    OUT_BATCH(MI_BATCH_BUFFER_START | (addr_size_dw - 1));
>> +    OUT_RELOC(batch->bo, I915_GEM_DOMAIN_INSTRUCTION, 0, jump_offset);
>> +
>> +    /* Should never get here, but end if it happens */
>> +    OUT_BATCH(MI_BATCH_BUFFER_END);
>> +    ADVANCE_BATCH();
>> +}
>> +
>> +/**
>> + * igt_create_timestamp_bb:
>> + * @fd: file descriptor for i915 driver instance
>> + * @batch: Batch buffer to write to
>> + * ringid: Ring to create batch buffer for. e.g. I915_EXEC_RENDER
>> + * dest: Buffer to use for saving the timestamps.
>> + * load: Buffer to access. Set NULL if not required.
>> + * write: If true and load is not NULL, will also write a timestamp 
>> +to load
>> + * buffer. If false and load is not NULL, will read from load buffer into 
>> dest.
>> + * Intended for dependency checking.
>> + *
>> + * This creates a batch buffer which writes timestamps into a buffer object.
>> + * If 'load' is non null, data is either written to 'load' or copied from 
>> 'load'
>> + * depending on whether 'write' is set.
>> + *
>> + * The dest buffer will have a number of Dwords written by the batch 
>> +buffer
>> + * when it runs. They are:
>> + * DW0 Reported timestamp - An indication of when the batch buffer ran 
>> allowing a
>> + *                          comparison between batch buffers to show 
>> execution order.
>> + *                          May wrap so igt_compare_timestamps() should be 
>> used to
>> + *                          compare timestamps.
>> + *                          The timestamp will wrap every few minutes.
>> + * DW2 Value copied from DW0 of load if write == false
>> + *
>> + */
>> +void igt_create_timestamp_bb(int fd, struct intel_batchbuffer *batch, int 
>> ringid,
>> +                             drm_intel_bo *dest, drm_intel_bo *load, 
>> +bool write)
>
>I still think that the timestamp capture should be its own function, because 
>it could be useful to add it multiple time in the same batch. 
>You could split that out in a separate function and then call it from 
>igt_create_timestamp_bb, i.e. something like:
>
>igt_emit_timestamp_sample(struct intel_batchbuffer *batch, int ringid, 
>drm_intel_bo *dest, unsigned dest_offset);

I can create a separate function. Will make it static for now as it is not 
needed outside this file.
>
>Personally I also still don't really like the "load" handling, which is not 
>related to timestamps in any way. won't oppose it if other people are ok with 
>it though.
>
>> +{
>> +    int addr_size_dw;
>> +    uint32_t mmio_base;
>> +
>> +    /* CMD parser blocks reading TIMESTAMP register on gen 7.5 */
>> +    igt_require(intel_gen(intel_get_drm_devid(fd)) >= 8);
>> +
>> +    addr_size_dw = bb_address_size_dw(fd);
>> +    mmio_base = get_mmio_base(ringid);
>> +    igt_assert(batch);
>> +
>> +    BEGIN_BATCH(3, 1);
>> +    /* store current reported timestamp in DW0 */
>> +    OUT_BATCH(MI_STORE_REGISTER_MEM(addr_size_dw + 2));
>> +    OUT_BATCH(mmio_base + TIMESTAMP_offset);
>> +    OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, 
>> +I915_GEM_DOMAIN_INSTRUCTION, DWORDS_TO_BYTES(0));
>> +
>> +    ADVANCE_BATCH();
>> +
>> +    if(load != NULL) {
>
>style: we tend to put a space between if/while/for and the parenthesis, but 
>you didn't anywhere in this patch

Ok

>
>> +            if(write) {
>> +                    BEGIN_BATCH(3, 1);
>> +                    OUT_BATCH(MI_STORE_REGISTER_MEM(addr_size_dw + 2));
>> +                    OUT_BATCH(mmio_base + TIMESTAMP_offset);
>> +                    OUT_RELOC(load, I915_GEM_DOMAIN_INSTRUCTION, 
>> I915_GEM_DOMAIN_INSTRUCTION, DWORDS_TO_BYTES(0));
>> +                    ADVANCE_BATCH();
>> +            }
>> +            else {
>
>weird indent

What is weird? The if and else line up and it is all tabs.

>
>> +                    BEGIN_BATCH(3, 2);
>> +                    OUT_BATCH(MI_COPY_MEM_MEM);
>> +                    OUT_RELOC(dest, I915_GEM_DOMAIN_INSTRUCTION, 
>> I915_GEM_DOMAIN_INSTRUCTION, DWORDS_TO_BYTES(2));
>> +                    OUT_RELOC(load, I915_GEM_DOMAIN_INSTRUCTION, 0, 
>> DWORDS_TO_BYTES(0));
>> +                    ADVANCE_BATCH();
>> +            }
>> +    }
>> +
>> +    BEGIN_BATCH(1, 0);
>> +    OUT_BATCH(MI_BATCH_BUFFER_END);
>> +    ADVANCE_BATCH();
>> +}
>> +
>> +/**
>> + * igt_create_noop_bb:
>> + * @batch: Batch buffer to write to
>> + * noops: Number of MI_NOOP instructions to add to the batch buffer.
>> + *
>> + * This creates a batch buffer with a specified number of MI_NOOP 
>> instructions.
>> + */
>> +void igt_create_noop_bb(struct intel_batchbuffer *batch, int noops) {
>> +    int loop;
>> +
>> +    igt_assert(batch);
>> +
>> +    BEGIN_BATCH(noops + 1, 0);
>> +    for(loop = 0; loop < noops; loop++)
>> +            OUT_BATCH(MI_NOOP);
>> +    OUT_BATCH(MI_BATCH_BUFFER_END);
>> +    ADVANCE_BATCH();
>> +
>> +}
>> +
>> +/* Store calibrated values so they only need calculating once.
>> + * Use intel_execution_engines array as list of supported rings  */ 
>> +static uint32_t *calibrated_ring_value = NULL;
>> +
>> +/**
>> + * igt_calibrate_delay_bb:
>> + * @fd: file descriptor for i915 driver instance
>> + * @bufmgr: Buffer manager to be used for creation of batch buffers
>> + * ringid: Ring to calibrate. e.g. I915_EXEC_RENDER
>> + *
>> + * This calculates the value of loops that would need to be passed to
>> + * igt_create_delay_bb() to create a delay of about 1 second on the 
>> +specified
>> + * ring.
>> + *
>> + * Returns:
>> + * uint32_t to be passed to igt_create_delay_bb().
>> + */
>> +/* 0x100000 will run for about 0.6 - 0.8 seconds (dependant on ring) 
>> +on BXT HW */ #define CAL_SEED (0x100000) uint32_t 
>> +igt_calibrate_delay_bb(int fd, drm_intel_bufmgr *bufmgr, int ringid) 
>> +{
>> +    uint32_t buf[2];
>> +    struct intel_batchbuffer *bb;
>> +    struct timespec start, end;
>> +    uint64_t duration;
>> +    uint64_t calibrated;
>> +    drm_intel_bo *target_bo;
>> +    int ring_index=0;
>> +
>> +/*  igt_assert(ringid < 8);
>> +    if(calibrated_ring_value[ringid] != 0)
>> +            return calibrated_ring_value[ringid];*/
>
>dead code

Removed

>
>> +
>> +    if(calibrated_ring_value == NULL) {
>> +            int count;
>> +            for(count = 0; intel_execution_engines[count].name != NULL; 
>> +count++) {}
>
>Can you add a comment to explain why this loop is required to count the 
>engines? it could also be possible to add a function in igt_gt to return the 
>exec_engines count, but I'm not sure that's worth the effort. Also,
>BSD1 and BSD2 will have the same calibration value so you can calibrate only 
>once for I915_EXEC_BSD

Can add a comment. It will require adding a load of logic to use a single 
calibration value for BSD1 and BSD2, and that would then make the assumption 
that they would have the same calibration value. I would prefer not to make 
such assumptions.

>
>> +            calibrated_ring_value = calloc(count, sizeof(uint32_t));
>> +            igt_assert(calibrated_ring_value);
>> +    }
>> +
>> +    /* Check if there is already a calibration value for this ring */
>> +    while(intel_execution_engines[ring_index].name != NULL) {
>> +            if((intel_execution_engines[ring_index].exec_id |
>> +                intel_execution_engines[ring_index].flags) == ringid) {
>> +                    if(calibrated_ring_value[ring_index] != 0) {
>> +                            return calibrated_ring_value[ring_index];
>> +                    }
>> +                    break;
>> +            }
>> +            ring_index++;
>
>Could use a for loop instead of incrementing on each iteration.

Ok

>
>> +    }
>> +
>> +    target_bo = drm_intel_bo_alloc(bufmgr, "target bo", BATCH_SZ, BATCH_SZ);
>> +    igt_assert(target_bo);
>> +
>> +    /* Put some non zero values in the target bo */
>> +    {
>
>This bracket used to give scope to the data variable doesn't look essential as 
>there are no other uses of a variable named data in this function
>
>> +            uint32_t data=0xffffffff;
>
>style: spaces around "="
>
>> +            drm_intel_bo_subdata(target_bo, 0, 4, &data);
>
>the subdata call can fail. In the tree we don't check the return code on every 
>usage, but I believe it is safer to do it. do_or_die() should do the trick.
>
>> +    }
>> +
>> +    bb = intel_batchbuffer_alloc(bufmgr, intel_get_drm_devid(fd));
>> +    igt_assert(bb);
>> +    igt_create_delay_bb(fd, bb, ringid, CAL_SEED, target_bo);
>> +
>> +    gem_quiescent_gpu(fd);
>> +    clock_gettime(CLOCK_MONOTONIC, &start);
>> +    intel_batchbuffer_flush_on_ring(bb, ringid);
>> +    /* This will not return until the bo has finished executing */
>> +    drm_intel_bo_wait_rendering(target_bo);
>> +    clock_gettime(CLOCK_MONOTONIC, &end);
>> +
>> +    drm_intel_bo_get_subdata(target_bo, 0, 4, (void*)buf);
>
>Why are you using a 2 words array to read only 1 word? what's the purpose of 
>buf[1]? if you don't need it you could reuse the data variable from above
>
>> +
>> +    /* buf[0] in the target buffer should be 0 if the batch buffer 
>> completed */
>> +    igt_assert_f(buf[0] == 0, "buf[0] expected 0x0, got 0x%x\n", 
>> +buf[0]);
>> +
>> +    duration = ((((uint64_t)end.tv_sec - (uint64_t)start.tv_sec) * 
>> SEC_TO_NSEC)
>> +               + (uint64_t)end.tv_nsec) - (uint64_t)start.tv_nsec;
>> +
>> +    calibrated = (((uint64_t)(CAL_SEED) * SEC_TO_NSEC) / duration);
>> +    igt_debug("Uncalibrated run took %" PRIu64 ".%04" PRIu64 "s\n",
>> +              duration / SEC_TO_NSEC,
>> +              (duration % SEC_TO_NSEC) / 100000);
>> +    drm_intel_bo_unreference(target_bo);
>> +    intel_batchbuffer_free(bb);
>> +
>> +    /* Sanity check. If duration < 100ms, something has clearly gone wrong 
>> */
>> +    igt_assert(duration > (SEC_TO_NSEC  / 10));
>> +
>> +    igt_assert_f(calibrated <= UINT32_MAX, "Calibrated value > 
>> +UINT32_MAX\n");
>> +
>> +    if(intel_execution_engines[ring_index].name != NULL)
>> +            calibrated_ring_value[ring_index] = (uint32_t)calibrated;
>> +    return (uint32_t)calibrated;
>> +}
>> +
>> +/**
>> + * igt_compare_timestamps:
>> + * @ts1: timestamp 1
>> + * @ts2: timestamp 2
>> + *
>> + * This compares two uint32_t timestamps. To handle wrapping it 
>> +assumes the
>> + * difference between the two timestamps is less than 1/4 the max 
>> +elapsed time
>> + * represented by the counters.
>> + * It also assumes the timestamps are samples from the same counter.
>> + *
>> + * Returns:
>> + * True if ts2 > ts1, allowing for counter wrapping, false otherwise.
>> + */
>> +
>> +bool igt_compare_timestamps(uint32_t ts1, uint32_t ts2) {
>> +    if (ts2 > ts1)
>
>This will return true if ts2 = 0xFFFFFFFF and ts1 = 0x00000001 even if
>ts1 came after ts2 due to wrapping.
>
>> +            return true;
>> +    else if ((ts1 > 0x80000000) && (ts2 < 0x40000000))
>> +            return true; /* Assuming timestamp counter wrapped */
>> +    else
>> +            return false;
>> +}
>
>You could use something like:
>
>     return (int32_t)(ts2 - ts1) > 0;

Ok

>
>This should give you the right result as long as the 2 samples are not more 
>than ~50% of the timestamp period apart
>
>Regards,
>Daniele
>
>> diff --git a/lib/intel_batchbuffer.h b/lib/intel_batchbuffer.h index 
>> 869747d..5b66fa3 100644
>> --- a/lib/intel_batchbuffer.h
>> +++ b/lib/intel_batchbuffer.h
>> @@ -323,4 +323,18 @@ typedef void (*igt_media_spinfunc_t)(struct 
>> intel_batchbuffer *batch,
>>   
>>   igt_media_spinfunc_t igt_get_media_spinfunc(int devid);
>>   
>> +uint32_t igt_batch_used(struct intel_batchbuffer *batch);
>> +
>> +void igt_create_delay_bb(int fd, struct intel_batchbuffer *batch,
>> +            int ringid, uint32_t loops, drm_intel_bo *dest);
>> +
>> +void igt_create_timestamp_bb(int fd, struct intel_batchbuffer *batch, int 
>> ringid,
>> +                    drm_intel_bo *dest, drm_intel_bo *load, bool write);
>> +
>> +void igt_create_noop_bb(struct intel_batchbuffer *batch, int noops);
>> +
>> +uint32_t igt_calibrate_delay_bb(int fd, drm_intel_bufmgr *bufmgr, int 
>> +ringid);
>> +
>> +bool igt_compare_timestamps(uint32_t ts1, uint32_t ts2);
>> +
>>   #endif
>
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to