1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2020 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#ifndef CROCUS_FINE_FENCE_DOT_H
25bf215546Sopenharmony_ci#define CROCUS_FINE_FENCE_DOT_H
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include <stdbool.h>
28bf215546Sopenharmony_ci#include <stdint.h>
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "crocus_screen.h"
31bf215546Sopenharmony_ci#include "crocus_resource.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci/**
34bf215546Sopenharmony_ci * A lightweight sequence number fence.
35bf215546Sopenharmony_ci *
36bf215546Sopenharmony_ci * We emit PIPE_CONTROLs inside a batch (possibly in the middle)
37bf215546Sopenharmony_ci * which update a monotonically increasing, 32-bit counter.  We
38bf215546Sopenharmony_ci * can then check if that moment has passed by either:
39bf215546Sopenharmony_ci *
40bf215546Sopenharmony_ci * 1. Checking on the CPU by snooping on the DWord via a coherent map
41bf215546Sopenharmony_ci *
42bf215546Sopenharmony_ci * 2. Blocking on the GPU with MI_SEMAPHORE_WAIT from a second batch
43bf215546Sopenharmony_ci *    (relying on mid-batch preemption to switch GPU execution to the
44bf215546Sopenharmony_ci *    batch that writes it).
45bf215546Sopenharmony_ci */
46bf215546Sopenharmony_cistruct crocus_fine_fence {
47bf215546Sopenharmony_ci   struct pipe_reference reference;
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   /** Buffer where the seqno lives */
50bf215546Sopenharmony_ci   struct crocus_state_ref ref;
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   /** Coherent CPU map of the buffer containing the seqno DWord. */
53bf215546Sopenharmony_ci   const uint32_t *map;
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci   /**
56bf215546Sopenharmony_ci    * A drm_syncobj pointing which will be signaled at the end of the
57bf215546Sopenharmony_ci    * batch which writes this seqno.  This can be used to block until
58bf215546Sopenharmony_ci    * the seqno has definitely passed (but may wait longer than necessary).
59bf215546Sopenharmony_ci    */
60bf215546Sopenharmony_ci   struct crocus_syncobj *syncobj;
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci#define CROCUS_FENCE_BOTTOM_OF_PIPE 0x0 /**< Written by bottom-of-pipe flush */
63bf215546Sopenharmony_ci#define CROCUS_FENCE_TOP_OF_PIPE    0x1 /**< Written by top-of-pipe flush */
64bf215546Sopenharmony_ci#define CROCUS_FENCE_END            0x2 /**< Written at the end of a batch */
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   /** Information about the type of flush involved (see CROCUS_FENCE_*) */
67bf215546Sopenharmony_ci   uint32_t flags;
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci   /**
70bf215546Sopenharmony_ci    * Sequence number expected to be written by the flush we inserted
71bf215546Sopenharmony_ci    * when creating this fence.  The crocus_fine_fence is 'signaled' when *@map
72bf215546Sopenharmony_ci    * (written by the flush on the GPU) is greater-than-or-equal to @seqno.
73bf215546Sopenharmony_ci    */
74bf215546Sopenharmony_ci   uint32_t seqno;
75bf215546Sopenharmony_ci};
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_civoid crocus_fine_fence_init(struct crocus_batch *batch);
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_cistruct crocus_fine_fence *crocus_fine_fence_new(struct crocus_batch *batch,
80bf215546Sopenharmony_ci                                                unsigned flags);
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_civoid crocus_fine_fence_destroy(struct crocus_screen *screen,
83bf215546Sopenharmony_ci                               struct crocus_fine_fence *sq);
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_cistatic inline void
86bf215546Sopenharmony_cicrocus_fine_fence_reference(struct crocus_screen *screen,
87bf215546Sopenharmony_ci                            struct crocus_fine_fence **dst,
88bf215546Sopenharmony_ci                            struct crocus_fine_fence *src)
89bf215546Sopenharmony_ci{
90bf215546Sopenharmony_ci   if (pipe_reference(&(*dst)->reference, &src->reference))
91bf215546Sopenharmony_ci      crocus_fine_fence_destroy(screen, *dst);
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   *dst = src;
94bf215546Sopenharmony_ci}
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci/**
97bf215546Sopenharmony_ci * Return true if this seqno has passed.
98bf215546Sopenharmony_ci *
99bf215546Sopenharmony_ci * NULL is considered signaled.
100bf215546Sopenharmony_ci */
101bf215546Sopenharmony_cistatic inline bool
102bf215546Sopenharmony_cicrocus_fine_fence_signaled(const struct crocus_fine_fence *sq)
103bf215546Sopenharmony_ci{
104bf215546Sopenharmony_ci   if (sq && !sq->map)
105bf215546Sopenharmony_ci      return false;
106bf215546Sopenharmony_ci   return !sq || (READ_ONCE(*sq->map) >= sq->seqno);
107bf215546Sopenharmony_ci}
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci#endif
110