mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-22 06:38:09 +02:00
u_vector_add() don't keep the returned pointers valid.
After the initial size allocated in u_vector_init() is reached it will
allocate a bigger buffer and copy data from older buffer to the new
one and free the old buffer, making all the previous pointers returned
by u_vector_add() invalid and crashing the application when trying to
access it.
This is reproduced when running
dEQP-VK.synchronization.signal_order.timeline_semaphore.* in DG2 SKUs
that has 4 CCS engines, INTEL_COMPUTE_CLASS=1 is set and of course
perfetto build is enabled.
To fix this issue here I'm moving the storage/allocation of
struct intel_ds_queue to struct anv_queue/iris_batch and using
struct list_head to maintain a chain of intel_ds_queue of the
intel_ds_device.
This allows us to append or remove queues dynamically in future if
necessary.
Fixes: e760c5b37b ("anv: add perfetto source")
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20977>
219 lines
6.6 KiB
C
219 lines
6.6 KiB
C
/*
|
|
* Copyright © 2021 Intel Corporation
|
|
*
|
|
* 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 without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 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.
|
|
*/
|
|
|
|
#ifndef INTEL_DRIVER_DS_H
|
|
#define INTEL_DRIVER_DS_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#include "util/macros.h"
|
|
#include "util/perf/u_trace.h"
|
|
#include "util/u_vector.h"
|
|
|
|
#include "dev/intel_device_info.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
enum intel_ds_api {
|
|
INTEL_DS_API_OPENGL,
|
|
INTEL_DS_API_VULKAN,
|
|
};
|
|
|
|
enum intel_ds_stall_flag {
|
|
INTEL_DS_DEPTH_CACHE_FLUSH_BIT = BITFIELD_BIT(0),
|
|
INTEL_DS_DATA_CACHE_FLUSH_BIT = BITFIELD_BIT(1),
|
|
INTEL_DS_HDC_PIPELINE_FLUSH_BIT = BITFIELD_BIT(2),
|
|
INTEL_DS_RENDER_TARGET_CACHE_FLUSH_BIT = BITFIELD_BIT(3),
|
|
INTEL_DS_TILE_CACHE_FLUSH_BIT = BITFIELD_BIT(4),
|
|
INTEL_DS_STATE_CACHE_INVALIDATE_BIT = BITFIELD_BIT(5),
|
|
INTEL_DS_CONST_CACHE_INVALIDATE_BIT = BITFIELD_BIT(6),
|
|
INTEL_DS_VF_CACHE_INVALIDATE_BIT = BITFIELD_BIT(7),
|
|
INTEL_DS_TEXTURE_CACHE_INVALIDATE_BIT = BITFIELD_BIT(8),
|
|
INTEL_DS_INST_CACHE_INVALIDATE_BIT = BITFIELD_BIT(9),
|
|
INTEL_DS_STALL_AT_SCOREBOARD_BIT = BITFIELD_BIT(10),
|
|
INTEL_DS_DEPTH_STALL_BIT = BITFIELD_BIT(11),
|
|
INTEL_DS_CS_STALL_BIT = BITFIELD_BIT(12),
|
|
INTEL_DS_UNTYPED_DATAPORT_CACHE_FLUSH_BIT = BITFIELD_BIT(13),
|
|
INTEL_DS_PSS_STALL_SYNC_BIT = BITFIELD_BIT(14),
|
|
};
|
|
|
|
/* Convert internal driver PIPE_CONTROL stall bits to intel_ds_stall_flag. */
|
|
typedef enum intel_ds_stall_flag (*intel_ds_stall_cb_t)(uint32_t flags);
|
|
|
|
enum intel_ds_queue_stage {
|
|
INTEL_DS_QUEUE_STAGE_CMD_BUFFER,
|
|
INTEL_DS_QUEUE_STAGE_GENERATE_DRAWS,
|
|
INTEL_DS_QUEUE_STAGE_STALL,
|
|
INTEL_DS_QUEUE_STAGE_COMPUTE,
|
|
INTEL_DS_QUEUE_STAGE_RENDER_PASS,
|
|
INTEL_DS_QUEUE_STAGE_BLORP,
|
|
INTEL_DS_QUEUE_STAGE_DRAW,
|
|
INTEL_DS_QUEUE_STAGE_DRAW_MESH,
|
|
INTEL_DS_QUEUE_STAGE_N_STAGES,
|
|
};
|
|
|
|
struct intel_ds_device {
|
|
struct intel_device_info info;
|
|
|
|
/* DRM fd */
|
|
int fd;
|
|
|
|
/* API of this device */
|
|
enum intel_ds_api api;
|
|
|
|
/* GPU identifier (minor number) */
|
|
uint32_t gpu_id;
|
|
|
|
/* Clock identifier for this device. */
|
|
uint32_t gpu_clock_id;
|
|
|
|
/* The timestamp at the point where we first emitted the clock_sync..
|
|
* this will be a *later* timestamp that the first GPU traces (since
|
|
* we capture the first clock_sync from the CPU *after* the first GPU
|
|
* tracepoints happen). To avoid confusing perfetto we need to drop
|
|
* the GPU traces with timestamps before this.
|
|
*/
|
|
uint64_t sync_gpu_ts;
|
|
|
|
/* Next timestamp after which we should resend a clock correlation. */
|
|
uint64_t next_clock_sync_ns;
|
|
|
|
/* Unique perfetto identifier for the context */
|
|
uint64_t iid;
|
|
|
|
/* Event ID generator (manipulate only inside
|
|
* IntelRenderpassDataSource::Trace)
|
|
*/
|
|
uint64_t event_id;
|
|
|
|
/* Start of unique IID for device generated events */
|
|
uint64_t start_app_event_iids;
|
|
|
|
/* Last app event iid (manipulate only inside
|
|
* IntelRenderpassDataSource::Trace)
|
|
*/
|
|
uint64_t current_app_event_iid;
|
|
|
|
/* Hash table of application generated events (string -> iid) (manipulate
|
|
* only inside IntelRenderpassDataSource::Trace)
|
|
*/
|
|
struct hash_table *app_events;
|
|
|
|
struct u_trace_context trace_context;
|
|
|
|
/* List of intel_ds_queue */
|
|
struct list_head queues;
|
|
};
|
|
|
|
struct intel_ds_stage {
|
|
/* Unique hw_queue IID */
|
|
uint64_t queue_iid;
|
|
|
|
/* Unique stage IID */
|
|
uint64_t stage_iid;
|
|
|
|
/* Start timestamp of the last work element. We have a array indexed by
|
|
* level so that we can track multi levels of events (like
|
|
* primary/secondary command buffers).
|
|
*/
|
|
uint64_t start_ns[5];
|
|
|
|
/* Current number of valid elements in start_ns */
|
|
uint32_t level;
|
|
};
|
|
|
|
struct intel_ds_queue {
|
|
struct list_head link;
|
|
|
|
/* Device this queue belongs to */
|
|
struct intel_ds_device *device;
|
|
|
|
/* Unique name of the queue */
|
|
char name[80];
|
|
|
|
/* Counter incremented on each intel_ds_end_submit() call */
|
|
uint64_t submission_id;
|
|
|
|
struct intel_ds_stage stages[INTEL_DS_QUEUE_STAGE_N_STAGES];
|
|
};
|
|
|
|
struct intel_ds_flush_data {
|
|
struct intel_ds_queue *queue;
|
|
|
|
/* u_trace element in which we copy other traces in case we deal with
|
|
* reusable command buffers.
|
|
*/
|
|
struct u_trace trace;
|
|
|
|
/* Unique submission ID associated with the trace */
|
|
uint64_t submission_id;
|
|
};
|
|
|
|
void intel_driver_ds_init(void);
|
|
|
|
void intel_ds_device_init(struct intel_ds_device *device,
|
|
const struct intel_device_info *devinfo,
|
|
int drm_fd,
|
|
uint32_t gpu_id,
|
|
enum intel_ds_api api);
|
|
void intel_ds_device_fini(struct intel_ds_device *device);
|
|
|
|
struct intel_ds_queue *
|
|
intel_ds_device_init_queue(struct intel_ds_device *device,
|
|
struct intel_ds_queue *queue,
|
|
const char *fmt_name,
|
|
...);
|
|
|
|
void intel_ds_flush_data_init(struct intel_ds_flush_data *data,
|
|
struct intel_ds_queue *queue,
|
|
uint64_t submission_id);
|
|
|
|
void intel_ds_flush_data_fini(struct intel_ds_flush_data *data);
|
|
|
|
#ifdef HAVE_PERFETTO
|
|
|
|
uint64_t intel_ds_begin_submit(struct intel_ds_queue *queue);
|
|
void intel_ds_end_submit(struct intel_ds_queue *queue,
|
|
uint64_t start_ts);
|
|
|
|
#else
|
|
|
|
static inline uint64_t intel_ds_begin_submit(struct intel_ds_queue *queue)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static inline void intel_ds_end_submit(struct intel_ds_queue *queue,
|
|
uint64_t start_ts)
|
|
{
|
|
}
|
|
|
|
#endif /* HAVE_PERFETTO */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* INTEL_DRIVER_DS_H */
|