Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/crocus/crocus_blorp.c
4570 views
1
/*
2
* Copyright © 2018 Intel Corporation
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice shall be included
12
* in all copies or substantial portions of the Software.
13
*
14
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
* DEALINGS IN THE SOFTWARE.
21
*/
22
23
/**
24
* @file crocus_blorp.c
25
*
26
* ============================= GENXML CODE =============================
27
* [This file is compiled once per generation.]
28
* =======================================================================
29
*
30
* GenX specific code for working with BLORP (blitting, resolves, clears
31
* on the 3D engine). This provides the driver-specific hooks needed to
32
* implement the BLORP API.
33
*
34
* See crocus_blit.c, crocus_clear.c, and so on.
35
*/
36
37
#include <assert.h>
38
39
#include "crocus_batch.h"
40
#include "crocus_resource.h"
41
#include "crocus_context.h"
42
43
#include "util/u_upload_mgr.h"
44
#include "intel/common/intel_l3_config.h"
45
46
#include "blorp/blorp_genX_exec.h"
47
48
#if GFX_VER <= 5
49
#include "gen4_blorp_exec.h"
50
#endif
51
52
static uint32_t *
53
stream_state(struct crocus_batch *batch,
54
unsigned size,
55
unsigned alignment,
56
uint32_t *out_offset,
57
struct crocus_bo **out_bo)
58
{
59
uint32_t offset = ALIGN(batch->state.used, alignment);
60
61
if (offset + size >= STATE_SZ && !batch->no_wrap) {
62
crocus_batch_flush(batch);
63
offset = ALIGN(batch->state.used, alignment);
64
} else if (offset + size >= batch->state.bo->size) {
65
const unsigned new_size =
66
MIN2(batch->state.bo->size + batch->state.bo->size / 2,
67
MAX_STATE_SIZE);
68
crocus_grow_buffer(batch, true, batch->state.used, new_size);
69
assert(offset + size < batch->state.bo->size);
70
}
71
72
crocus_record_state_size(batch->state_sizes, offset, size);
73
74
batch->state.used = offset + size;
75
*out_offset = offset;
76
77
/* If the caller has asked for a BO, we leave them the responsibility of
78
* adding bo->gtt_offset (say, by handing an address to genxml). If not,
79
* we assume they want the offset from a base address.
80
*/
81
if (out_bo)
82
*out_bo = batch->state.bo;
83
84
return (uint32_t *)batch->state.map + (offset >> 2);
85
}
86
87
static void *
88
blorp_emit_dwords(struct blorp_batch *blorp_batch, unsigned n)
89
{
90
struct crocus_batch *batch = blorp_batch->driver_batch;
91
return crocus_get_command_space(batch, n * sizeof(uint32_t));
92
}
93
94
static uint64_t
95
blorp_emit_reloc(struct blorp_batch *blorp_batch, UNUSED void *location,
96
struct blorp_address addr, uint32_t delta)
97
{
98
struct crocus_batch *batch = blorp_batch->driver_batch;
99
uint32_t offset;
100
101
if (GFX_VER < 6 && crocus_ptr_in_state_buffer(batch, location)) {
102
offset = (char *)location - (char *)batch->state.map;
103
return crocus_state_reloc(batch, offset,
104
addr.buffer, addr.offset + delta,
105
addr.reloc_flags);
106
}
107
108
assert(!crocus_ptr_in_state_buffer(batch, location));
109
110
offset = (char *)location - (char *)batch->command.map;
111
return crocus_command_reloc(batch, offset,
112
addr.buffer, addr.offset + delta,
113
addr.reloc_flags);
114
}
115
116
static void
117
blorp_surface_reloc(struct blorp_batch *blorp_batch, uint32_t ss_offset,
118
struct blorp_address addr, uint32_t delta)
119
{
120
struct crocus_batch *batch = blorp_batch->driver_batch;
121
struct crocus_bo *bo = addr.buffer;
122
123
uint64_t reloc_val =
124
crocus_state_reloc(batch, ss_offset, bo, addr.offset + delta,
125
addr.reloc_flags);
126
127
void *reloc_ptr = (void *)batch->state.map + ss_offset;
128
*(uint32_t *)reloc_ptr = reloc_val;
129
}
130
131
static uint64_t
132
blorp_get_surface_address(struct blorp_batch *blorp_batch,
133
struct blorp_address addr)
134
{
135
/* We'll let blorp_surface_reloc write the address. */
136
return 0ull;
137
}
138
139
#if GFX_VER >= 7
140
static struct blorp_address
141
blorp_get_surface_base_address(struct blorp_batch *blorp_batch)
142
{
143
struct crocus_batch *batch = blorp_batch->driver_batch;
144
return (struct blorp_address) {
145
.buffer = batch->state.bo,
146
.offset = 0
147
};
148
}
149
#endif
150
151
static void *
152
blorp_alloc_dynamic_state(struct blorp_batch *blorp_batch,
153
uint32_t size,
154
uint32_t alignment,
155
uint32_t *offset)
156
{
157
struct crocus_batch *batch = blorp_batch->driver_batch;
158
159
return stream_state(batch, size, alignment, offset, NULL);
160
}
161
162
static void
163
blorp_alloc_binding_table(struct blorp_batch *blorp_batch,
164
unsigned num_entries,
165
unsigned state_size,
166
unsigned state_alignment,
167
uint32_t *bt_offset,
168
uint32_t *surface_offsets,
169
void **surface_maps)
170
{
171
struct crocus_batch *batch = blorp_batch->driver_batch;
172
uint32_t *bt_map = stream_state(batch, num_entries * sizeof(uint32_t), 32,
173
bt_offset, NULL);
174
175
for (unsigned i = 0; i < num_entries; i++) {
176
surface_maps[i] = stream_state(batch,
177
state_size, state_alignment,
178
&(surface_offsets)[i], NULL);
179
bt_map[i] = surface_offsets[i];
180
}
181
}
182
183
static void *
184
blorp_alloc_vertex_buffer(struct blorp_batch *blorp_batch,
185
uint32_t size,
186
struct blorp_address *addr)
187
{
188
struct crocus_batch *batch = blorp_batch->driver_batch;
189
struct crocus_bo *bo;
190
uint32_t offset;
191
192
void *map = stream_state(batch, size, 64,
193
&offset, &bo);
194
195
*addr = (struct blorp_address) {
196
.buffer = bo,
197
.offset = offset,
198
.reloc_flags = RELOC_32BIT,
199
#if GFX_VER >= 7
200
.mocs = crocus_mocs(bo, &batch->screen->isl_dev),
201
#endif
202
};
203
204
return map;
205
}
206
207
/**
208
*/
209
static void
210
blorp_vf_invalidate_for_vb_48b_transitions(struct blorp_batch *blorp_batch,
211
const struct blorp_address *addrs,
212
UNUSED uint32_t *sizes,
213
unsigned num_vbs)
214
{
215
}
216
217
static struct blorp_address
218
blorp_get_workaround_address(struct blorp_batch *blorp_batch)
219
{
220
struct crocus_batch *batch = blorp_batch->driver_batch;
221
222
return (struct blorp_address) {
223
.buffer = batch->ice->workaround_bo,
224
.offset = batch->ice->workaround_offset,
225
};
226
}
227
228
static void
229
blorp_flush_range(UNUSED struct blorp_batch *blorp_batch,
230
UNUSED void *start,
231
UNUSED size_t size)
232
{
233
/* All allocated states come from the batch which we will flush before we
234
* submit it. There's nothing for us to do here.
235
*/
236
}
237
238
#if GFX_VER >= 7
239
static const struct intel_l3_config *
240
blorp_get_l3_config(struct blorp_batch *blorp_batch)
241
{
242
struct crocus_batch *batch = blorp_batch->driver_batch;
243
return batch->screen->l3_config_3d;
244
}
245
#else /* GFX_VER < 7 */
246
static void
247
blorp_emit_urb_config(struct blorp_batch *blorp_batch,
248
unsigned vs_entry_size,
249
UNUSED unsigned sf_entry_size)
250
{
251
struct crocus_batch *batch = blorp_batch->driver_batch;
252
#if GFX_VER <= 5
253
batch->screen->vtbl.calculate_urb_fence(batch, 0, vs_entry_size, sf_entry_size);
254
#else
255
genX(crocus_upload_urb)(batch, vs_entry_size, false, vs_entry_size);
256
#endif
257
}
258
#endif
259
260
static void
261
crocus_blorp_exec(struct blorp_batch *blorp_batch,
262
const struct blorp_params *params)
263
{
264
struct crocus_context *ice = blorp_batch->blorp->driver_ctx;
265
struct crocus_batch *batch = blorp_batch->driver_batch;
266
267
/* Flush the sampler and render caches. We definitely need to flush the
268
* sampler cache so that we get updated contents from the render cache for
269
* the glBlitFramebuffer() source. Also, we are sometimes warned in the
270
* docs to flush the cache between reinterpretations of the same surface
271
* data with different formats, which blorp does for stencil and depth
272
* data.
273
*/
274
if (params->src.enabled)
275
crocus_cache_flush_for_read(batch, params->src.addr.buffer);
276
if (params->dst.enabled) {
277
crocus_cache_flush_for_render(batch, params->dst.addr.buffer,
278
params->dst.view.format,
279
params->dst.aux_usage);
280
}
281
if (params->depth.enabled)
282
crocus_cache_flush_for_depth(batch, params->depth.addr.buffer);
283
if (params->stencil.enabled)
284
crocus_cache_flush_for_depth(batch, params->stencil.addr.buffer);
285
286
crocus_require_command_space(batch, 1400);
287
crocus_require_statebuffer_space(batch, 600);
288
batch->no_wrap = true;
289
290
#if GFX_VER == 8
291
genX(crocus_update_pma_fix)(ice, batch, false);
292
#endif
293
294
#if GFX_VER == 6
295
/* Emit workaround flushes when we switch from drawing to blorping. */
296
crocus_emit_post_sync_nonzero_flush(batch);
297
#endif
298
299
#if GFX_VER >= 6
300
crocus_emit_depth_stall_flushes(batch);
301
#endif
302
303
blorp_emit(blorp_batch, GENX(3DSTATE_DRAWING_RECTANGLE), rect) {
304
rect.ClippedDrawingRectangleXMax = MAX2(params->x1, params->x0) - 1;
305
rect.ClippedDrawingRectangleYMax = MAX2(params->y1, params->y0) - 1;
306
}
307
308
batch->screen->vtbl.update_surface_base_address(batch);
309
crocus_handle_always_flush_cache(batch);
310
311
batch->contains_draw = true;
312
blorp_exec(blorp_batch, params);
313
314
batch->no_wrap = false;
315
crocus_handle_always_flush_cache(batch);
316
317
/* We've smashed all state compared to what the normal 3D pipeline
318
* rendering tracks for GL.
319
*/
320
321
uint64_t skip_bits = (CROCUS_DIRTY_POLYGON_STIPPLE |
322
CROCUS_DIRTY_GEN7_SO_BUFFERS |
323
CROCUS_DIRTY_SO_DECL_LIST |
324
CROCUS_DIRTY_LINE_STIPPLE |
325
CROCUS_ALL_DIRTY_FOR_COMPUTE |
326
CROCUS_DIRTY_GEN6_SCISSOR_RECT |
327
CROCUS_DIRTY_GEN75_VF |
328
CROCUS_DIRTY_SF_CL_VIEWPORT);
329
330
uint64_t skip_stage_bits = (CROCUS_ALL_STAGE_DIRTY_FOR_COMPUTE |
331
CROCUS_STAGE_DIRTY_UNCOMPILED_VS |
332
CROCUS_STAGE_DIRTY_UNCOMPILED_TCS |
333
CROCUS_STAGE_DIRTY_UNCOMPILED_TES |
334
CROCUS_STAGE_DIRTY_UNCOMPILED_GS |
335
CROCUS_STAGE_DIRTY_UNCOMPILED_FS |
336
CROCUS_STAGE_DIRTY_SAMPLER_STATES_VS |
337
CROCUS_STAGE_DIRTY_SAMPLER_STATES_TCS |
338
CROCUS_STAGE_DIRTY_SAMPLER_STATES_TES |
339
CROCUS_STAGE_DIRTY_SAMPLER_STATES_GS);
340
341
if (!ice->shaders.uncompiled[MESA_SHADER_TESS_EVAL]) {
342
/* BLORP disabled tessellation, that's fine for the next draw */
343
skip_stage_bits |= CROCUS_STAGE_DIRTY_TCS |
344
CROCUS_STAGE_DIRTY_TES |
345
CROCUS_STAGE_DIRTY_CONSTANTS_TCS |
346
CROCUS_STAGE_DIRTY_CONSTANTS_TES |
347
CROCUS_STAGE_DIRTY_BINDINGS_TCS |
348
CROCUS_STAGE_DIRTY_BINDINGS_TES;
349
}
350
351
if (!ice->shaders.uncompiled[MESA_SHADER_GEOMETRY]) {
352
/* BLORP disabled geometry shaders, that's fine for the next draw */
353
skip_stage_bits |= CROCUS_STAGE_DIRTY_GS |
354
CROCUS_STAGE_DIRTY_CONSTANTS_GS |
355
CROCUS_STAGE_DIRTY_BINDINGS_GS;
356
}
357
358
/* we can skip flagging CROCUS_DIRTY_DEPTH_BUFFER, if
359
* BLORP_BATCH_NO_EMIT_DEPTH_STENCIL is set.
360
*/
361
if (blorp_batch->flags & BLORP_BATCH_NO_EMIT_DEPTH_STENCIL)
362
skip_bits |= CROCUS_DIRTY_DEPTH_BUFFER;
363
364
if (!params->wm_prog_data)
365
skip_bits |= CROCUS_DIRTY_GEN6_BLEND_STATE;
366
367
ice->state.dirty |= ~skip_bits;
368
ice->state.stage_dirty |= ~skip_stage_bits;
369
370
ice->urb.vsize = 0;
371
ice->urb.gs_present = false;
372
ice->urb.gsize = 0;
373
ice->urb.tess_present = false;
374
ice->urb.hsize = 0;
375
ice->urb.dsize = 0;
376
377
if (params->dst.enabled) {
378
crocus_render_cache_add_bo(batch, params->dst.addr.buffer,
379
params->dst.view.format,
380
params->dst.aux_usage);
381
}
382
if (params->depth.enabled)
383
crocus_depth_cache_add_bo(batch, params->depth.addr.buffer);
384
if (params->stencil.enabled)
385
crocus_depth_cache_add_bo(batch, params->stencil.addr.buffer);
386
}
387
388
static void
389
blorp_measure_start(struct blorp_batch *blorp_batch,
390
const struct blorp_params *params)
391
{
392
}
393
394
void
395
genX(crocus_init_blorp)(struct crocus_context *ice)
396
{
397
struct crocus_screen *screen = (struct crocus_screen *)ice->ctx.screen;
398
399
blorp_init(&ice->blorp, ice, &screen->isl_dev);
400
ice->blorp.compiler = screen->compiler;
401
ice->blorp.lookup_shader = crocus_blorp_lookup_shader;
402
ice->blorp.upload_shader = crocus_blorp_upload_shader;
403
ice->blorp.exec = crocus_blorp_exec;
404
}
405
406