1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
/**************************************************************************
*
* Copyright 2018-2019 Alyssa Rosenzweig
* Copyright 2018-2019 Collabora, Ltd.
* 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
* without limitation the rights to use, copy, modify, merge, publish,
* 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.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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 PAN_SCREEN_H
#define PAN_SCREEN_H
#include "pipe/p_screen.h"
#include "pipe/p_defines.h"
#include "renderonly/renderonly.h"
#include "util/u_dynarray.h"
#include "util/bitset.h"
#include <panfrost-misc.h>
#include "pan_allocate.h"
struct panfrost_context;
struct panfrost_resource;
struct panfrost_screen;
/* Flags for allocated memory */
/* This memory region is executable */
#define PAN_ALLOCATE_EXECUTE (1 << 0)
/* This memory region should be lazily allocated and grow-on-page-fault. Must
* be used in conjunction with INVISIBLE */
#define PAN_ALLOCATE_GROWABLE (1 << 1)
/* This memory region should not be mapped to the CPU */
#define PAN_ALLOCATE_INVISIBLE (1 << 2)
/* This memory region will be used for varyings and needs to have the cache
* bits twiddled accordingly */
#define PAN_ALLOCATE_COHERENT_LOCAL (1 << 3)
/* This region may not be used immediately and will not mmap on allocate
* (semantically distinct from INVISIBLE, which cannot never be mmaped) */
#define PAN_ALLOCATE_DELAY_MMAP (1 << 4)
/* Transient slab size. This is a balance between fragmentation against cache
* locality and ease of bookkeeping */
#define TRANSIENT_SLAB_PAGES (32) /* 128kb */
#define TRANSIENT_SLAB_SIZE (4096 * TRANSIENT_SLAB_PAGES)
/* Maximum number of transient slabs so we don't need dynamic arrays. Most
* interesting Mali boards are 4GB RAM max, so if the entire RAM was filled
* with transient slabs, you could never exceed (4GB / TRANSIENT_SLAB_SIZE)
* allocations anyway. By capping, we can use a fixed-size bitset for tracking
* free slabs, eliminating quite a bit of complexity. We can pack the free
* state of 8 slabs into a single byte, so for 128kb transient slabs the bitset
* occupies a cheap 4kb of memory */
#define MAX_TRANSIENT_SLABS (1024*1024 / TRANSIENT_SLAB_PAGES)
struct panfrost_screen {
struct pipe_screen base;
int fd;
unsigned gpu_id;
struct renderonly *ro;
/* Memory management is based on subdividing slabs with AMD's allocator */
struct pb_slabs slabs;
/* Transient memory management is based on borrowing fixed-size slabs
* off the screen (loaning them out to the batch). Dynamic array
* container of panfrost_bo */
struct util_dynarray transient_bo;
/* Set of free transient BOs */
BITSET_DECLARE(free_transient, MAX_TRANSIENT_SLABS);
/* While we're busy building up the job for frame N, the GPU is
* still busy executing frame N-1. So hold a reference to
* yesterjob */
int last_fragment_flushed;
struct panfrost_job *last_job;
};
static inline struct panfrost_screen *
pan_screen(struct pipe_screen *p)
{
return (struct panfrost_screen *)p;
}
/* Get a transient BO off the screen given a
* particular index */
static inline struct panfrost_bo *
pan_bo_for_index(struct panfrost_screen *screen, unsigned index)
{
return *(util_dynarray_element(&screen->transient_bo,
struct panfrost_bo *, index));
}
void
panfrost_drm_allocate_slab(struct panfrost_screen *screen,
struct panfrost_memory *mem,
size_t pages,
bool same_va,
int extra_flags,
int commit_count,
int extent);
void
panfrost_drm_free_slab(struct panfrost_screen *screen,
struct panfrost_memory *mem);
struct panfrost_bo *
panfrost_drm_create_bo(struct panfrost_screen *screen, size_t size,
uint32_t flags);
void
panfrost_drm_release_bo(struct panfrost_screen *screen, struct panfrost_bo *bo);
struct panfrost_bo *
panfrost_drm_import_bo(struct panfrost_screen *screen, int fd);
int
panfrost_drm_export_bo(struct panfrost_screen *screen, const struct panfrost_bo *bo);
int
panfrost_drm_submit_vs_fs_job(struct panfrost_context *ctx, bool has_draws,
bool is_scanout);
void
panfrost_drm_force_flush_fragment(struct panfrost_context *ctx,
struct pipe_fence_handle **fence);
unsigned
panfrost_drm_query_gpu_version(struct panfrost_screen *screen);
int
panfrost_drm_init_context(struct panfrost_context *ctx);
void
panfrost_drm_fence_reference(struct pipe_screen *screen,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *fence);
boolean
panfrost_drm_fence_finish(struct pipe_screen *pscreen,
struct pipe_context *ctx,
struct pipe_fence_handle *fence,
uint64_t timeout);
#endif /* PAN_SCREEN_H */
|