Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/virtio/vulkan/vn_cs.c
4560 views
1
/*
2
* Copyright 2019 Google LLC
3
* SPDX-License-Identifier: MIT
4
*/
5
6
#include "vn_cs.h"
7
8
#include "vn_device.h"
9
#include "vn_renderer.h"
10
11
static void
12
vn_cs_encoder_sanity_check(struct vn_cs_encoder *enc)
13
{
14
assert(enc->buffer_count <= enc->buffer_max);
15
16
size_t total_committed_size = 0;
17
for (uint32_t i = 0; i < enc->buffer_count; i++)
18
total_committed_size += enc->buffers[i].committed_size;
19
assert(enc->total_committed_size == total_committed_size);
20
21
if (enc->buffer_count) {
22
const struct vn_cs_encoder_buffer *cur_buf =
23
&enc->buffers[enc->buffer_count - 1];
24
assert(cur_buf->base <= enc->cur && enc->cur <= enc->end &&
25
enc->end <= cur_buf->base + enc->current_buffer_size);
26
if (cur_buf->committed_size)
27
assert(enc->cur == enc->end);
28
} else {
29
assert(!enc->current_buffer_size);
30
assert(!enc->cur && !enc->end);
31
}
32
}
33
34
static void
35
vn_cs_encoder_add_buffer(struct vn_cs_encoder *enc,
36
struct vn_renderer_shmem *shmem,
37
size_t offset,
38
void *base,
39
size_t size)
40
{
41
/* add a buffer and make it current */
42
assert(enc->buffer_count < enc->buffer_max);
43
struct vn_cs_encoder_buffer *cur_buf = &enc->buffers[enc->buffer_count++];
44
/* shmem ownership transferred */
45
cur_buf->shmem = shmem;
46
cur_buf->offset = offset;
47
cur_buf->base = base;
48
cur_buf->committed_size = 0;
49
50
/* update the write pointer */
51
enc->cur = base;
52
enc->end = base + size;
53
}
54
55
static void
56
vn_cs_encoder_commit_buffer(struct vn_cs_encoder *enc)
57
{
58
assert(enc->buffer_count);
59
struct vn_cs_encoder_buffer *cur_buf =
60
&enc->buffers[enc->buffer_count - 1];
61
const size_t written_size = enc->cur - cur_buf->base;
62
if (cur_buf->committed_size) {
63
assert(cur_buf->committed_size == written_size);
64
} else {
65
cur_buf->committed_size = written_size;
66
enc->total_committed_size += written_size;
67
}
68
}
69
70
static void
71
vn_cs_encoder_gc_buffers(struct vn_cs_encoder *enc)
72
{
73
/* free all but the current buffer */
74
assert(enc->buffer_count);
75
struct vn_cs_encoder_buffer *cur_buf =
76
&enc->buffers[enc->buffer_count - 1];
77
for (uint32_t i = 0; i < enc->buffer_count - 1; i++)
78
vn_renderer_shmem_unref(enc->instance->renderer, enc->buffers[i].shmem);
79
80
/* move the current buffer to the beginning, skipping the used part */
81
const size_t used = cur_buf->offset + cur_buf->committed_size;
82
enc->buffer_count = 0;
83
vn_cs_encoder_add_buffer(enc, cur_buf->shmem, used,
84
cur_buf->base + cur_buf->committed_size,
85
enc->current_buffer_size - used);
86
87
enc->total_committed_size = 0;
88
}
89
90
void
91
vn_cs_encoder_init_indirect(struct vn_cs_encoder *enc,
92
struct vn_instance *instance,
93
size_t min_size)
94
{
95
memset(enc, 0, sizeof(*enc));
96
enc->instance = instance;
97
enc->min_buffer_size = min_size;
98
enc->indirect = true;
99
}
100
101
void
102
vn_cs_encoder_fini(struct vn_cs_encoder *enc)
103
{
104
if (unlikely(!enc->indirect))
105
return;
106
107
for (uint32_t i = 0; i < enc->buffer_count; i++)
108
vn_renderer_shmem_unref(enc->instance->renderer, enc->buffers[i].shmem);
109
if (enc->buffers)
110
free(enc->buffers);
111
}
112
113
/**
114
* Reset a cs for reuse.
115
*/
116
void
117
vn_cs_encoder_reset(struct vn_cs_encoder *enc)
118
{
119
/* enc->error is sticky */
120
if (likely(enc->buffer_count))
121
vn_cs_encoder_gc_buffers(enc);
122
}
123
124
static uint32_t
125
next_array_size(uint32_t cur_size, uint32_t min_size)
126
{
127
const uint32_t next_size = cur_size ? cur_size * 2 : min_size;
128
return next_size > cur_size ? next_size : 0;
129
}
130
131
static size_t
132
next_buffer_size(size_t cur_size, size_t min_size, size_t need)
133
{
134
size_t next_size = cur_size ? cur_size * 2 : min_size;
135
while (next_size < need) {
136
next_size *= 2;
137
if (!next_size)
138
return 0;
139
}
140
return next_size;
141
}
142
143
static bool
144
vn_cs_encoder_grow_buffer_array(struct vn_cs_encoder *enc)
145
{
146
const uint32_t buf_max = next_array_size(enc->buffer_max, 4);
147
if (!buf_max)
148
return false;
149
150
void *bufs = realloc(enc->buffers, sizeof(*enc->buffers) * buf_max);
151
if (!bufs)
152
return false;
153
154
enc->buffers = bufs;
155
enc->buffer_max = buf_max;
156
157
return true;
158
}
159
160
/**
161
* Add a new vn_cs_encoder_buffer to a cs.
162
*/
163
bool
164
vn_cs_encoder_reserve_internal(struct vn_cs_encoder *enc, size_t size)
165
{
166
if (unlikely(!enc->indirect))
167
return false;
168
169
if (enc->buffer_count >= enc->buffer_max) {
170
if (!vn_cs_encoder_grow_buffer_array(enc))
171
return false;
172
assert(enc->buffer_count < enc->buffer_max);
173
}
174
175
size_t buf_size = 0;
176
if (likely(enc->buffer_count)) {
177
vn_cs_encoder_commit_buffer(enc);
178
179
/* TODO better strategy to grow buffer size */
180
const struct vn_cs_encoder_buffer *cur_buf =
181
&enc->buffers[enc->buffer_count - 1];
182
if (cur_buf->offset)
183
buf_size = next_buffer_size(0, enc->current_buffer_size, size);
184
}
185
186
if (!buf_size) {
187
buf_size = next_buffer_size(enc->current_buffer_size,
188
enc->min_buffer_size, size);
189
if (!buf_size)
190
return false;
191
}
192
193
struct vn_renderer_shmem *shmem =
194
vn_renderer_shmem_create(enc->instance->renderer, buf_size);
195
if (!shmem)
196
return false;
197
198
uint32_t roundtrip;
199
VkResult result = vn_instance_submit_roundtrip(enc->instance, &roundtrip);
200
if (result != VK_SUCCESS) {
201
vn_renderer_shmem_unref(enc->instance->renderer, shmem);
202
return false;
203
}
204
205
vn_cs_encoder_add_buffer(enc, shmem, 0, shmem->mmap_ptr, buf_size);
206
enc->current_buffer_size = buf_size;
207
enc->current_buffer_roundtrip = roundtrip;
208
209
vn_cs_encoder_sanity_check(enc);
210
211
return true;
212
}
213
214
/*
215
* Commit written data.
216
*/
217
void
218
vn_cs_encoder_commit(struct vn_cs_encoder *enc)
219
{
220
if (likely(enc->buffer_count)) {
221
vn_cs_encoder_commit_buffer(enc);
222
223
/* trigger the slow path on next vn_cs_encoder_reserve */
224
enc->end = enc->cur;
225
}
226
227
vn_cs_encoder_sanity_check(enc);
228
}
229
230