Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_context.c
4570 views
1
/*
2
* Copyright 2018 Collabora Ltd.
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
* on the rights to use, copy, modify, merge, publish, distribute, sub
8
* license, and/or sell copies of the Software, and to permit persons to whom
9
* the Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21
* USE OR OTHER DEALINGS IN THE SOFTWARE.
22
*/
23
24
#include "zink_context.h"
25
26
#include "zink_batch.h"
27
#include "zink_compiler.h"
28
#include "zink_fence.h"
29
#include "zink_framebuffer.h"
30
#include "zink_helpers.h"
31
#include "zink_program.h"
32
#include "zink_pipeline.h"
33
#include "zink_query.h"
34
#include "zink_render_pass.h"
35
#include "zink_resource.h"
36
#include "zink_screen.h"
37
#include "zink_state.h"
38
#include "zink_surface.h"
39
40
#include "util/u_blitter.h"
41
#include "util/u_debug.h"
42
#include "util/format_srgb.h"
43
#include "util/format/u_format.h"
44
#include "util/u_framebuffer.h"
45
#include "util/u_helpers.h"
46
#include "util/u_inlines.h"
47
#include "util/u_thread.h"
48
#include "util/u_cpu_detect.h"
49
#include "util/strndup.h"
50
#include "nir.h"
51
52
#include "util/u_memory.h"
53
#include "util/u_upload_mgr.h"
54
55
#define XXH_INLINE_ALL
56
#include "util/xxhash.h"
57
58
static void
59
calc_descriptor_hash_sampler_state(struct zink_sampler_state *sampler_state)
60
{
61
void *hash_data = &sampler_state->sampler;
62
size_t data_size = sizeof(VkSampler);
63
sampler_state->hash = XXH32(hash_data, data_size, 0);
64
}
65
66
void
67
debug_describe_zink_buffer_view(char *buf, const struct zink_buffer_view *ptr)
68
{
69
sprintf(buf, "zink_buffer_view");
70
}
71
72
ALWAYS_INLINE static void
73
check_resource_for_batch_ref(struct zink_context *ctx, struct zink_resource *res)
74
{
75
if (!res->bind_count[0] && !res->bind_count[1])
76
zink_batch_reference_resource(&ctx->batch, res);
77
}
78
79
static void
80
zink_context_destroy(struct pipe_context *pctx)
81
{
82
struct zink_context *ctx = zink_context(pctx);
83
struct zink_screen *screen = zink_screen(pctx->screen);
84
85
if (screen->queue && !screen->device_lost && vkQueueWaitIdle(screen->queue) != VK_SUCCESS)
86
debug_printf("vkQueueWaitIdle failed\n");
87
88
util_blitter_destroy(ctx->blitter);
89
for (unsigned i = 0; i < ctx->fb_state.nr_cbufs; i++)
90
zink_surface_reference(screen, (struct zink_surface**)&ctx->fb_state.cbufs[i], NULL);
91
zink_surface_reference(screen, (struct zink_surface**)&ctx->fb_state.zsbuf, NULL);
92
93
pipe_resource_reference(&ctx->dummy_vertex_buffer, NULL);
94
pipe_resource_reference(&ctx->dummy_xfb_buffer, NULL);
95
96
zink_surface_reference(screen, (struct zink_surface**)&ctx->dummy_surface, NULL);
97
zink_buffer_view_reference(screen, &ctx->dummy_bufferview, NULL);
98
99
simple_mtx_destroy(&ctx->batch_mtx);
100
zink_clear_batch_state(ctx, ctx->batch.state);
101
zink_batch_state_reference(screen, &ctx->batch.state, NULL);
102
hash_table_foreach(&ctx->batch_states, entry) {
103
struct zink_batch_state *bs = entry->data;
104
zink_clear_batch_state(ctx, bs);
105
zink_batch_state_reference(screen, &bs, NULL);
106
}
107
util_dynarray_foreach(&ctx->free_batch_states, struct zink_batch_state*, bs) {
108
zink_clear_batch_state(ctx, *bs);
109
zink_batch_state_reference(screen, bs, NULL);
110
}
111
112
if (ctx->framebuffer) {
113
simple_mtx_lock(&screen->framebuffer_mtx);
114
struct hash_entry *entry = _mesa_hash_table_search(&screen->framebuffer_cache, &ctx->framebuffer->state);
115
if (zink_framebuffer_reference(screen, &ctx->framebuffer, NULL))
116
_mesa_hash_table_remove(&screen->framebuffer_cache, entry);
117
simple_mtx_unlock(&screen->framebuffer_mtx);
118
}
119
120
hash_table_foreach(ctx->render_pass_cache, he)
121
zink_destroy_render_pass(screen, he->data);
122
123
u_upload_destroy(pctx->stream_uploader);
124
u_upload_destroy(pctx->const_uploader);
125
slab_destroy_child(&ctx->transfer_pool);
126
_mesa_hash_table_destroy(ctx->program_cache, NULL);
127
_mesa_hash_table_destroy(ctx->compute_program_cache, NULL);
128
_mesa_hash_table_destroy(ctx->render_pass_cache, NULL);
129
slab_destroy_child(&ctx->transfer_pool_unsync);
130
131
screen->descriptors_deinit(ctx);
132
133
zink_descriptor_layouts_deinit(ctx);
134
135
p_atomic_dec(&screen->base.num_contexts);
136
137
ralloc_free(ctx);
138
}
139
140
static void
141
check_device_lost(struct zink_context *ctx)
142
{
143
if (!zink_screen(ctx->base.screen)->device_lost || ctx->is_device_lost)
144
return;
145
debug_printf("ZINK: device lost detected!\n");
146
if (ctx->reset.reset)
147
ctx->reset.reset(ctx->reset.data, PIPE_GUILTY_CONTEXT_RESET);
148
ctx->is_device_lost = true;
149
}
150
151
static enum pipe_reset_status
152
zink_get_device_reset_status(struct pipe_context *pctx)
153
{
154
struct zink_context *ctx = zink_context(pctx);
155
156
enum pipe_reset_status status = PIPE_NO_RESET;
157
158
if (ctx->is_device_lost) {
159
// Since we don't know what really happened to the hardware, just
160
// assume that we are in the wrong
161
status = PIPE_GUILTY_CONTEXT_RESET;
162
163
debug_printf("ZINK: device lost detected!\n");
164
165
if (ctx->reset.reset)
166
ctx->reset.reset(ctx->reset.data, status);
167
}
168
169
return status;
170
}
171
172
static void
173
zink_set_device_reset_callback(struct pipe_context *pctx,
174
const struct pipe_device_reset_callback *cb)
175
{
176
struct zink_context *ctx = zink_context(pctx);
177
178
if (cb)
179
ctx->reset = *cb;
180
else
181
memset(&ctx->reset, 0, sizeof(ctx->reset));
182
}
183
184
static void
185
zink_set_context_param(struct pipe_context *pctx, enum pipe_context_param param,
186
unsigned value)
187
{
188
struct zink_context *ctx = zink_context(pctx);
189
190
switch (param) {
191
case PIPE_CONTEXT_PARAM_PIN_THREADS_TO_L3_CACHE:
192
util_set_thread_affinity(zink_screen(ctx->base.screen)->flush_queue.threads[0],
193
util_get_cpu_caps()->L3_affinity_mask[value],
194
NULL, util_get_cpu_caps()->num_cpu_mask_bits);
195
break;
196
default:
197
break;
198
}
199
}
200
201
static VkSamplerMipmapMode
202
sampler_mipmap_mode(enum pipe_tex_mipfilter filter)
203
{
204
switch (filter) {
205
case PIPE_TEX_MIPFILTER_NEAREST: return VK_SAMPLER_MIPMAP_MODE_NEAREST;
206
case PIPE_TEX_MIPFILTER_LINEAR: return VK_SAMPLER_MIPMAP_MODE_LINEAR;
207
case PIPE_TEX_MIPFILTER_NONE:
208
unreachable("PIPE_TEX_MIPFILTER_NONE should be dealt with earlier");
209
}
210
unreachable("unexpected filter");
211
}
212
213
static VkSamplerAddressMode
214
sampler_address_mode(enum pipe_tex_wrap filter)
215
{
216
switch (filter) {
217
case PIPE_TEX_WRAP_REPEAT: return VK_SAMPLER_ADDRESS_MODE_REPEAT;
218
case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
219
case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
220
case PIPE_TEX_WRAP_MIRROR_REPEAT: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
221
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
222
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; /* not technically correct, but kinda works */
223
default: break;
224
}
225
unreachable("unexpected wrap");
226
}
227
228
static VkCompareOp
229
compare_op(enum pipe_compare_func op)
230
{
231
switch (op) {
232
case PIPE_FUNC_NEVER: return VK_COMPARE_OP_NEVER;
233
case PIPE_FUNC_LESS: return VK_COMPARE_OP_LESS;
234
case PIPE_FUNC_EQUAL: return VK_COMPARE_OP_EQUAL;
235
case PIPE_FUNC_LEQUAL: return VK_COMPARE_OP_LESS_OR_EQUAL;
236
case PIPE_FUNC_GREATER: return VK_COMPARE_OP_GREATER;
237
case PIPE_FUNC_NOTEQUAL: return VK_COMPARE_OP_NOT_EQUAL;
238
case PIPE_FUNC_GEQUAL: return VK_COMPARE_OP_GREATER_OR_EQUAL;
239
case PIPE_FUNC_ALWAYS: return VK_COMPARE_OP_ALWAYS;
240
}
241
unreachable("unexpected compare");
242
}
243
244
static inline bool
245
wrap_needs_border_color(unsigned wrap)
246
{
247
return wrap == PIPE_TEX_WRAP_CLAMP || wrap == PIPE_TEX_WRAP_CLAMP_TO_BORDER ||
248
wrap == PIPE_TEX_WRAP_MIRROR_CLAMP || wrap == PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER;
249
}
250
251
static VkBorderColor
252
get_border_color(const union pipe_color_union *color, bool is_integer, bool need_custom)
253
{
254
if (is_integer) {
255
if (color->ui[0] == 0 && color->ui[1] == 0 && color->ui[2] == 0 && color->ui[3] == 0)
256
return VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
257
if (color->ui[0] == 0 && color->ui[1] == 0 && color->ui[2] == 0 && color->ui[3] == 1)
258
return VK_BORDER_COLOR_INT_OPAQUE_BLACK;
259
if (color->ui[0] == 1 && color->ui[1] == 1 && color->ui[2] == 1 && color->ui[3] == 1)
260
return VK_BORDER_COLOR_INT_OPAQUE_WHITE;
261
return need_custom ? VK_BORDER_COLOR_INT_CUSTOM_EXT : VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
262
}
263
264
if (color->f[0] == 0 && color->f[1] == 0 && color->f[2] == 0 && color->f[3] == 0)
265
return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
266
if (color->f[0] == 0 && color->f[1] == 0 && color->f[2] == 0 && color->f[3] == 1)
267
return VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
268
if (color->f[0] == 1 && color->f[1] == 1 && color->f[2] == 1 && color->f[3] == 1)
269
return VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
270
return need_custom ? VK_BORDER_COLOR_FLOAT_CUSTOM_EXT : VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
271
}
272
273
static void *
274
zink_create_sampler_state(struct pipe_context *pctx,
275
const struct pipe_sampler_state *state)
276
{
277
struct zink_screen *screen = zink_screen(pctx->screen);
278
bool need_custom = false;
279
280
VkSamplerCreateInfo sci = {0};
281
VkSamplerCustomBorderColorCreateInfoEXT cbci = {0};
282
sci.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
283
sci.magFilter = zink_filter(state->mag_img_filter);
284
sci.minFilter = zink_filter(state->min_img_filter);
285
286
VkSamplerReductionModeCreateInfo rci;
287
rci.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO;
288
rci.pNext = NULL;
289
switch (state->reduction_mode) {
290
case PIPE_TEX_REDUCTION_MIN:
291
rci.reductionMode = VK_SAMPLER_REDUCTION_MODE_MIN;
292
break;
293
case PIPE_TEX_REDUCTION_MAX:
294
rci.reductionMode = VK_SAMPLER_REDUCTION_MODE_MAX;
295
break;
296
default:
297
rci.reductionMode = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE;
298
break;
299
}
300
if (state->reduction_mode)
301
sci.pNext = &rci;
302
303
if (state->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) {
304
sci.mipmapMode = sampler_mipmap_mode(state->min_mip_filter);
305
sci.minLod = state->min_lod;
306
sci.maxLod = state->max_lod;
307
} else {
308
sci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
309
sci.minLod = 0;
310
sci.maxLod = 0.25f;
311
}
312
313
sci.addressModeU = sampler_address_mode(state->wrap_s);
314
sci.addressModeV = sampler_address_mode(state->wrap_t);
315
sci.addressModeW = sampler_address_mode(state->wrap_r);
316
sci.mipLodBias = state->lod_bias;
317
318
need_custom |= wrap_needs_border_color(state->wrap_s);
319
need_custom |= wrap_needs_border_color(state->wrap_t);
320
need_custom |= wrap_needs_border_color(state->wrap_r);
321
322
if (state->compare_mode == PIPE_TEX_COMPARE_NONE)
323
sci.compareOp = VK_COMPARE_OP_NEVER;
324
else {
325
sci.compareOp = compare_op(state->compare_func);
326
sci.compareEnable = VK_TRUE;
327
}
328
329
bool is_integer = state->border_color_is_integer;
330
331
sci.borderColor = get_border_color(&state->border_color, is_integer, need_custom);
332
if (sci.borderColor > VK_BORDER_COLOR_INT_OPAQUE_WHITE && need_custom) {
333
if (screen->info.have_EXT_custom_border_color &&
334
screen->info.border_color_feats.customBorderColorWithoutFormat) {
335
cbci.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT;
336
cbci.format = VK_FORMAT_UNDEFINED;
337
/* these are identical unions */
338
memcpy(&cbci.customBorderColor, &state->border_color, sizeof(union pipe_color_union));
339
cbci.pNext = sci.pNext;
340
sci.pNext = &cbci;
341
UNUSED uint32_t check = p_atomic_inc_return(&screen->cur_custom_border_color_samplers);
342
assert(check <= screen->info.border_color_props.maxCustomBorderColorSamplers);
343
} else
344
sci.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; // TODO with custom shader if we're super interested?
345
}
346
347
sci.unnormalizedCoordinates = !state->normalized_coords;
348
349
if (state->max_anisotropy > 1) {
350
sci.maxAnisotropy = state->max_anisotropy;
351
sci.anisotropyEnable = VK_TRUE;
352
}
353
354
struct zink_sampler_state *sampler = CALLOC_STRUCT(zink_sampler_state);
355
if (!sampler)
356
return NULL;
357
358
if (vkCreateSampler(screen->dev, &sci, NULL, &sampler->sampler) != VK_SUCCESS) {
359
FREE(sampler);
360
return NULL;
361
}
362
util_dynarray_init(&sampler->desc_set_refs.refs, NULL);
363
calc_descriptor_hash_sampler_state(sampler);
364
sampler->custom_border_color = need_custom;
365
366
return sampler;
367
}
368
369
ALWAYS_INLINE static VkImageLayout
370
get_layout_for_binding(struct zink_resource *res, enum zink_descriptor_type type, bool is_compute)
371
{
372
if (res->obj->is_buffer)
373
return 0;
374
switch (type) {
375
case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
376
return res->image_bind_count[is_compute] ?
377
VK_IMAGE_LAYOUT_GENERAL :
378
res->aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) ?
379
//Vulkan-Docs#1490
380
//(res->aspect == VK_IMAGE_ASPECT_DEPTH_BIT ? VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL :
381
//res->aspect == VK_IMAGE_ASPECT_STENCIL_BIT ? VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL :
382
(res->aspect == VK_IMAGE_ASPECT_DEPTH_BIT ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
383
res->aspect == VK_IMAGE_ASPECT_STENCIL_BIT ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL :
384
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL) :
385
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
386
case ZINK_DESCRIPTOR_TYPE_IMAGE:
387
return VK_IMAGE_LAYOUT_GENERAL;
388
default:
389
break;
390
}
391
return 0;
392
}
393
394
ALWAYS_INLINE static struct zink_surface *
395
get_imageview_for_binding(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type, unsigned idx)
396
{
397
switch (type) {
398
case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW: {
399
struct zink_sampler_view *sampler_view = zink_sampler_view(ctx->sampler_views[stage][idx]);
400
return sampler_view->base.texture ? sampler_view->image_view : NULL;
401
}
402
case ZINK_DESCRIPTOR_TYPE_IMAGE: {
403
struct zink_image_view *image_view = &ctx->image_views[stage][idx];
404
return image_view->base.resource ? image_view->surface : NULL;
405
}
406
default:
407
break;
408
}
409
unreachable("ACK");
410
return VK_NULL_HANDLE;
411
}
412
413
ALWAYS_INLINE static struct zink_buffer_view *
414
get_bufferview_for_binding(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type, unsigned idx)
415
{
416
switch (type) {
417
case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW: {
418
struct zink_sampler_view *sampler_view = zink_sampler_view(ctx->sampler_views[stage][idx]);
419
return sampler_view->base.texture ? sampler_view->buffer_view : NULL;
420
}
421
case ZINK_DESCRIPTOR_TYPE_IMAGE: {
422
struct zink_image_view *image_view = &ctx->image_views[stage][idx];
423
return image_view->base.resource ? image_view->buffer_view : NULL;
424
}
425
default:
426
break;
427
}
428
unreachable("ACK");
429
return VK_NULL_HANDLE;
430
}
431
432
ALWAYS_INLINE static void
433
update_descriptor_state_ubo(struct zink_context *ctx, enum pipe_shader_type shader, unsigned slot)
434
{
435
struct zink_screen *screen = zink_screen(ctx->base.screen);
436
bool have_null_descriptors = screen->info.rb2_feats.nullDescriptor;
437
const enum zink_descriptor_type type = ZINK_DESCRIPTOR_TYPE_UBO;
438
struct zink_resource *res = zink_get_resource_for_descriptor(ctx, type, shader, slot);
439
ctx->di.descriptor_res[type][shader][slot] = res;
440
ctx->di.ubos[shader][slot].offset = ctx->ubos[shader][slot].buffer_offset;
441
if (res) {
442
ctx->di.ubos[shader][slot].buffer = res->obj->buffer;
443
ctx->di.ubos[shader][slot].range = ctx->ubos[shader][slot].buffer_size;
444
assert(ctx->di.ubos[shader][slot].range <= screen->info.props.limits.maxUniformBufferRange);
445
} else {
446
VkBuffer null_buffer = zink_resource(ctx->dummy_vertex_buffer)->obj->buffer;
447
ctx->di.ubos[shader][slot].buffer = have_null_descriptors ? VK_NULL_HANDLE : null_buffer;
448
ctx->di.ubos[shader][slot].range = VK_WHOLE_SIZE;
449
}
450
if (!slot) {
451
if (res)
452
ctx->di.push_valid |= BITFIELD64_BIT(shader);
453
else
454
ctx->di.push_valid &= ~BITFIELD64_BIT(shader);
455
}
456
}
457
458
ALWAYS_INLINE static void
459
update_descriptor_state_ssbo(struct zink_context *ctx, enum pipe_shader_type shader, unsigned slot)
460
{
461
struct zink_screen *screen = zink_screen(ctx->base.screen);
462
bool have_null_descriptors = screen->info.rb2_feats.nullDescriptor;
463
const enum zink_descriptor_type type = ZINK_DESCRIPTOR_TYPE_SSBO;
464
struct zink_resource *res = zink_get_resource_for_descriptor(ctx, type, shader, slot);
465
ctx->di.descriptor_res[type][shader][slot] = res;
466
ctx->di.ssbos[shader][slot].offset = ctx->ssbos[shader][slot].buffer_offset;
467
if (res) {
468
ctx->di.ssbos[shader][slot].buffer = res->obj->buffer;
469
ctx->di.ssbos[shader][slot].range = ctx->ssbos[shader][slot].buffer_size;
470
} else {
471
VkBuffer null_buffer = zink_resource(ctx->dummy_vertex_buffer)->obj->buffer;
472
ctx->di.ssbos[shader][slot].buffer = have_null_descriptors ? VK_NULL_HANDLE : null_buffer;
473
ctx->di.ssbos[shader][slot].range = VK_WHOLE_SIZE;
474
}
475
}
476
477
ALWAYS_INLINE static void
478
update_descriptor_state_sampler(struct zink_context *ctx, enum pipe_shader_type shader, unsigned slot)
479
{
480
struct zink_screen *screen = zink_screen(ctx->base.screen);
481
bool have_null_descriptors = screen->info.rb2_feats.nullDescriptor;
482
const enum zink_descriptor_type type = ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW;
483
struct zink_resource *res = zink_get_resource_for_descriptor(ctx, type, shader, slot);
484
ctx->di.descriptor_res[type][shader][slot] = res;
485
if (res) {
486
if (res->obj->is_buffer) {
487
struct zink_buffer_view *bv = get_bufferview_for_binding(ctx, shader, type, slot);
488
ctx->di.tbos[shader][slot] = bv->buffer_view;
489
ctx->di.sampler_surfaces[shader][slot].bufferview = bv;
490
ctx->di.sampler_surfaces[shader][slot].is_buffer = true;
491
} else {
492
struct zink_surface *surface = get_imageview_for_binding(ctx, shader, type, slot);
493
ctx->di.textures[shader][slot].imageLayout = get_layout_for_binding(res, type, shader == PIPE_SHADER_COMPUTE);
494
ctx->di.textures[shader][slot].imageView = surface->image_view;
495
ctx->di.sampler_surfaces[shader][slot].surface = surface;
496
ctx->di.sampler_surfaces[shader][slot].is_buffer = false;
497
}
498
} else {
499
if (likely(have_null_descriptors)) {
500
ctx->di.textures[shader][slot].imageView = VK_NULL_HANDLE;
501
ctx->di.textures[shader][slot].imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
502
ctx->di.tbos[shader][slot] = VK_NULL_HANDLE;
503
} else {
504
struct zink_surface *null_surface = zink_surface(ctx->dummy_surface);
505
struct zink_buffer_view *null_bufferview = ctx->dummy_bufferview;
506
ctx->di.textures[shader][slot].imageView = null_surface->image_view;
507
ctx->di.textures[shader][slot].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
508
ctx->di.tbos[shader][slot] = null_bufferview->buffer_view;
509
}
510
memset(&ctx->di.sampler_surfaces[shader][slot], 0, sizeof(ctx->di.sampler_surfaces[shader][slot]));
511
}
512
}
513
514
ALWAYS_INLINE static void
515
update_descriptor_state_image(struct zink_context *ctx, enum pipe_shader_type shader, unsigned slot)
516
{
517
struct zink_screen *screen = zink_screen(ctx->base.screen);
518
bool have_null_descriptors = screen->info.rb2_feats.nullDescriptor;
519
const enum zink_descriptor_type type = ZINK_DESCRIPTOR_TYPE_IMAGE;
520
struct zink_resource *res = zink_get_resource_for_descriptor(ctx, type, shader, slot);
521
ctx->di.descriptor_res[type][shader][slot] = res;
522
if (res) {
523
if (res->obj->is_buffer) {
524
struct zink_buffer_view *bv = get_bufferview_for_binding(ctx, shader, type, slot);
525
ctx->di.texel_images[shader][slot] = bv->buffer_view;
526
ctx->di.image_surfaces[shader][slot].bufferview = bv;
527
ctx->di.image_surfaces[shader][slot].is_buffer = true;
528
} else {
529
struct zink_surface *surface = get_imageview_for_binding(ctx, shader, type, slot);
530
ctx->di.images[shader][slot].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
531
ctx->di.images[shader][slot].imageView = surface->image_view;
532
ctx->di.image_surfaces[shader][slot].surface = surface;
533
ctx->di.image_surfaces[shader][slot].is_buffer = false;
534
}
535
} else {
536
if (likely(have_null_descriptors)) {
537
memset(&ctx->di.images[shader][slot], 0, sizeof(ctx->di.images[shader][slot]));
538
ctx->di.texel_images[shader][slot] = VK_NULL_HANDLE;
539
} else {
540
struct zink_surface *null_surface = zink_surface(ctx->dummy_surface);
541
struct zink_buffer_view *null_bufferview = ctx->dummy_bufferview;
542
ctx->di.images[shader][slot].imageView = null_surface->image_view;
543
ctx->di.images[shader][slot].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
544
ctx->di.texel_images[shader][slot] = null_bufferview->buffer_view;
545
}
546
memset(&ctx->di.image_surfaces[shader][slot], 0, sizeof(ctx->di.image_surfaces[shader][slot]));
547
}
548
}
549
550
static void
551
zink_bind_sampler_states(struct pipe_context *pctx,
552
enum pipe_shader_type shader,
553
unsigned start_slot,
554
unsigned num_samplers,
555
void **samplers)
556
{
557
struct zink_context *ctx = zink_context(pctx);
558
for (unsigned i = 0; i < num_samplers; ++i) {
559
struct zink_sampler_state *state = samplers[i];
560
if (ctx->sampler_states[shader][start_slot + i] != state)
561
zink_screen(pctx->screen)->context_invalidate_descriptor_state(ctx, shader, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW, start_slot, 1);
562
ctx->sampler_states[shader][start_slot + i] = state;
563
ctx->di.textures[shader][start_slot + i].sampler = state ? state->sampler : VK_NULL_HANDLE;
564
if (state)
565
zink_batch_usage_set(&state->batch_uses, ctx->batch.state);
566
}
567
ctx->di.num_samplers[shader] = start_slot + num_samplers;
568
}
569
570
static void
571
zink_delete_sampler_state(struct pipe_context *pctx,
572
void *sampler_state)
573
{
574
struct zink_sampler_state *sampler = sampler_state;
575
struct zink_batch *batch = &zink_context(pctx)->batch;
576
zink_descriptor_set_refs_clear(&sampler->desc_set_refs, sampler_state);
577
util_dynarray_append(&batch->state->zombie_samplers, VkSampler,
578
sampler->sampler);
579
if (sampler->custom_border_color)
580
p_atomic_dec(&zink_screen(pctx->screen)->cur_custom_border_color_samplers);
581
FREE(sampler);
582
}
583
584
static VkComponentSwizzle
585
component_mapping(enum pipe_swizzle swizzle)
586
{
587
switch (swizzle) {
588
case PIPE_SWIZZLE_X: return VK_COMPONENT_SWIZZLE_R;
589
case PIPE_SWIZZLE_Y: return VK_COMPONENT_SWIZZLE_G;
590
case PIPE_SWIZZLE_Z: return VK_COMPONENT_SWIZZLE_B;
591
case PIPE_SWIZZLE_W: return VK_COMPONENT_SWIZZLE_A;
592
case PIPE_SWIZZLE_0: return VK_COMPONENT_SWIZZLE_ZERO;
593
case PIPE_SWIZZLE_1: return VK_COMPONENT_SWIZZLE_ONE;
594
case PIPE_SWIZZLE_NONE: return VK_COMPONENT_SWIZZLE_IDENTITY; // ???
595
default:
596
unreachable("unexpected swizzle");
597
}
598
}
599
600
static VkImageAspectFlags
601
sampler_aspect_from_format(enum pipe_format fmt)
602
{
603
if (util_format_is_depth_or_stencil(fmt)) {
604
const struct util_format_description *desc = util_format_description(fmt);
605
if (util_format_has_depth(desc))
606
return VK_IMAGE_ASPECT_DEPTH_BIT;
607
assert(util_format_has_stencil(desc));
608
return VK_IMAGE_ASPECT_STENCIL_BIT;
609
} else
610
return VK_IMAGE_ASPECT_COLOR_BIT;
611
}
612
613
static uint32_t
614
hash_bufferview(void *bvci)
615
{
616
size_t offset = offsetof(VkBufferViewCreateInfo, flags);
617
return _mesa_hash_data((char*)bvci + offset, sizeof(VkBufferViewCreateInfo) - offset);
618
}
619
620
static struct zink_buffer_view *
621
get_buffer_view(struct zink_context *ctx, struct zink_resource *res, enum pipe_format format, uint32_t offset, uint32_t range)
622
{
623
struct zink_screen *screen = zink_screen(ctx->base.screen);
624
struct zink_buffer_view *buffer_view = NULL;
625
VkBufferViewCreateInfo bvci = {0};
626
bvci.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
627
bvci.buffer = res->obj->buffer;
628
bvci.format = zink_get_format(screen, format);
629
assert(bvci.format);
630
bvci.offset = offset;
631
bvci.range = range;
632
633
uint32_t hash = hash_bufferview(&bvci);
634
simple_mtx_lock(&screen->bufferview_mtx);
635
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&screen->bufferview_cache, hash, &bvci);
636
if (he) {
637
buffer_view = he->data;
638
p_atomic_inc(&buffer_view->reference.count);
639
} else {
640
VkBufferView view;
641
if (vkCreateBufferView(screen->dev, &bvci, NULL, &view) != VK_SUCCESS)
642
goto out;
643
buffer_view = CALLOC_STRUCT(zink_buffer_view);
644
if (!buffer_view) {
645
vkDestroyBufferView(screen->dev, view, NULL);
646
goto out;
647
}
648
pipe_reference_init(&buffer_view->reference, 1);
649
util_dynarray_init(&buffer_view->desc_set_refs.refs, NULL);
650
buffer_view->bvci = bvci;
651
buffer_view->buffer_view = view;
652
buffer_view->hash = hash;
653
_mesa_hash_table_insert_pre_hashed(&screen->bufferview_cache, hash, &buffer_view->bvci, buffer_view);
654
}
655
out:
656
simple_mtx_unlock(&screen->bufferview_mtx);
657
return buffer_view;
658
}
659
660
static inline enum pipe_swizzle
661
clamp_void_swizzle(const struct util_format_description *desc, enum pipe_swizzle swizzle)
662
{
663
switch (swizzle) {
664
case PIPE_SWIZZLE_X:
665
case PIPE_SWIZZLE_Y:
666
case PIPE_SWIZZLE_Z:
667
case PIPE_SWIZZLE_W:
668
return desc->channel[swizzle].type == UTIL_FORMAT_TYPE_VOID ? PIPE_SWIZZLE_1 : swizzle;
669
default:
670
break;
671
}
672
return swizzle;
673
}
674
675
ALWAYS_INLINE static enum pipe_swizzle
676
clamp_zs_swizzle(enum pipe_swizzle swizzle)
677
{
678
switch (swizzle) {
679
case PIPE_SWIZZLE_X:
680
case PIPE_SWIZZLE_Y:
681
case PIPE_SWIZZLE_Z:
682
case PIPE_SWIZZLE_W:
683
return PIPE_SWIZZLE_X;
684
default:
685
break;
686
}
687
return swizzle;
688
}
689
690
static inline bool
691
format_is_usable_rgba_variant(const struct util_format_description *desc)
692
{
693
unsigned chan;
694
695
if(desc->block.width != 1 ||
696
desc->block.height != 1 ||
697
(desc->block.bits != 32 && desc->block.bits != 64))
698
return false;
699
700
if (desc->nr_channels != 4)
701
return false;
702
703
unsigned size = desc->channel[0].size;
704
for(chan = 0; chan < 4; ++chan) {
705
if(desc->channel[chan].size != size)
706
return false;
707
}
708
709
return true;
710
}
711
712
static struct pipe_sampler_view *
713
zink_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *pres,
714
const struct pipe_sampler_view *state)
715
{
716
struct zink_screen *screen = zink_screen(pctx->screen);
717
struct zink_resource *res = zink_resource(pres);
718
struct zink_sampler_view *sampler_view = CALLOC_STRUCT(zink_sampler_view);
719
bool err;
720
721
sampler_view->base = *state;
722
sampler_view->base.texture = NULL;
723
pipe_resource_reference(&sampler_view->base.texture, pres);
724
sampler_view->base.reference.count = 1;
725
sampler_view->base.context = pctx;
726
727
if (state->target != PIPE_BUFFER) {
728
VkImageViewCreateInfo ivci;
729
730
struct pipe_surface templ = {0};
731
templ.u.tex.level = state->u.tex.first_level;
732
templ.format = state->format;
733
if (state->target != PIPE_TEXTURE_3D) {
734
templ.u.tex.first_layer = state->u.tex.first_layer;
735
templ.u.tex.last_layer = state->u.tex.last_layer;
736
}
737
738
ivci = create_ivci(screen, res, &templ, state->target);
739
ivci.subresourceRange.levelCount = state->u.tex.last_level - state->u.tex.first_level + 1;
740
ivci.subresourceRange.aspectMask = sampler_aspect_from_format(state->format);
741
/* samplers for stencil aspects of packed formats need to always use stencil swizzle */
742
if (ivci.subresourceRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
743
ivci.components.r = component_mapping(clamp_zs_swizzle(sampler_view->base.swizzle_r));
744
ivci.components.g = component_mapping(clamp_zs_swizzle(sampler_view->base.swizzle_g));
745
ivci.components.b = component_mapping(clamp_zs_swizzle(sampler_view->base.swizzle_b));
746
ivci.components.a = component_mapping(clamp_zs_swizzle(sampler_view->base.swizzle_a));
747
} else {
748
/* if we have e.g., R8G8B8X8, then we have to ignore alpha since we're just emulating
749
* these formats
750
*/
751
const struct util_format_description *desc = util_format_description(state->format);
752
if (format_is_usable_rgba_variant(desc)) {
753
sampler_view->base.swizzle_r = clamp_void_swizzle(desc, sampler_view->base.swizzle_r);
754
sampler_view->base.swizzle_g = clamp_void_swizzle(desc, sampler_view->base.swizzle_g);
755
sampler_view->base.swizzle_b = clamp_void_swizzle(desc, sampler_view->base.swizzle_b);
756
sampler_view->base.swizzle_a = clamp_void_swizzle(desc, sampler_view->base.swizzle_a);
757
}
758
ivci.components.r = component_mapping(sampler_view->base.swizzle_r);
759
ivci.components.g = component_mapping(sampler_view->base.swizzle_g);
760
ivci.components.b = component_mapping(sampler_view->base.swizzle_b);
761
ivci.components.a = component_mapping(sampler_view->base.swizzle_a);
762
}
763
assert(ivci.format);
764
765
sampler_view->image_view = (struct zink_surface*)zink_get_surface(zink_context(pctx), pres, &templ, &ivci);
766
err = !sampler_view->image_view;
767
} else {
768
sampler_view->buffer_view = get_buffer_view(zink_context(pctx), res, state->format, state->u.buf.offset, state->u.buf.size);
769
err = !sampler_view->buffer_view;
770
}
771
if (err) {
772
FREE(sampler_view);
773
return NULL;
774
}
775
return &sampler_view->base;
776
}
777
778
void
779
zink_destroy_buffer_view(struct zink_screen *screen, struct zink_buffer_view *buffer_view)
780
{
781
simple_mtx_lock(&screen->bufferview_mtx);
782
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&screen->bufferview_cache, buffer_view->hash, &buffer_view->bvci);
783
assert(he);
784
_mesa_hash_table_remove(&screen->bufferview_cache, he);
785
simple_mtx_unlock(&screen->bufferview_mtx);
786
vkDestroyBufferView(screen->dev, buffer_view->buffer_view, NULL);
787
zink_descriptor_set_refs_clear(&buffer_view->desc_set_refs, buffer_view);
788
FREE(buffer_view);
789
}
790
791
static void
792
zink_sampler_view_destroy(struct pipe_context *pctx,
793
struct pipe_sampler_view *pview)
794
{
795
struct zink_sampler_view *view = zink_sampler_view(pview);
796
if (pview->texture->target == PIPE_BUFFER)
797
zink_buffer_view_reference(zink_screen(pctx->screen), &view->buffer_view, NULL);
798
else {
799
zink_surface_reference(zink_screen(pctx->screen), &view->image_view, NULL);
800
}
801
pipe_resource_reference(&pview->texture, NULL);
802
FREE(view);
803
}
804
805
static void
806
zink_get_sample_position(struct pipe_context *ctx,
807
unsigned sample_count,
808
unsigned sample_index,
809
float *out_value)
810
{
811
/* TODO: handle this I guess */
812
assert(zink_screen(ctx->screen)->info.props.limits.standardSampleLocations);
813
/* from 26.4. Multisampling */
814
switch (sample_count) {
815
case 0:
816
case 1: {
817
float pos[][2] = { {0.5,0.5}, };
818
out_value[0] = pos[sample_index][0];
819
out_value[1] = pos[sample_index][1];
820
break;
821
}
822
case 2: {
823
float pos[][2] = { {0.75,0.75},
824
{0.25,0.25}, };
825
out_value[0] = pos[sample_index][0];
826
out_value[1] = pos[sample_index][1];
827
break;
828
}
829
case 4: {
830
float pos[][2] = { {0.375, 0.125},
831
{0.875, 0.375},
832
{0.125, 0.625},
833
{0.625, 0.875}, };
834
out_value[0] = pos[sample_index][0];
835
out_value[1] = pos[sample_index][1];
836
break;
837
}
838
case 8: {
839
float pos[][2] = { {0.5625, 0.3125},
840
{0.4375, 0.6875},
841
{0.8125, 0.5625},
842
{0.3125, 0.1875},
843
{0.1875, 0.8125},
844
{0.0625, 0.4375},
845
{0.6875, 0.9375},
846
{0.9375, 0.0625}, };
847
out_value[0] = pos[sample_index][0];
848
out_value[1] = pos[sample_index][1];
849
break;
850
}
851
case 16: {
852
float pos[][2] = { {0.5625, 0.5625},
853
{0.4375, 0.3125},
854
{0.3125, 0.625},
855
{0.75, 0.4375},
856
{0.1875, 0.375},
857
{0.625, 0.8125},
858
{0.8125, 0.6875},
859
{0.6875, 0.1875},
860
{0.375, 0.875},
861
{0.5, 0.0625},
862
{0.25, 0.125},
863
{0.125, 0.75},
864
{0.0, 0.5},
865
{0.9375, 0.25},
866
{0.875, 0.9375},
867
{0.0625, 0.0}, };
868
out_value[0] = pos[sample_index][0];
869
out_value[1] = pos[sample_index][1];
870
break;
871
}
872
default:
873
unreachable("unhandled sample count!");
874
}
875
}
876
877
static void
878
zink_set_polygon_stipple(struct pipe_context *pctx,
879
const struct pipe_poly_stipple *ps)
880
{
881
}
882
883
ALWAYS_INLINE static void
884
update_res_bind_count(struct zink_context *ctx, struct zink_resource *res, bool is_compute, bool decrement)
885
{
886
if (decrement) {
887
assert(res->bind_count[is_compute]);
888
if (!--res->bind_count[is_compute])
889
_mesa_set_remove_key(ctx->need_barriers[is_compute], res);
890
check_resource_for_batch_ref(ctx, res);
891
} else
892
res->bind_count[is_compute]++;
893
}
894
895
ALWAYS_INLINE static void
896
update_existing_vbo(struct zink_context *ctx, unsigned slot)
897
{
898
if (!ctx->vertex_buffers[slot].buffer.resource)
899
return;
900
struct zink_resource *res = zink_resource(ctx->vertex_buffers[slot].buffer.resource);
901
res->vbo_bind_count--;
902
update_res_bind_count(ctx, res, false, true);
903
}
904
905
static void
906
zink_set_vertex_buffers(struct pipe_context *pctx,
907
unsigned start_slot,
908
unsigned num_buffers,
909
unsigned unbind_num_trailing_slots,
910
bool take_ownership,
911
const struct pipe_vertex_buffer *buffers)
912
{
913
struct zink_context *ctx = zink_context(pctx);
914
915
uint32_t enabled_buffers = ctx->gfx_pipeline_state.vertex_buffers_enabled_mask;
916
enabled_buffers |= u_bit_consecutive(start_slot, num_buffers);
917
enabled_buffers &= ~u_bit_consecutive(start_slot + num_buffers, unbind_num_trailing_slots);
918
919
if (buffers) {
920
if (!zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state)
921
ctx->gfx_pipeline_state.vertex_state_dirty = true;
922
for (unsigned i = 0; i < num_buffers; ++i) {
923
const struct pipe_vertex_buffer *vb = buffers + i;
924
struct pipe_vertex_buffer *ctx_vb = &ctx->vertex_buffers[start_slot + i];
925
update_existing_vbo(ctx, start_slot + i);
926
if (!take_ownership)
927
pipe_resource_reference(&ctx_vb->buffer.resource, vb->buffer.resource);
928
else {
929
pipe_resource_reference(&ctx_vb->buffer.resource, NULL);
930
ctx_vb->buffer.resource = vb->buffer.resource;
931
}
932
if (vb->buffer.resource) {
933
struct zink_resource *res = zink_resource(vb->buffer.resource);
934
res->vbo_bind_count++;
935
update_res_bind_count(ctx, res, false, false);
936
ctx_vb->stride = vb->stride;
937
ctx_vb->buffer_offset = vb->buffer_offset;
938
zink_batch_resource_usage_set(&ctx->batch, res, false);
939
zink_resource_buffer_barrier(ctx, NULL, res, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
940
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT);
941
}
942
}
943
} else {
944
if (!zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state)
945
ctx->gfx_pipeline_state.vertex_state_dirty = true;
946
for (unsigned i = 0; i < num_buffers; ++i) {
947
update_existing_vbo(ctx, start_slot + i);
948
pipe_resource_reference(&ctx->vertex_buffers[start_slot + i].buffer.resource, NULL);
949
}
950
}
951
for (unsigned i = 0; i < unbind_num_trailing_slots; i++) {
952
update_existing_vbo(ctx, start_slot + i);
953
pipe_resource_reference(&ctx->vertex_buffers[start_slot + i].buffer.resource, NULL);
954
}
955
ctx->gfx_pipeline_state.vertex_buffers_enabled_mask = enabled_buffers;
956
ctx->vertex_buffers_dirty = num_buffers > 0;
957
}
958
959
static void
960
zink_set_viewport_states(struct pipe_context *pctx,
961
unsigned start_slot,
962
unsigned num_viewports,
963
const struct pipe_viewport_state *state)
964
{
965
struct zink_context *ctx = zink_context(pctx);
966
967
for (unsigned i = 0; i < num_viewports; ++i)
968
ctx->vp_state.viewport_states[start_slot + i] = state[i];
969
ctx->vp_state.num_viewports = start_slot + num_viewports;
970
971
if (!zink_screen(pctx->screen)->info.have_EXT_extended_dynamic_state) {
972
if (ctx->gfx_pipeline_state.num_viewports != ctx->vp_state.num_viewports)
973
ctx->gfx_pipeline_state.dirty = true;
974
ctx->gfx_pipeline_state.num_viewports = ctx->vp_state.num_viewports;
975
}
976
ctx->vp_state_changed = true;
977
}
978
979
static void
980
zink_set_scissor_states(struct pipe_context *pctx,
981
unsigned start_slot, unsigned num_scissors,
982
const struct pipe_scissor_state *states)
983
{
984
struct zink_context *ctx = zink_context(pctx);
985
986
for (unsigned i = 0; i < num_scissors; i++)
987
ctx->vp_state.scissor_states[start_slot + i] = states[i];
988
ctx->scissor_changed = true;
989
}
990
991
static void
992
zink_set_inlinable_constants(struct pipe_context *pctx,
993
enum pipe_shader_type shader,
994
uint num_values, uint32_t *values)
995
{
996
struct zink_context *ctx = (struct zink_context *)pctx;
997
998
memcpy(ctx->inlinable_uniforms[shader], values, num_values * 4);
999
ctx->dirty_shader_stages |= 1 << shader;
1000
ctx->inlinable_uniforms_valid_mask |= 1 << shader;
1001
}
1002
1003
ALWAYS_INLINE static void
1004
unbind_ubo(struct zink_context *ctx, struct zink_resource *res, enum pipe_shader_type pstage, unsigned slot)
1005
{
1006
if (!res)
1007
return;
1008
res->ubo_bind_mask[pstage] &= ~BITFIELD_BIT(slot);
1009
res->ubo_bind_count[pstage == PIPE_SHADER_COMPUTE]--;
1010
update_res_bind_count(ctx, res, pstage == PIPE_SHADER_COMPUTE, true);
1011
}
1012
1013
static void
1014
zink_set_constant_buffer(struct pipe_context *pctx,
1015
enum pipe_shader_type shader, uint index,
1016
bool take_ownership,
1017
const struct pipe_constant_buffer *cb)
1018
{
1019
struct zink_context *ctx = zink_context(pctx);
1020
bool update = false;
1021
1022
struct zink_resource *res = zink_resource(ctx->ubos[shader][index].buffer);
1023
if (cb) {
1024
struct pipe_resource *buffer = cb->buffer;
1025
unsigned offset = cb->buffer_offset;
1026
struct zink_screen *screen = zink_screen(pctx->screen);
1027
if (cb->user_buffer) {
1028
u_upload_data(ctx->base.const_uploader, 0, cb->buffer_size,
1029
screen->info.props.limits.minUniformBufferOffsetAlignment,
1030
cb->user_buffer, &offset, &buffer);
1031
}
1032
struct zink_resource *new_res = zink_resource(buffer);
1033
if (new_res) {
1034
if (new_res != res) {
1035
unbind_ubo(ctx, res, shader, index);
1036
new_res->bind_history |= BITFIELD_BIT(ZINK_DESCRIPTOR_TYPE_UBO);
1037
new_res->bind_stages |= 1 << shader;
1038
new_res->ubo_bind_count[shader == PIPE_SHADER_COMPUTE]++;
1039
new_res->ubo_bind_mask[shader] |= BITFIELD_BIT(index);
1040
update_res_bind_count(ctx, new_res, shader == PIPE_SHADER_COMPUTE, false);
1041
}
1042
zink_batch_resource_usage_set(&ctx->batch, new_res, false);
1043
zink_fake_buffer_barrier(new_res, VK_ACCESS_UNIFORM_READ_BIT,
1044
zink_pipeline_flags_from_pipe_stage(shader));
1045
}
1046
update |= ((index || screen->descriptor_mode == ZINK_DESCRIPTOR_MODE_LAZY) && ctx->ubos[shader][index].buffer_offset != offset) ||
1047
!!res != !!buffer || (res && res->obj->buffer != new_res->obj->buffer) ||
1048
ctx->ubos[shader][index].buffer_size != cb->buffer_size;
1049
1050
if (take_ownership) {
1051
pipe_resource_reference(&ctx->ubos[shader][index].buffer, NULL);
1052
ctx->ubos[shader][index].buffer = buffer;
1053
} else {
1054
pipe_resource_reference(&ctx->ubos[shader][index].buffer, buffer);
1055
}
1056
ctx->ubos[shader][index].buffer_offset = offset;
1057
ctx->ubos[shader][index].buffer_size = cb->buffer_size;
1058
ctx->ubos[shader][index].user_buffer = NULL;
1059
1060
if (cb->user_buffer)
1061
pipe_resource_reference(&buffer, NULL);
1062
1063
if (index + 1 >= ctx->di.num_ubos[shader])
1064
ctx->di.num_ubos[shader] = index + 1;
1065
} else {
1066
if (res)
1067
unbind_ubo(ctx, res, shader, index);
1068
update = !!ctx->ubos[shader][index].buffer;
1069
1070
pipe_resource_reference(&ctx->ubos[shader][index].buffer, NULL);
1071
ctx->ubos[shader][index].buffer_offset = 0;
1072
ctx->ubos[shader][index].buffer_size = 0;
1073
ctx->ubos[shader][index].user_buffer = NULL;
1074
if (ctx->di.num_ubos[shader] == index + 1)
1075
ctx->di.num_ubos[shader]--;
1076
}
1077
if (index == 0) {
1078
/* Invalidate current inlinable uniforms. */
1079
ctx->inlinable_uniforms_valid_mask &= ~(1 << shader);
1080
}
1081
update_descriptor_state_ubo(ctx, shader, index);
1082
1083
if (update)
1084
zink_screen(pctx->screen)->context_invalidate_descriptor_state(ctx, shader, ZINK_DESCRIPTOR_TYPE_UBO, index, 1);
1085
}
1086
1087
ALWAYS_INLINE static void
1088
unbind_ssbo(struct zink_context *ctx, struct zink_resource *res, enum pipe_shader_type pstage, unsigned slot, bool writable)
1089
{
1090
if (!res)
1091
return;
1092
res->ssbo_bind_mask[pstage] &= ~BITFIELD_BIT(slot);
1093
update_res_bind_count(ctx, res, pstage == PIPE_SHADER_COMPUTE, true);
1094
if (writable)
1095
res->write_bind_count[pstage == PIPE_SHADER_COMPUTE]--;
1096
}
1097
1098
static void
1099
zink_set_shader_buffers(struct pipe_context *pctx,
1100
enum pipe_shader_type p_stage,
1101
unsigned start_slot, unsigned count,
1102
const struct pipe_shader_buffer *buffers,
1103
unsigned writable_bitmask)
1104
{
1105
struct zink_context *ctx = zink_context(pctx);
1106
bool update = false;
1107
unsigned max_slot = 0;
1108
1109
unsigned modified_bits = u_bit_consecutive(start_slot, count);
1110
unsigned old_writable_mask = ctx->writable_ssbos[p_stage];
1111
ctx->writable_ssbos[p_stage] &= ~modified_bits;
1112
ctx->writable_ssbos[p_stage] |= writable_bitmask << start_slot;
1113
1114
for (unsigned i = 0; i < count; i++) {
1115
struct pipe_shader_buffer *ssbo = &ctx->ssbos[p_stage][start_slot + i];
1116
struct zink_resource *res = ssbo->buffer ? zink_resource(ssbo->buffer) : NULL;
1117
bool was_writable = old_writable_mask & BITFIELD64_BIT(start_slot + i);
1118
if (buffers && buffers[i].buffer) {
1119
struct zink_resource *new_res = zink_resource(buffers[i].buffer);
1120
if (new_res != res) {
1121
unbind_ssbo(ctx, res, p_stage, i, was_writable);
1122
new_res->bind_history |= BITFIELD_BIT(ZINK_DESCRIPTOR_TYPE_SSBO);
1123
new_res->bind_stages |= 1 << p_stage;
1124
new_res->ssbo_bind_mask[p_stage] |= BITFIELD_BIT(i);
1125
update_res_bind_count(ctx, new_res, p_stage == PIPE_SHADER_COMPUTE, false);
1126
}
1127
VkAccessFlags access = VK_ACCESS_SHADER_READ_BIT;
1128
if (ctx->writable_ssbos[p_stage] & BITFIELD64_BIT(start_slot + i)) {
1129
new_res->write_bind_count[p_stage == PIPE_SHADER_COMPUTE]++;
1130
access |= VK_ACCESS_SHADER_WRITE_BIT;
1131
}
1132
pipe_resource_reference(&ssbo->buffer, &new_res->base.b);
1133
zink_batch_resource_usage_set(&ctx->batch, new_res, access & VK_ACCESS_SHADER_WRITE_BIT);
1134
ssbo->buffer_offset = buffers[i].buffer_offset;
1135
ssbo->buffer_size = MIN2(buffers[i].buffer_size, new_res->base.b.width0 - ssbo->buffer_offset);
1136
util_range_add(&new_res->base.b, &new_res->valid_buffer_range, ssbo->buffer_offset,
1137
ssbo->buffer_offset + ssbo->buffer_size);
1138
zink_fake_buffer_barrier(new_res, access,
1139
zink_pipeline_flags_from_pipe_stage(p_stage));
1140
update = true;
1141
max_slot = MAX2(max_slot, start_slot + i);
1142
} else {
1143
update = !!res;
1144
if (res)
1145
unbind_ssbo(ctx, res, p_stage, i, was_writable);
1146
pipe_resource_reference(&ssbo->buffer, NULL);
1147
ssbo->buffer_offset = 0;
1148
ssbo->buffer_size = 0;
1149
}
1150
update_descriptor_state_ssbo(ctx, p_stage, start_slot + i);
1151
}
1152
if (start_slot + count >= ctx->di.num_ssbos[p_stage])
1153
ctx->di.num_ssbos[p_stage] = max_slot + 1;
1154
if (update)
1155
zink_screen(pctx->screen)->context_invalidate_descriptor_state(ctx, p_stage, ZINK_DESCRIPTOR_TYPE_SSBO, start_slot, count);
1156
}
1157
1158
static void
1159
update_binds_for_samplerviews(struct zink_context *ctx, struct zink_resource *res, bool is_compute)
1160
{
1161
VkImageLayout layout = get_layout_for_binding(res, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW, is_compute);
1162
if (is_compute) {
1163
u_foreach_bit(slot, res->sampler_binds[PIPE_SHADER_COMPUTE]) {
1164
if (ctx->di.textures[PIPE_SHADER_COMPUTE][slot].imageLayout != layout) {
1165
update_descriptor_state_sampler(ctx, PIPE_SHADER_COMPUTE, slot);
1166
zink_screen(ctx->base.screen)->context_invalidate_descriptor_state(ctx, PIPE_SHADER_COMPUTE, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW, slot, 1);
1167
}
1168
}
1169
} else {
1170
for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) {
1171
u_foreach_bit(slot, res->sampler_binds[i]) {
1172
if (ctx->di.textures[i][slot].imageLayout != layout) {
1173
update_descriptor_state_sampler(ctx, i, slot);
1174
zink_screen(ctx->base.screen)->context_invalidate_descriptor_state(ctx, i, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW, slot, 1);
1175
}
1176
}
1177
}
1178
}
1179
}
1180
1181
static void
1182
flush_pending_clears(struct zink_context *ctx, struct zink_resource *res)
1183
{
1184
if (res->fb_binds && ctx->clears_enabled)
1185
zink_fb_clears_apply(ctx, &res->base.b);
1186
}
1187
1188
static inline void
1189
unbind_shader_image_counts(struct zink_context *ctx, struct zink_resource *res, bool is_compute, bool writable)
1190
{
1191
update_res_bind_count(ctx, res, is_compute, true);
1192
if (writable)
1193
res->write_bind_count[is_compute]--;
1194
res->image_bind_count[is_compute]--;
1195
/* if this was the last image bind, the sampler bind layouts must be updated */
1196
if (!res->obj->is_buffer && !res->image_bind_count[is_compute] && res->bind_count[is_compute])
1197
update_binds_for_samplerviews(ctx, res, is_compute);
1198
}
1199
1200
ALWAYS_INLINE static void
1201
check_for_layout_update(struct zink_context *ctx, struct zink_resource *res, bool is_compute)
1202
{
1203
VkImageLayout layout = res->bind_count[is_compute] ? zink_descriptor_util_image_layout_eval(res, is_compute) : VK_IMAGE_LAYOUT_UNDEFINED;
1204
VkImageLayout other_layout = res->bind_count[!is_compute] ? zink_descriptor_util_image_layout_eval(res, !is_compute) : VK_IMAGE_LAYOUT_UNDEFINED;
1205
if (res->bind_count[is_compute] && res->layout != layout)
1206
_mesa_set_add(ctx->need_barriers[is_compute], res);
1207
if (res->bind_count[!is_compute] && (layout != other_layout || res->layout != other_layout))
1208
_mesa_set_add(ctx->need_barriers[!is_compute], res);
1209
}
1210
1211
static void
1212
unbind_shader_image(struct zink_context *ctx, enum pipe_shader_type stage, unsigned slot)
1213
{
1214
struct zink_image_view *image_view = &ctx->image_views[stage][slot];
1215
bool is_compute = stage == PIPE_SHADER_COMPUTE;
1216
if (!image_view->base.resource)
1217
return;
1218
1219
struct zink_resource *res = zink_resource(image_view->base.resource);
1220
unbind_shader_image_counts(ctx, res, is_compute, image_view->base.access & PIPE_IMAGE_ACCESS_WRITE);
1221
1222
if (image_view->base.resource->target == PIPE_BUFFER) {
1223
if (zink_batch_usage_exists(image_view->buffer_view->batch_uses))
1224
zink_batch_reference_bufferview(&ctx->batch, image_view->buffer_view);
1225
zink_buffer_view_reference(zink_screen(ctx->base.screen), &image_view->buffer_view, NULL);
1226
} else {
1227
if (!res->image_bind_count[is_compute])
1228
check_for_layout_update(ctx, res, is_compute);
1229
if (zink_batch_usage_exists(image_view->surface->batch_uses))
1230
zink_batch_reference_surface(&ctx->batch, image_view->surface);
1231
zink_surface_reference(zink_screen(ctx->base.screen), &image_view->surface, NULL);
1232
}
1233
pipe_resource_reference(&image_view->base.resource, NULL);
1234
image_view->base.resource = NULL;
1235
image_view->surface = NULL;
1236
}
1237
1238
static void
1239
zink_set_shader_images(struct pipe_context *pctx,
1240
enum pipe_shader_type p_stage,
1241
unsigned start_slot, unsigned count,
1242
unsigned unbind_num_trailing_slots,
1243
const struct pipe_image_view *images)
1244
{
1245
struct zink_context *ctx = zink_context(pctx);
1246
bool update = false;
1247
for (unsigned i = 0; i < count; i++) {
1248
struct zink_image_view *image_view = &ctx->image_views[p_stage][start_slot + i];
1249
if (images && images[i].resource) {
1250
struct zink_resource *res = zink_resource(images[i].resource);
1251
struct zink_resource *old_res = zink_resource(image_view->base.resource);
1252
if (!zink_resource_object_init_storage(ctx, res)) {
1253
debug_printf("couldn't create storage image!");
1254
continue;
1255
}
1256
if (res != old_res) {
1257
if (old_res) {
1258
unbind_shader_image_counts(ctx, old_res, p_stage == PIPE_SHADER_COMPUTE, image_view->base.access & PIPE_IMAGE_ACCESS_WRITE);
1259
if (!old_res->obj->is_buffer && !old_res->image_bind_count[p_stage == PIPE_SHADER_COMPUTE])
1260
check_for_layout_update(ctx, old_res, p_stage == PIPE_SHADER_COMPUTE);
1261
}
1262
res->bind_history |= BITFIELD_BIT(ZINK_DESCRIPTOR_TYPE_IMAGE);
1263
res->bind_stages |= 1 << p_stage;
1264
update_res_bind_count(ctx, res, p_stage == PIPE_SHADER_COMPUTE, false);
1265
}
1266
util_copy_image_view(&image_view->base, images + i);
1267
VkAccessFlags access = 0;
1268
if (image_view->base.access & PIPE_IMAGE_ACCESS_WRITE) {
1269
zink_resource(image_view->base.resource)->write_bind_count[p_stage == PIPE_SHADER_COMPUTE]++;
1270
access |= VK_ACCESS_SHADER_WRITE_BIT;
1271
}
1272
if (image_view->base.access & PIPE_IMAGE_ACCESS_READ) {
1273
access |= VK_ACCESS_SHADER_READ_BIT;
1274
}
1275
res->image_bind_count[p_stage == PIPE_SHADER_COMPUTE]++;
1276
if (images[i].resource->target == PIPE_BUFFER) {
1277
image_view->buffer_view = get_buffer_view(ctx, res, images[i].format, images[i].u.buf.offset, images[i].u.buf.size);
1278
assert(image_view->buffer_view);
1279
util_range_add(&res->base.b, &res->valid_buffer_range, images[i].u.buf.offset,
1280
images[i].u.buf.offset + images[i].u.buf.size);
1281
zink_batch_usage_set(&image_view->buffer_view->batch_uses, ctx->batch.state);
1282
zink_fake_buffer_barrier(res, access,
1283
zink_pipeline_flags_from_pipe_stage(p_stage));
1284
} else {
1285
struct pipe_surface tmpl = {0};
1286
tmpl.format = images[i].format;
1287
tmpl.nr_samples = 1;
1288
tmpl.u.tex.level = images[i].u.tex.level;
1289
tmpl.u.tex.first_layer = images[i].u.tex.first_layer;
1290
tmpl.u.tex.last_layer = images[i].u.tex.last_layer;
1291
image_view->surface = zink_surface(pctx->create_surface(pctx, &res->base.b, &tmpl));
1292
assert(image_view->surface);
1293
/* if this is the first image bind and there are sampler binds, the image's sampler layout
1294
* must be updated to GENERAL
1295
*/
1296
if (res->image_bind_count[p_stage == PIPE_SHADER_COMPUTE] == 1 &&
1297
res->bind_count[p_stage == PIPE_SHADER_COMPUTE] > 1)
1298
update_binds_for_samplerviews(ctx, res, p_stage == PIPE_SHADER_COMPUTE);
1299
check_for_layout_update(ctx, res, p_stage == PIPE_SHADER_COMPUTE);
1300
zink_batch_usage_set(&image_view->surface->batch_uses, ctx->batch.state);
1301
flush_pending_clears(ctx, res);
1302
}
1303
zink_batch_resource_usage_set(&ctx->batch, zink_resource(image_view->base.resource),
1304
zink_resource_access_is_write(access));
1305
update = true;
1306
} else if (image_view->base.resource) {
1307
update |= !!image_view->base.resource;
1308
1309
unbind_shader_image(ctx, p_stage, start_slot + i);
1310
}
1311
update_descriptor_state_image(ctx, p_stage, start_slot + i);
1312
}
1313
for (unsigned i = 0; i < unbind_num_trailing_slots; i++) {
1314
update |= !!ctx->image_views[p_stage][start_slot + count + i].base.resource;
1315
unbind_shader_image(ctx, p_stage, start_slot + count + i);
1316
update_descriptor_state_image(ctx, p_stage, start_slot + count + i);
1317
}
1318
ctx->di.num_images[p_stage] = start_slot + count;
1319
if (update)
1320
zink_screen(pctx->screen)->context_invalidate_descriptor_state(ctx, p_stage, ZINK_DESCRIPTOR_TYPE_IMAGE, start_slot, count);
1321
}
1322
1323
ALWAYS_INLINE static void
1324
check_samplerview_for_batch_ref(struct zink_context *ctx, struct zink_sampler_view *sv)
1325
{
1326
const struct zink_resource *res = zink_resource(sv->base.texture);
1327
if ((res->obj->is_buffer && zink_batch_usage_exists(sv->buffer_view->batch_uses)) ||
1328
(!res->obj->is_buffer && zink_batch_usage_exists(sv->image_view->batch_uses)))
1329
zink_batch_reference_sampler_view(&ctx->batch, sv);
1330
}
1331
1332
ALWAYS_INLINE static void
1333
unbind_samplerview(struct zink_context *ctx, enum pipe_shader_type stage, unsigned slot)
1334
{
1335
struct zink_sampler_view *sv = zink_sampler_view(ctx->sampler_views[stage][slot]);
1336
if (!sv || !sv->base.texture)
1337
return;
1338
struct zink_resource *res = zink_resource(sv->base.texture);
1339
check_samplerview_for_batch_ref(ctx, sv);
1340
update_res_bind_count(ctx, res, stage == PIPE_SHADER_COMPUTE, true);
1341
res->sampler_binds[stage] &= ~BITFIELD_BIT(slot);
1342
}
1343
1344
static void
1345
zink_set_sampler_views(struct pipe_context *pctx,
1346
enum pipe_shader_type shader_type,
1347
unsigned start_slot,
1348
unsigned num_views,
1349
unsigned unbind_num_trailing_slots,
1350
struct pipe_sampler_view **views)
1351
{
1352
struct zink_context *ctx = zink_context(pctx);
1353
unsigned i;
1354
1355
bool update = false;
1356
for (i = 0; i < num_views; ++i) {
1357
struct pipe_sampler_view *pview = views ? views[i] : NULL;
1358
struct zink_sampler_view *a = zink_sampler_view(ctx->sampler_views[shader_type][start_slot + i]);
1359
struct zink_sampler_view *b = zink_sampler_view(pview);
1360
if (b && b->base.texture) {
1361
struct zink_resource *res = zink_resource(b->base.texture);
1362
if (!a || zink_resource(a->base.texture) != res) {
1363
if (a)
1364
unbind_samplerview(ctx, shader_type, start_slot + i);
1365
update_res_bind_count(ctx, res, shader_type == PIPE_SHADER_COMPUTE, false);
1366
res->bind_history |= BITFIELD64_BIT(ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW);
1367
res->bind_stages |= 1 << shader_type;
1368
} else if (a != b) {
1369
check_samplerview_for_batch_ref(ctx, a);
1370
}
1371
if (res->base.b.target == PIPE_BUFFER) {
1372
if (res->bind_history & BITFIELD64_BIT(ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW)) {
1373
/* if this resource has been rebound while it wasn't set here,
1374
* its backing resource will have changed and thus we need to update
1375
* the bufferview
1376
*/
1377
struct zink_buffer_view *buffer_view = get_buffer_view(ctx, res, b->base.format, b->base.u.buf.offset, b->base.u.buf.size);
1378
if (buffer_view == b->buffer_view)
1379
p_atomic_dec(&buffer_view->reference.count);
1380
else {
1381
if (zink_batch_usage_exists(b->buffer_view->batch_uses))
1382
zink_batch_reference_bufferview(&ctx->batch, b->buffer_view);
1383
zink_buffer_view_reference(zink_screen(ctx->base.screen), &b->buffer_view, NULL);
1384
b->buffer_view = buffer_view;
1385
update = true;
1386
}
1387
}
1388
zink_batch_usage_set(&b->buffer_view->batch_uses, ctx->batch.state);
1389
zink_fake_buffer_barrier(res, VK_ACCESS_SHADER_READ_BIT,
1390
zink_pipeline_flags_from_pipe_stage(shader_type));
1391
if (!a || a->buffer_view->buffer_view != b->buffer_view->buffer_view)
1392
update = true;
1393
} else if (!res->obj->is_buffer) {
1394
if (res->obj != b->image_view->obj) {
1395
struct pipe_surface *psurf = &b->image_view->base;
1396
VkImageView iv = b->image_view->image_view;
1397
zink_rebind_surface(ctx, &psurf);
1398
b->image_view = zink_surface(psurf);
1399
update |= iv != b->image_view->image_view;
1400
} else if (a != b)
1401
update = true;
1402
flush_pending_clears(ctx, res);
1403
check_for_layout_update(ctx, res, shader_type == PIPE_SHADER_COMPUTE);
1404
zink_batch_usage_set(&b->image_view->batch_uses, ctx->batch.state);
1405
if (!a)
1406
update = true;
1407
}
1408
res->sampler_binds[shader_type] |= BITFIELD_BIT(start_slot + i);
1409
zink_batch_resource_usage_set(&ctx->batch, res, false);
1410
} else if (a) {
1411
unbind_samplerview(ctx, shader_type, start_slot + i);
1412
update = true;
1413
}
1414
pipe_sampler_view_reference(&ctx->sampler_views[shader_type][start_slot + i], pview);
1415
update_descriptor_state_sampler(ctx, shader_type, start_slot + i);
1416
}
1417
for (; i < num_views + unbind_num_trailing_slots; ++i) {
1418
update |= !!ctx->sampler_views[shader_type][start_slot + i];
1419
unbind_samplerview(ctx, shader_type, start_slot + i);
1420
pipe_sampler_view_reference(
1421
&ctx->sampler_views[shader_type][start_slot + i],
1422
NULL);
1423
update_descriptor_state_sampler(ctx, shader_type, start_slot + i);
1424
}
1425
ctx->di.num_sampler_views[shader_type] = start_slot + num_views;
1426
if (update)
1427
zink_screen(pctx->screen)->context_invalidate_descriptor_state(ctx, shader_type, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW, start_slot, num_views);
1428
}
1429
1430
static void
1431
zink_set_stencil_ref(struct pipe_context *pctx,
1432
const struct pipe_stencil_ref ref)
1433
{
1434
struct zink_context *ctx = zink_context(pctx);
1435
ctx->stencil_ref = ref;
1436
ctx->stencil_ref_changed = true;
1437
}
1438
1439
static void
1440
zink_set_clip_state(struct pipe_context *pctx,
1441
const struct pipe_clip_state *pcs)
1442
{
1443
}
1444
1445
static void
1446
zink_set_tess_state(struct pipe_context *pctx,
1447
const float default_outer_level[4],
1448
const float default_inner_level[2])
1449
{
1450
struct zink_context *ctx = zink_context(pctx);
1451
memcpy(&ctx->default_inner_level, default_inner_level, sizeof(ctx->default_inner_level));
1452
memcpy(&ctx->default_outer_level, default_outer_level, sizeof(ctx->default_outer_level));
1453
}
1454
1455
static uint32_t
1456
hash_render_pass_state(const void *key)
1457
{
1458
struct zink_render_pass_state* s = (struct zink_render_pass_state*)key;
1459
return _mesa_hash_data(key, offsetof(struct zink_render_pass_state, rts) + sizeof(s->rts[0]) * s->num_rts);
1460
}
1461
1462
static bool
1463
equals_render_pass_state(const void *a, const void *b)
1464
{
1465
const struct zink_render_pass_state *s_a = a, *s_b = b;
1466
if (s_a->num_rts != s_b->num_rts)
1467
return false;
1468
return memcmp(a, b, offsetof(struct zink_render_pass_state, rts) + sizeof(s_a->rts[0]) * s_a->num_rts) == 0;
1469
}
1470
1471
static struct zink_render_pass *
1472
get_render_pass(struct zink_context *ctx)
1473
{
1474
struct zink_screen *screen = zink_screen(ctx->base.screen);
1475
const struct pipe_framebuffer_state *fb = &ctx->fb_state;
1476
struct zink_render_pass_state state = {0};
1477
uint32_t clears = 0;
1478
state.swapchain_init = ctx->new_swapchain;
1479
1480
for (int i = 0; i < fb->nr_cbufs; i++) {
1481
struct pipe_surface *surf = fb->cbufs[i];
1482
if (surf) {
1483
state.rts[i].format = zink_get_format(screen, surf->format);
1484
state.rts[i].samples = surf->texture->nr_samples > 0 ? surf->texture->nr_samples :
1485
VK_SAMPLE_COUNT_1_BIT;
1486
state.rts[i].clear_color = zink_fb_clear_enabled(ctx, i) && !zink_fb_clear_first_needs_explicit(&ctx->fb_clears[i]);
1487
clears |= !!state.rts[i].clear_color ? PIPE_CLEAR_COLOR0 << i : 0;
1488
state.rts[i].swapchain = surf->texture->bind & PIPE_BIND_SCANOUT;
1489
} else {
1490
state.rts[i].format = VK_FORMAT_R8_UINT;
1491
state.rts[i].samples = MAX2(fb->samples, 1);
1492
}
1493
state.num_rts++;
1494
}
1495
state.num_cbufs = fb->nr_cbufs;
1496
1497
if (fb->zsbuf) {
1498
struct zink_resource *zsbuf = zink_resource(fb->zsbuf->texture);
1499
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS];
1500
state.rts[fb->nr_cbufs].format = zsbuf->format;
1501
state.rts[fb->nr_cbufs].samples = zsbuf->base.b.nr_samples > 0 ? zsbuf->base.b.nr_samples : VK_SAMPLE_COUNT_1_BIT;
1502
state.rts[fb->nr_cbufs].clear_color = zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) &&
1503
!zink_fb_clear_first_needs_explicit(fb_clear) &&
1504
(zink_fb_clear_element(fb_clear, 0)->zs.bits & PIPE_CLEAR_DEPTH);
1505
state.rts[fb->nr_cbufs].clear_stencil = zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) &&
1506
!zink_fb_clear_first_needs_explicit(fb_clear) &&
1507
(zink_fb_clear_element(fb_clear, 0)->zs.bits & PIPE_CLEAR_STENCIL);
1508
if (state.rts[fb->nr_cbufs].clear_color)
1509
clears |= PIPE_CLEAR_DEPTH;
1510
if (state.rts[fb->nr_cbufs].clear_stencil)
1511
clears |= PIPE_CLEAR_STENCIL;
1512
const uint64_t outputs_written = ctx->gfx_stages[PIPE_SHADER_FRAGMENT] ?
1513
ctx->gfx_stages[PIPE_SHADER_FRAGMENT]->nir->info.outputs_written : 0;
1514
bool needs_write = (ctx->dsa_state && ctx->dsa_state->hw_state.depth_write) ||
1515
outputs_written & (BITFIELD64_BIT(FRAG_RESULT_DEPTH) | BITFIELD64_BIT(FRAG_RESULT_STENCIL));
1516
state.rts[fb->nr_cbufs].needs_write = needs_write || state.rts[fb->nr_cbufs].clear_color || state.rts[fb->nr_cbufs].clear_stencil;
1517
state.num_rts++;
1518
}
1519
state.have_zsbuf = fb->zsbuf != NULL;
1520
assert(clears == ctx->rp_clears_enabled);
1521
state.clears = clears;
1522
uint32_t hash = hash_render_pass_state(&state);
1523
struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(ctx->render_pass_cache, hash,
1524
&state);
1525
struct zink_render_pass *rp;
1526
if (entry) {
1527
rp = entry->data;
1528
assert(rp->state.clears == clears);
1529
} else {
1530
rp = zink_create_render_pass(screen, &state);
1531
if (!_mesa_hash_table_insert_pre_hashed(ctx->render_pass_cache, hash, &rp->state, rp))
1532
return NULL;
1533
}
1534
return rp;
1535
}
1536
1537
static struct zink_framebuffer *
1538
get_framebuffer(struct zink_context *ctx)
1539
{
1540
struct zink_screen *screen = zink_screen(ctx->base.screen);
1541
struct pipe_surface *attachments[PIPE_MAX_COLOR_BUFS + 1] = {0};
1542
1543
struct zink_framebuffer_state state = {0};
1544
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
1545
struct pipe_surface *psurf = ctx->fb_state.cbufs[i];
1546
state.attachments[i] = psurf ? zink_surface(psurf)->image_view : VK_NULL_HANDLE;
1547
attachments[i] = psurf;
1548
}
1549
1550
state.num_attachments = ctx->fb_state.nr_cbufs;
1551
if (ctx->fb_state.zsbuf) {
1552
struct pipe_surface *psurf = ctx->fb_state.zsbuf;
1553
state.attachments[state.num_attachments] = psurf ? zink_surface(psurf)->image_view : VK_NULL_HANDLE;
1554
attachments[state.num_attachments++] = psurf;
1555
}
1556
1557
state.width = MAX2(ctx->fb_state.width, 1);
1558
state.height = MAX2(ctx->fb_state.height, 1);
1559
state.layers = MAX2(util_framebuffer_get_num_layers(&ctx->fb_state), 1);
1560
state.samples = ctx->fb_state.samples;
1561
1562
struct zink_framebuffer *fb;
1563
simple_mtx_lock(&screen->framebuffer_mtx);
1564
struct hash_entry *entry = _mesa_hash_table_search(&screen->framebuffer_cache, &state);
1565
if (entry) {
1566
fb = (void*)entry->data;
1567
struct zink_framebuffer *fb_ref = NULL;
1568
/* this gains 1 ref every time we reuse it */
1569
zink_framebuffer_reference(screen, &fb_ref, fb);
1570
} else {
1571
/* this adds 1 extra ref on creation because all newly-created framebuffers are
1572
* going to be bound; necessary to handle framebuffers which have no "real" attachments
1573
* and are only using null surfaces since the only ref they get is the extra one here
1574
*/
1575
fb = zink_create_framebuffer(ctx, &state, attachments);
1576
_mesa_hash_table_insert(&screen->framebuffer_cache, &fb->state, fb);
1577
}
1578
simple_mtx_unlock(&screen->framebuffer_mtx);
1579
1580
return fb;
1581
}
1582
1583
static void
1584
setup_framebuffer(struct zink_context *ctx)
1585
{
1586
struct zink_screen *screen = zink_screen(ctx->base.screen);
1587
struct zink_render_pass *rp = ctx->gfx_pipeline_state.render_pass;
1588
1589
if (ctx->gfx_pipeline_state.sample_locations_enabled && ctx->sample_locations_changed) {
1590
unsigned samples = ctx->gfx_pipeline_state.rast_samples;
1591
unsigned idx = util_logbase2_ceil(MAX2(samples, 1));
1592
VkExtent2D grid_size = screen->maxSampleLocationGridSize[idx];
1593
1594
for (unsigned pixel = 0; pixel < grid_size.width * grid_size.height; pixel++) {
1595
for (unsigned sample = 0; sample < samples; sample++) {
1596
unsigned pixel_x = pixel % grid_size.width;
1597
unsigned pixel_y = pixel / grid_size.width;
1598
unsigned wi = pixel * samples + sample;
1599
unsigned ri = (pixel_y * grid_size.width + pixel_x % grid_size.width);
1600
ri = ri * samples + sample;
1601
ctx->vk_sample_locations[wi].x = (ctx->sample_locations[ri] & 0xf) / 16.0f;
1602
ctx->vk_sample_locations[wi].y = (16 - (ctx->sample_locations[ri] >> 4)) / 16.0f;
1603
}
1604
}
1605
}
1606
1607
if (rp)
1608
ctx->rp_changed |= ctx->rp_clears_enabled != rp->state.clears;
1609
if (ctx->rp_changed)
1610
rp = get_render_pass(ctx);
1611
1612
if (rp != ctx->gfx_pipeline_state.render_pass)
1613
ctx->gfx_pipeline_state.dirty =
1614
ctx->fb_changed = true;
1615
1616
ctx->rp_changed = false;
1617
1618
if (!ctx->fb_changed)
1619
return;
1620
1621
zink_init_framebuffer(screen, ctx->framebuffer, rp);
1622
ctx->fb_changed = false;
1623
ctx->gfx_pipeline_state.render_pass = rp;
1624
}
1625
1626
static unsigned
1627
begin_render_pass(struct zink_context *ctx)
1628
{
1629
struct zink_batch *batch = &ctx->batch;
1630
struct pipe_framebuffer_state *fb_state = &ctx->fb_state;
1631
1632
VkRenderPassBeginInfo rpbi = {0};
1633
rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
1634
rpbi.renderPass = ctx->gfx_pipeline_state.render_pass->render_pass;
1635
rpbi.renderArea.offset.x = 0;
1636
rpbi.renderArea.offset.y = 0;
1637
rpbi.renderArea.extent.width = fb_state->width;
1638
rpbi.renderArea.extent.height = fb_state->height;
1639
1640
VkClearValue clears[PIPE_MAX_COLOR_BUFS + 1] = {0};
1641
unsigned clear_buffers = 0;
1642
uint32_t clear_validate = 0;
1643
for (int i = 0; i < fb_state->nr_cbufs; i++) {
1644
/* these are no-ops */
1645
if (!fb_state->cbufs[i] || !zink_fb_clear_enabled(ctx, i))
1646
continue;
1647
/* these need actual clear calls inside the rp */
1648
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(&ctx->fb_clears[i], 0);
1649
if (zink_fb_clear_needs_explicit(&ctx->fb_clears[i])) {
1650
clear_buffers |= (PIPE_CLEAR_COLOR0 << i);
1651
if (zink_fb_clear_count(&ctx->fb_clears[i]) < 2 ||
1652
zink_fb_clear_element_needs_explicit(clear))
1653
continue;
1654
}
1655
/* we now know there's one clear that can be done here */
1656
zink_fb_clear_util_unpack_clear_color(clear, fb_state->cbufs[i]->format, (void*)&clears[i].color);
1657
rpbi.clearValueCount = i + 1;
1658
clear_validate |= PIPE_CLEAR_COLOR0 << i;
1659
assert(ctx->framebuffer->rp->state.clears);
1660
}
1661
if (fb_state->zsbuf && zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS)) {
1662
struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS];
1663
struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, 0);
1664
if (!zink_fb_clear_element_needs_explicit(clear)) {
1665
clears[fb_state->nr_cbufs].depthStencil.depth = clear->zs.depth;
1666
clears[fb_state->nr_cbufs].depthStencil.stencil = clear->zs.stencil;
1667
rpbi.clearValueCount = fb_state->nr_cbufs + 1;
1668
clear_validate |= clear->zs.bits;
1669
assert(ctx->framebuffer->rp->state.clears);
1670
}
1671
if (zink_fb_clear_needs_explicit(fb_clear)) {
1672
for (int j = !zink_fb_clear_element_needs_explicit(clear);
1673
(clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL && j < zink_fb_clear_count(fb_clear);
1674
j++)
1675
clear_buffers |= zink_fb_clear_element(fb_clear, j)->zs.bits;
1676
}
1677
}
1678
assert(clear_validate == ctx->framebuffer->rp->state.clears);
1679
rpbi.pClearValues = &clears[0];
1680
rpbi.framebuffer = ctx->framebuffer->fb;
1681
1682
assert(ctx->gfx_pipeline_state.render_pass && ctx->framebuffer);
1683
1684
zink_batch_reference_framebuffer(batch, ctx->framebuffer);
1685
for (int i = 0; i < ctx->framebuffer->state.num_attachments; i++) {
1686
if (ctx->framebuffer->surfaces[i]) {
1687
struct zink_surface *surf = zink_surface(ctx->framebuffer->surfaces[i]);
1688
zink_batch_resource_usage_set(batch, zink_resource(surf->base.texture), true);
1689
zink_batch_usage_set(&surf->batch_uses, batch->state);
1690
1691
struct zink_resource *res = zink_resource(surf->base.texture);
1692
VkAccessFlags access;
1693
VkPipelineStageFlags pipeline;
1694
VkImageLayout layout = zink_render_pass_attachment_get_barrier_info(ctx->gfx_pipeline_state.render_pass,
1695
i, &pipeline, &access);
1696
zink_resource_image_barrier(ctx, NULL, res, layout, access, pipeline);
1697
}
1698
}
1699
1700
vkCmdBeginRenderPass(batch->state->cmdbuf, &rpbi, VK_SUBPASS_CONTENTS_INLINE);
1701
batch->in_rp = true;
1702
ctx->new_swapchain = false;
1703
return clear_buffers;
1704
}
1705
1706
void
1707
zink_init_vk_sample_locations(struct zink_context *ctx, VkSampleLocationsInfoEXT *loc)
1708
{
1709
struct zink_screen *screen = zink_screen(ctx->base.screen);
1710
unsigned idx = util_logbase2_ceil(MAX2(ctx->gfx_pipeline_state.rast_samples, 1));
1711
loc->sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT;
1712
loc->pNext = NULL;
1713
loc->sampleLocationsPerPixel = 1 << idx;
1714
loc->sampleLocationsCount = ctx->gfx_pipeline_state.rast_samples;
1715
loc->sampleLocationGridSize = screen->maxSampleLocationGridSize[idx];
1716
loc->pSampleLocations = ctx->vk_sample_locations;
1717
}
1718
1719
static void
1720
zink_evaluate_depth_buffer(struct pipe_context *pctx)
1721
{
1722
struct zink_context *ctx = zink_context(pctx);
1723
1724
if (!ctx->fb_state.zsbuf)
1725
return;
1726
1727
struct zink_resource *res = zink_resource(ctx->fb_state.zsbuf->texture);
1728
res->obj->needs_zs_evaluate = true;
1729
zink_init_vk_sample_locations(ctx, &res->obj->zs_evaluate);
1730
zink_batch_no_rp(ctx);
1731
}
1732
1733
void
1734
zink_begin_render_pass(struct zink_context *ctx, struct zink_batch *batch)
1735
{
1736
setup_framebuffer(ctx);
1737
assert(ctx->gfx_pipeline_state.render_pass);
1738
unsigned clear_buffers = begin_render_pass(ctx);
1739
1740
if (ctx->render_condition.query)
1741
zink_start_conditional_render(ctx);
1742
zink_clear_framebuffer(ctx, clear_buffers);
1743
}
1744
1745
static void
1746
zink_end_render_pass(struct zink_context *ctx, struct zink_batch *batch)
1747
{
1748
if (batch->in_rp) {
1749
if (ctx->render_condition.query)
1750
zink_stop_conditional_render(ctx);
1751
vkCmdEndRenderPass(batch->state->cmdbuf);
1752
}
1753
batch->in_rp = false;
1754
}
1755
1756
static void
1757
sync_flush(struct zink_context *ctx, struct zink_batch_state *bs)
1758
{
1759
if (zink_screen(ctx->base.screen)->threaded)
1760
util_queue_fence_wait(&bs->flush_completed);
1761
}
1762
1763
static inline VkAccessFlags
1764
get_access_flags_for_binding(struct zink_context *ctx, enum zink_descriptor_type type, enum pipe_shader_type stage, unsigned idx)
1765
{
1766
VkAccessFlags flags = 0;
1767
switch (type) {
1768
case ZINK_DESCRIPTOR_TYPE_UBO:
1769
return VK_ACCESS_UNIFORM_READ_BIT;
1770
case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
1771
return VK_ACCESS_SHADER_READ_BIT;
1772
case ZINK_DESCRIPTOR_TYPE_SSBO: {
1773
flags = VK_ACCESS_SHADER_READ_BIT;
1774
if (ctx->writable_ssbos[stage] & (1 << idx))
1775
flags |= VK_ACCESS_SHADER_WRITE_BIT;
1776
return flags;
1777
}
1778
case ZINK_DESCRIPTOR_TYPE_IMAGE: {
1779
struct zink_image_view *image_view = &ctx->image_views[stage][idx];
1780
if (image_view->base.access & PIPE_IMAGE_ACCESS_READ)
1781
flags |= VK_ACCESS_SHADER_READ_BIT;
1782
if (image_view->base.access & PIPE_IMAGE_ACCESS_WRITE)
1783
flags |= VK_ACCESS_SHADER_WRITE_BIT;
1784
return flags;
1785
}
1786
default:
1787
break;
1788
}
1789
unreachable("ACK");
1790
return 0;
1791
}
1792
1793
static void
1794
update_resource_refs_for_stage(struct zink_context *ctx, enum pipe_shader_type stage)
1795
{
1796
struct zink_batch *batch = &ctx->batch;
1797
unsigned max_slot[] = {
1798
[ZINK_DESCRIPTOR_TYPE_UBO] = ctx->di.num_ubos[stage],
1799
[ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW] = ctx->di.num_samplers[stage],
1800
[ZINK_DESCRIPTOR_TYPE_SSBO] = ctx->di.num_ssbos[stage],
1801
[ZINK_DESCRIPTOR_TYPE_IMAGE] = ctx->di.num_images[stage]
1802
};
1803
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
1804
for (unsigned j = 0; j < max_slot[i]; j++) {
1805
if (ctx->di.descriptor_res[i][stage][j]) {
1806
struct zink_resource *res = ctx->di.descriptor_res[i][stage][j];
1807
if (!res)
1808
continue;
1809
bool is_write = zink_resource_access_is_write(get_access_flags_for_binding(ctx, i, stage, j));
1810
zink_batch_resource_usage_set(batch, res, is_write);
1811
1812
struct zink_sampler_view *sv = zink_sampler_view(ctx->sampler_views[stage][j]);
1813
struct zink_sampler_state *sampler_state = ctx->sampler_states[stage][j];
1814
struct zink_image_view *iv = &ctx->image_views[stage][j];
1815
if (sampler_state && i == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW && j <= ctx->di.num_samplers[stage])
1816
zink_batch_usage_set(&sampler_state->batch_uses, ctx->batch.state);
1817
if (sv && i == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW && j <= ctx->di.num_sampler_views[stage]) {
1818
if (res->obj->is_buffer)
1819
zink_batch_usage_set(&sv->buffer_view->batch_uses, ctx->batch.state);
1820
else
1821
zink_batch_usage_set(&sv->image_view->batch_uses, ctx->batch.state);
1822
zink_batch_reference_sampler_view(batch, sv);
1823
} else if (i == ZINK_DESCRIPTOR_TYPE_IMAGE && j <= ctx->di.num_images[stage]) {
1824
if (res->obj->is_buffer)
1825
zink_batch_usage_set(&iv->buffer_view->batch_uses, ctx->batch.state);
1826
else
1827
zink_batch_usage_set(&iv->surface->batch_uses, ctx->batch.state);
1828
zink_batch_reference_image_view(batch, iv);
1829
}
1830
}
1831
}
1832
}
1833
}
1834
1835
void
1836
zink_update_descriptor_refs(struct zink_context *ctx, bool compute)
1837
{
1838
struct zink_batch *batch = &ctx->batch;
1839
if (compute) {
1840
update_resource_refs_for_stage(ctx, PIPE_SHADER_COMPUTE);
1841
if (ctx->curr_compute)
1842
zink_batch_reference_program(batch, &ctx->curr_compute->base);
1843
} else {
1844
for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++)
1845
update_resource_refs_for_stage(ctx, i);
1846
unsigned vertex_buffers_enabled_mask = ctx->gfx_pipeline_state.vertex_buffers_enabled_mask;
1847
unsigned last_vbo = util_last_bit(vertex_buffers_enabled_mask);
1848
for (unsigned i = 0; i < last_vbo + 1; i++) {
1849
if (ctx->vertex_buffers[i].buffer.resource)
1850
zink_batch_resource_usage_set(batch, zink_resource(ctx->vertex_buffers[i].buffer.resource), false);
1851
}
1852
if (ctx->curr_program)
1853
zink_batch_reference_program(batch, &ctx->curr_program->base);
1854
}
1855
ctx->descriptor_refs_dirty[compute] = false;
1856
}
1857
1858
static void
1859
flush_batch(struct zink_context *ctx, bool sync)
1860
{
1861
struct zink_batch *batch = &ctx->batch;
1862
if (ctx->clears_enabled)
1863
/* start rp to do all the clears */
1864
zink_begin_render_pass(ctx, batch);
1865
zink_end_render_pass(ctx, batch);
1866
zink_end_batch(ctx, batch);
1867
ctx->deferred_fence = NULL;
1868
1869
if (sync)
1870
sync_flush(ctx, ctx->batch.state);
1871
1872
if (ctx->batch.state->is_device_lost) {
1873
check_device_lost(ctx);
1874
} else {
1875
zink_start_batch(ctx, batch);
1876
if (zink_screen(ctx->base.screen)->info.have_EXT_transform_feedback && ctx->num_so_targets)
1877
ctx->dirty_so_targets = true;
1878
ctx->descriptor_refs_dirty[0] = ctx->descriptor_refs_dirty[1] = true;
1879
ctx->pipeline_changed[0] = ctx->pipeline_changed[1] = true;
1880
ctx->sample_locations_changed |= ctx->gfx_pipeline_state.sample_locations_enabled;
1881
ctx->vertex_buffers_dirty = true;
1882
ctx->vp_state_changed = true;
1883
ctx->scissor_changed = true;
1884
ctx->rast_state_changed = true;
1885
ctx->stencil_ref_changed = true;
1886
ctx->dsa_state_changed = true;
1887
}
1888
}
1889
1890
struct zink_batch *
1891
zink_batch_rp(struct zink_context *ctx)
1892
{
1893
struct zink_batch *batch = &ctx->batch;
1894
if (!batch->in_rp) {
1895
zink_begin_render_pass(ctx, batch);
1896
assert(ctx->framebuffer && ctx->framebuffer->rp);
1897
}
1898
return batch;
1899
}
1900
1901
struct zink_batch *
1902
zink_batch_no_rp(struct zink_context *ctx)
1903
{
1904
struct zink_batch *batch = &ctx->batch;
1905
zink_end_render_pass(ctx, batch);
1906
assert(!batch->in_rp);
1907
return batch;
1908
}
1909
1910
void
1911
zink_flush_queue(struct zink_context *ctx)
1912
{
1913
flush_batch(ctx, true);
1914
}
1915
1916
static bool
1917
rebind_fb_surface(struct zink_context *ctx, struct pipe_surface **surf, struct zink_resource *match_res)
1918
{
1919
if (!*surf)
1920
return false;
1921
struct zink_resource *surf_res = zink_resource((*surf)->texture);
1922
if ((match_res == surf_res) || surf_res->obj != zink_surface(*surf)->obj)
1923
return zink_rebind_surface(ctx, surf);
1924
return false;
1925
}
1926
1927
static bool
1928
rebind_fb_state(struct zink_context *ctx, struct zink_resource *match_res, bool from_set_fb)
1929
{
1930
bool rebind = false;
1931
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
1932
rebind |= rebind_fb_surface(ctx, &ctx->fb_state.cbufs[i], match_res);
1933
if (from_set_fb && ctx->fb_state.cbufs[i] && ctx->fb_state.cbufs[i]->texture->bind & PIPE_BIND_SCANOUT)
1934
ctx->new_swapchain = true;
1935
}
1936
rebind |= rebind_fb_surface(ctx, &ctx->fb_state.zsbuf, match_res);
1937
return rebind;
1938
}
1939
1940
static void
1941
unbind_fb_surface(struct zink_context *ctx, struct pipe_surface *surf, bool changed)
1942
{
1943
if (!surf)
1944
return;
1945
if (changed) {
1946
zink_fb_clears_apply(ctx, surf->texture);
1947
if (zink_batch_usage_exists(zink_surface(surf)->batch_uses))
1948
zink_batch_reference_surface(&ctx->batch, zink_surface(surf));
1949
ctx->rp_changed = true;
1950
}
1951
struct zink_resource *res = zink_resource(surf->texture);
1952
res->fb_binds--;
1953
if (!res->fb_binds)
1954
check_resource_for_batch_ref(ctx, res);
1955
}
1956
1957
static void
1958
zink_set_framebuffer_state(struct pipe_context *pctx,
1959
const struct pipe_framebuffer_state *state)
1960
{
1961
struct zink_context *ctx = zink_context(pctx);
1962
1963
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
1964
struct pipe_surface *surf = ctx->fb_state.cbufs[i];
1965
unbind_fb_surface(ctx, surf, i >= state->nr_cbufs || surf != state->cbufs[i]);
1966
}
1967
if (ctx->fb_state.zsbuf) {
1968
struct pipe_surface *surf = ctx->fb_state.zsbuf;
1969
struct zink_resource *res = zink_resource(surf->texture);
1970
bool changed = surf != state->zsbuf;
1971
unbind_fb_surface(ctx, surf, changed);
1972
if (changed && unlikely(res->obj->needs_zs_evaluate))
1973
/* have to flush zs eval while the sample location data still exists,
1974
* so just throw some random barrier */
1975
zink_resource_image_barrier(ctx, NULL, res, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
1976
VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
1977
}
1978
/* renderpass changes if the number or types of attachments change */
1979
ctx->rp_changed |= ctx->fb_state.nr_cbufs != state->nr_cbufs;
1980
ctx->rp_changed |= !!ctx->fb_state.zsbuf != !!state->zsbuf;
1981
1982
unsigned w = ctx->fb_state.width;
1983
unsigned h = ctx->fb_state.height;
1984
1985
util_copy_framebuffer_state(&ctx->fb_state, state);
1986
unsigned prev_void_alpha_attachments = ctx->gfx_pipeline_state.void_alpha_attachments;
1987
ctx->gfx_pipeline_state.void_alpha_attachments = 0;
1988
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
1989
struct pipe_surface *surf = ctx->fb_state.cbufs[i];
1990
if (surf) {
1991
zink_resource(surf->texture)->fb_binds++;
1992
ctx->gfx_pipeline_state.void_alpha_attachments |= util_format_has_alpha1(surf->format) ? BITFIELD_BIT(i) : 0;
1993
}
1994
}
1995
if (ctx->gfx_pipeline_state.void_alpha_attachments != prev_void_alpha_attachments)
1996
ctx->gfx_pipeline_state.dirty = true;
1997
if (ctx->fb_state.zsbuf) {
1998
struct pipe_surface *surf = ctx->fb_state.zsbuf;
1999
zink_resource(surf->texture)->fb_binds++;
2000
}
2001
if (ctx->fb_state.width != w || ctx->fb_state.height != h)
2002
ctx->scissor_changed = true;
2003
rebind_fb_state(ctx, NULL, true);
2004
/* get_framebuffer adds a ref if the fb is reused or created;
2005
* always do get_framebuffer first to avoid deleting the same fb
2006
* we're about to use
2007
*/
2008
struct zink_framebuffer *fb = get_framebuffer(ctx);
2009
if (ctx->framebuffer) {
2010
struct zink_screen *screen = zink_screen(pctx->screen);
2011
simple_mtx_lock(&screen->framebuffer_mtx);
2012
struct hash_entry *he = _mesa_hash_table_search(&screen->framebuffer_cache, &ctx->framebuffer->state);
2013
if (ctx->framebuffer && !ctx->framebuffer->state.num_attachments) {
2014
/* if this has no attachments then its lifetime has ended */
2015
_mesa_hash_table_remove(&screen->framebuffer_cache, he);
2016
he = NULL;
2017
}
2018
/* a framebuffer loses 1 ref every time we unset it;
2019
* we do NOT add refs here, as the ref has already been added in
2020
* get_framebuffer()
2021
*/
2022
if (zink_framebuffer_reference(screen, &ctx->framebuffer, NULL) && he)
2023
_mesa_hash_table_remove(&screen->framebuffer_cache, he);
2024
simple_mtx_unlock(&screen->framebuffer_mtx);
2025
}
2026
ctx->fb_changed |= ctx->framebuffer != fb;
2027
ctx->framebuffer = fb;
2028
2029
uint8_t rast_samples = util_framebuffer_get_num_samples(state);
2030
/* in vulkan, gl_SampleMask needs to be explicitly ignored for sampleCount == 1 */
2031
if ((ctx->gfx_pipeline_state.rast_samples > 1) != (rast_samples > 1))
2032
ctx->dirty_shader_stages |= 1 << PIPE_SHADER_FRAGMENT;
2033
if (ctx->gfx_pipeline_state.rast_samples != rast_samples) {
2034
ctx->sample_locations_changed |= ctx->gfx_pipeline_state.sample_locations_enabled;
2035
ctx->gfx_pipeline_state.dirty = true;
2036
}
2037
ctx->gfx_pipeline_state.rast_samples = rast_samples;
2038
if (ctx->gfx_pipeline_state.num_attachments != state->nr_cbufs)
2039
ctx->gfx_pipeline_state.dirty = true;
2040
ctx->gfx_pipeline_state.num_attachments = state->nr_cbufs;
2041
2042
/* need to ensure we start a new rp on next draw */
2043
zink_batch_no_rp(ctx);
2044
}
2045
2046
static void
2047
zink_set_blend_color(struct pipe_context *pctx,
2048
const struct pipe_blend_color *color)
2049
{
2050
struct zink_context *ctx = zink_context(pctx);
2051
memcpy(ctx->blend_constants, color->color, sizeof(float) * 4);
2052
}
2053
2054
static void
2055
zink_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
2056
{
2057
struct zink_context *ctx = zink_context(pctx);
2058
ctx->gfx_pipeline_state.sample_mask = sample_mask;
2059
ctx->gfx_pipeline_state.dirty = true;
2060
}
2061
2062
static void
2063
zink_set_sample_locations(struct pipe_context *pctx, size_t size, const uint8_t *locations)
2064
{
2065
struct zink_context *ctx = zink_context(pctx);
2066
2067
ctx->gfx_pipeline_state.sample_locations_enabled = size && locations;
2068
ctx->sample_locations_changed = ctx->gfx_pipeline_state.sample_locations_enabled;
2069
if (size > sizeof(ctx->sample_locations))
2070
size = sizeof(ctx->sample_locations);
2071
memcpy(ctx->sample_locations, locations, size);
2072
}
2073
2074
static VkAccessFlags
2075
access_src_flags(VkImageLayout layout)
2076
{
2077
switch (layout) {
2078
case VK_IMAGE_LAYOUT_UNDEFINED:
2079
return 0;
2080
2081
case VK_IMAGE_LAYOUT_GENERAL:
2082
return VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
2083
2084
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
2085
return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
2086
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
2087
return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
2088
2089
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2090
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
2091
return VK_ACCESS_SHADER_READ_BIT;
2092
2093
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
2094
return VK_ACCESS_TRANSFER_READ_BIT;
2095
2096
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
2097
return VK_ACCESS_TRANSFER_WRITE_BIT;
2098
2099
case VK_IMAGE_LAYOUT_PREINITIALIZED:
2100
return VK_ACCESS_HOST_WRITE_BIT;
2101
2102
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
2103
return 0;
2104
2105
default:
2106
unreachable("unexpected layout");
2107
}
2108
}
2109
2110
static VkAccessFlags
2111
access_dst_flags(VkImageLayout layout)
2112
{
2113
switch (layout) {
2114
case VK_IMAGE_LAYOUT_UNDEFINED:
2115
return 0;
2116
2117
case VK_IMAGE_LAYOUT_GENERAL:
2118
return VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
2119
2120
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
2121
return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2122
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
2123
return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
2124
2125
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
2126
return VK_ACCESS_SHADER_READ_BIT;
2127
2128
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
2129
return VK_ACCESS_TRANSFER_READ_BIT;
2130
2131
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2132
return VK_ACCESS_SHADER_READ_BIT;
2133
2134
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
2135
return VK_ACCESS_TRANSFER_WRITE_BIT;
2136
2137
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
2138
return 0;
2139
2140
default:
2141
unreachable("unexpected layout");
2142
}
2143
}
2144
2145
static VkPipelineStageFlags
2146
pipeline_dst_stage(VkImageLayout layout)
2147
{
2148
switch (layout) {
2149
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
2150
return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
2151
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
2152
return VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
2153
2154
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
2155
return VK_PIPELINE_STAGE_TRANSFER_BIT;
2156
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
2157
return VK_PIPELINE_STAGE_TRANSFER_BIT;
2158
2159
case VK_IMAGE_LAYOUT_GENERAL:
2160
return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
2161
2162
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
2163
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
2164
return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
2165
2166
default:
2167
return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
2168
}
2169
}
2170
2171
#define ALL_READ_ACCESS_FLAGS \
2172
(VK_ACCESS_INDIRECT_COMMAND_READ_BIT | \
2173
VK_ACCESS_INDEX_READ_BIT | \
2174
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | \
2175
VK_ACCESS_UNIFORM_READ_BIT | \
2176
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | \
2177
VK_ACCESS_SHADER_READ_BIT | \
2178
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | \
2179
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | \
2180
VK_ACCESS_TRANSFER_READ_BIT |\
2181
VK_ACCESS_HOST_READ_BIT |\
2182
VK_ACCESS_MEMORY_READ_BIT |\
2183
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT |\
2184
VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT |\
2185
VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT |\
2186
VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR |\
2187
VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV |\
2188
VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT |\
2189
VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV |\
2190
VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV |\
2191
VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV)
2192
2193
2194
bool
2195
zink_resource_access_is_write(VkAccessFlags flags)
2196
{
2197
return (flags & ALL_READ_ACCESS_FLAGS) != flags;
2198
}
2199
2200
bool
2201
zink_resource_image_needs_barrier(struct zink_resource *res, VkImageLayout new_layout, VkAccessFlags flags, VkPipelineStageFlags pipeline)
2202
{
2203
if (!pipeline)
2204
pipeline = pipeline_dst_stage(new_layout);
2205
if (!flags)
2206
flags = access_dst_flags(new_layout);
2207
return res->layout != new_layout || (res->access_stage & pipeline) != pipeline ||
2208
(res->access & flags) != flags ||
2209
zink_resource_access_is_write(res->access) ||
2210
zink_resource_access_is_write(flags);
2211
}
2212
2213
bool
2214
zink_resource_image_barrier_init(VkImageMemoryBarrier *imb, struct zink_resource *res, VkImageLayout new_layout, VkAccessFlags flags, VkPipelineStageFlags pipeline)
2215
{
2216
if (!pipeline)
2217
pipeline = pipeline_dst_stage(new_layout);
2218
if (!flags)
2219
flags = access_dst_flags(new_layout);
2220
2221
VkImageSubresourceRange isr = {
2222
res->aspect,
2223
0, VK_REMAINING_MIP_LEVELS,
2224
0, VK_REMAINING_ARRAY_LAYERS
2225
};
2226
*imb = (VkImageMemoryBarrier){
2227
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2228
NULL,
2229
res->access ? res->access : access_src_flags(res->layout),
2230
flags,
2231
res->layout,
2232
new_layout,
2233
VK_QUEUE_FAMILY_IGNORED,
2234
VK_QUEUE_FAMILY_IGNORED,
2235
res->obj->image,
2236
isr
2237
};
2238
return res->obj->needs_zs_evaluate || zink_resource_image_needs_barrier(res, new_layout, flags, pipeline);
2239
}
2240
2241
static inline bool
2242
is_shader_pipline_stage(VkPipelineStageFlags pipeline)
2243
{
2244
return pipeline & (VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
2245
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
2246
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
2247
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
2248
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
2249
}
2250
2251
static void
2252
resource_check_defer_buffer_barrier(struct zink_context *ctx, struct zink_resource *res, VkPipelineStageFlags pipeline)
2253
{
2254
assert(res->obj->is_buffer);
2255
if (res->bind_count[0]) {
2256
if ((res->obj->is_buffer && res->vbo_bind_count && !(pipeline & VK_PIPELINE_STAGE_VERTEX_INPUT_BIT)) ||
2257
((!res->obj->is_buffer || res->vbo_bind_count != res->bind_count[0]) && !is_shader_pipline_stage(pipeline)))
2258
/* gfx rebind */
2259
_mesa_set_add(ctx->need_barriers[0], res);
2260
}
2261
if (res->bind_count[1] && !(pipeline & VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT))
2262
/* compute rebind */
2263
_mesa_set_add(ctx->need_barriers[1], res);
2264
}
2265
2266
static inline VkCommandBuffer
2267
get_cmdbuf(struct zink_context *ctx, struct zink_resource *res)
2268
{
2269
if ((res->access && !res->unordered_barrier) || !ctx->batch.in_rp) {
2270
struct zink_batch *batch = zink_batch_no_rp(ctx);
2271
assert(!batch->in_rp);
2272
res->unordered_barrier = false;
2273
return batch->state->cmdbuf;
2274
}
2275
res->unordered_barrier = true;
2276
ctx->batch.state->has_barriers = true;
2277
return ctx->batch.state->barrier_cmdbuf;
2278
}
2279
2280
static void
2281
resource_check_defer_image_barrier(struct zink_context *ctx, struct zink_resource *res, VkImageLayout layout, VkPipelineStageFlags pipeline)
2282
{
2283
assert(!res->obj->is_buffer);
2284
2285
bool is_compute = pipeline == VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
2286
/* if this is a non-shader barrier and there are binds, always queue a shader barrier */
2287
bool is_shader = is_shader_pipline_stage(pipeline);
2288
if ((is_shader || !res->bind_count[is_compute]) &&
2289
/* if no layout change is needed between gfx and compute, do nothing */
2290
!res->bind_count[!is_compute] && (!is_compute || !res->fb_binds))
2291
return;
2292
2293
if (res->bind_count[!is_compute] && is_shader) {
2294
/* if the layout is the same between gfx and compute, do nothing */
2295
if (layout == zink_descriptor_util_image_layout_eval(res, !is_compute))
2296
return;
2297
}
2298
/* queue a layout change if a layout change will be needed */
2299
if (res->bind_count[!is_compute])
2300
_mesa_set_add(ctx->need_barriers[!is_compute], res);
2301
/* also queue a layout change if this is a non-shader layout */
2302
if (res->bind_count[is_compute] && !is_shader)
2303
_mesa_set_add(ctx->need_barriers[is_compute], res);
2304
}
2305
2306
void
2307
zink_resource_image_barrier(struct zink_context *ctx, struct zink_batch *batch, struct zink_resource *res,
2308
VkImageLayout new_layout, VkAccessFlags flags, VkPipelineStageFlags pipeline)
2309
{
2310
VkImageMemoryBarrier imb;
2311
if (!pipeline)
2312
pipeline = pipeline_dst_stage(new_layout);
2313
2314
if (!zink_resource_image_barrier_init(&imb, res, new_layout, flags, pipeline))
2315
return;
2316
/* only barrier if we're changing layout or doing something besides read -> read */
2317
VkCommandBuffer cmdbuf = get_cmdbuf(ctx, res);
2318
assert(new_layout);
2319
if (res->obj->needs_zs_evaluate)
2320
imb.pNext = &res->obj->zs_evaluate;
2321
res->obj->needs_zs_evaluate = false;
2322
vkCmdPipelineBarrier(
2323
cmdbuf,
2324
res->access_stage ? res->access_stage : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
2325
pipeline,
2326
0,
2327
0, NULL,
2328
0, NULL,
2329
1, &imb
2330
);
2331
2332
resource_check_defer_image_barrier(ctx, res, new_layout, pipeline);
2333
2334
if (res->unordered_barrier) {
2335
res->access |= imb.dstAccessMask;
2336
res->access_stage |= pipeline;
2337
} else {
2338
res->access = imb.dstAccessMask;
2339
res->access_stage = pipeline;
2340
}
2341
res->layout = new_layout;
2342
}
2343
2344
2345
VkPipelineStageFlags
2346
zink_pipeline_flags_from_stage(VkShaderStageFlagBits stage)
2347
{
2348
switch (stage) {
2349
case VK_SHADER_STAGE_VERTEX_BIT:
2350
return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
2351
case VK_SHADER_STAGE_FRAGMENT_BIT:
2352
return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
2353
case VK_SHADER_STAGE_GEOMETRY_BIT:
2354
return VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
2355
case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
2356
return VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT;
2357
case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
2358
return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
2359
case VK_SHADER_STAGE_COMPUTE_BIT:
2360
return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
2361
default:
2362
unreachable("unknown shader stage bit");
2363
}
2364
}
2365
2366
ALWAYS_INLINE static VkPipelineStageFlags
2367
pipeline_access_stage(VkAccessFlags flags)
2368
{
2369
if (flags & (VK_ACCESS_UNIFORM_READ_BIT |
2370
VK_ACCESS_SHADER_READ_BIT |
2371
VK_ACCESS_SHADER_WRITE_BIT))
2372
return VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV |
2373
VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV |
2374
VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR |
2375
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
2376
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
2377
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
2378
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
2379
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
2380
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
2381
return VK_PIPELINE_STAGE_TRANSFER_BIT;
2382
}
2383
2384
ALWAYS_INLINE static bool
2385
zink_resource_buffer_needs_barrier(struct zink_resource *res, VkAccessFlags flags, VkPipelineStageFlags pipeline)
2386
{
2387
if (!res->access || !res->access_stage)
2388
return true;
2389
if (!pipeline)
2390
pipeline = pipeline_access_stage(flags);
2391
return zink_resource_access_is_write(res->access) ||
2392
zink_resource_access_is_write(flags) ||
2393
((res->access_stage & pipeline) != pipeline && !(res->access_stage & (pipeline - 1))) ||
2394
(res->access & flags) != flags;
2395
}
2396
2397
void
2398
zink_fake_buffer_barrier(struct zink_resource *res, VkAccessFlags flags, VkPipelineStageFlags pipeline)
2399
{
2400
res->access = flags;
2401
res->access_stage = pipeline;
2402
}
2403
2404
void
2405
zink_resource_buffer_barrier(struct zink_context *ctx, struct zink_batch *batch, struct zink_resource *res, VkAccessFlags flags, VkPipelineStageFlags pipeline)
2406
{
2407
VkMemoryBarrier bmb;
2408
if (!pipeline)
2409
pipeline = pipeline_access_stage(flags);
2410
if (!zink_resource_buffer_needs_barrier(res, flags, pipeline))
2411
return;
2412
2413
bmb.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2414
bmb.pNext = NULL;
2415
bmb.srcAccessMask = res->access;
2416
bmb.dstAccessMask = flags;
2417
VkCommandBuffer cmdbuf = get_cmdbuf(ctx, res);
2418
/* only barrier if we're changing layout or doing something besides read -> read */
2419
vkCmdPipelineBarrier(
2420
cmdbuf,
2421
res->access_stage ? res->access_stage : pipeline_access_stage(res->access),
2422
pipeline,
2423
0,
2424
1, &bmb,
2425
0, NULL,
2426
0, NULL
2427
);
2428
2429
resource_check_defer_buffer_barrier(ctx, res, pipeline);
2430
2431
if (res->unordered_barrier) {
2432
res->access |= bmb.dstAccessMask;
2433
res->access_stage |= pipeline;
2434
} else {
2435
res->access = bmb.dstAccessMask;
2436
res->access_stage = pipeline;
2437
}
2438
}
2439
2440
bool
2441
zink_resource_needs_barrier(struct zink_resource *res, VkImageLayout layout, VkAccessFlags flags, VkPipelineStageFlags pipeline)
2442
{
2443
if (res->base.b.target == PIPE_BUFFER)
2444
return zink_resource_buffer_needs_barrier(res, flags, pipeline);
2445
return zink_resource_image_needs_barrier(res, layout, flags, pipeline);
2446
}
2447
2448
void
2449
zink_resource_barrier(struct zink_context *ctx, struct zink_batch *batch, struct zink_resource *res, VkImageLayout layout, VkAccessFlags flags, VkPipelineStageFlags pipeline)
2450
{
2451
if (res->base.b.target == PIPE_BUFFER)
2452
zink_resource_buffer_barrier(ctx, batch, res, flags, pipeline);
2453
else
2454
zink_resource_image_barrier(ctx, batch, res, layout, flags, pipeline);
2455
}
2456
2457
VkShaderStageFlagBits
2458
zink_shader_stage(enum pipe_shader_type type)
2459
{
2460
VkShaderStageFlagBits stages[] = {
2461
[PIPE_SHADER_VERTEX] = VK_SHADER_STAGE_VERTEX_BIT,
2462
[PIPE_SHADER_FRAGMENT] = VK_SHADER_STAGE_FRAGMENT_BIT,
2463
[PIPE_SHADER_GEOMETRY] = VK_SHADER_STAGE_GEOMETRY_BIT,
2464
[PIPE_SHADER_TESS_CTRL] = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
2465
[PIPE_SHADER_TESS_EVAL] = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
2466
[PIPE_SHADER_COMPUTE] = VK_SHADER_STAGE_COMPUTE_BIT,
2467
};
2468
return stages[type];
2469
}
2470
2471
static uint32_t
2472
hash_gfx_program(const void *key)
2473
{
2474
return _mesa_hash_data(key, sizeof(struct zink_shader *) * (ZINK_SHADER_COUNT));
2475
}
2476
2477
static bool
2478
equals_gfx_program(const void *a, const void *b)
2479
{
2480
return memcmp(a, b, sizeof(struct zink_shader *) * (ZINK_SHADER_COUNT)) == 0;
2481
}
2482
2483
static void
2484
zink_flush(struct pipe_context *pctx,
2485
struct pipe_fence_handle **pfence,
2486
unsigned flags)
2487
{
2488
struct zink_context *ctx = zink_context(pctx);
2489
bool deferred = flags & PIPE_FLUSH_DEFERRED;
2490
bool deferred_fence = false;
2491
struct zink_batch *batch = &ctx->batch;
2492
struct zink_fence *fence = NULL;
2493
struct zink_screen *screen = zink_screen(ctx->base.screen);
2494
unsigned submit_count = 0;
2495
2496
/* triggering clears will force has_work */
2497
if (!deferred && ctx->clears_enabled)
2498
/* start rp to do all the clears */
2499
zink_begin_render_pass(ctx, batch);
2500
2501
if (!batch->has_work) {
2502
if (pfence) {
2503
/* reuse last fence */
2504
fence = ctx->last_fence;
2505
}
2506
if (!deferred) {
2507
struct zink_batch_state *last = zink_batch_state(ctx->last_fence);
2508
if (last) {
2509
sync_flush(ctx, last);
2510
if (last->is_device_lost)
2511
check_device_lost(ctx);
2512
}
2513
}
2514
tc_driver_internal_flush_notify(ctx->tc);
2515
} else {
2516
fence = &batch->state->fence;
2517
submit_count = batch->state->submit_count;
2518
if (deferred && !(flags & PIPE_FLUSH_FENCE_FD) && pfence)
2519
deferred_fence = true;
2520
else
2521
flush_batch(ctx, true);
2522
}
2523
2524
if (pfence) {
2525
struct zink_tc_fence *mfence;
2526
2527
if (flags & TC_FLUSH_ASYNC) {
2528
mfence = zink_tc_fence(*pfence);
2529
assert(mfence);
2530
} else {
2531
mfence = zink_create_tc_fence();
2532
2533
screen->base.fence_reference(&screen->base, pfence, NULL);
2534
*pfence = (struct pipe_fence_handle *)mfence;
2535
}
2536
2537
struct zink_batch_state *bs = zink_batch_state(fence);
2538
zink_batch_state_reference(screen, NULL, bs);
2539
mfence->fence = fence;
2540
if (fence)
2541
mfence->submit_count = submit_count;
2542
2543
if (deferred_fence) {
2544
assert(fence);
2545
mfence->deferred_ctx = pctx;
2546
assert(!ctx->deferred_fence || ctx->deferred_fence == fence);
2547
ctx->deferred_fence = fence;
2548
}
2549
2550
if (!fence || flags & TC_FLUSH_ASYNC) {
2551
if (!util_queue_fence_is_signalled(&mfence->ready))
2552
util_queue_fence_signal(&mfence->ready);
2553
}
2554
}
2555
if (fence) {
2556
if (!(flags & (PIPE_FLUSH_DEFERRED | PIPE_FLUSH_ASYNC)))
2557
sync_flush(ctx, zink_batch_state(fence));
2558
2559
if (flags & PIPE_FLUSH_END_OF_FRAME && !(flags & TC_FLUSH_ASYNC) && !deferred) {
2560
/* if the first frame has not yet occurred, we need an explicit fence here
2561
* in some cases in order to correctly draw the first frame, though it's
2562
* unknown at this time why this is the case
2563
*/
2564
if (!ctx->first_frame_done)
2565
zink_vkfence_wait(screen, fence, PIPE_TIMEOUT_INFINITE);
2566
ctx->first_frame_done = true;
2567
}
2568
}
2569
}
2570
2571
void
2572
zink_maybe_flush_or_stall(struct zink_context *ctx)
2573
{
2574
struct zink_screen *screen = zink_screen(ctx->base.screen);
2575
/* flush anytime our total batch memory usage is potentially >= 50% of total video memory */
2576
if (ctx->batch.state->resource_size >= screen->total_video_mem / 2 ||
2577
/* or if there's >100k draws+computes */
2578
ctx->batch.state->draw_count + ctx->batch.state->compute_count >= 100000)
2579
flush_batch(ctx, true);
2580
2581
if (ctx->resource_size >= screen->total_video_mem / 2 || _mesa_hash_table_num_entries(&ctx->batch_states) > 100) {
2582
sync_flush(ctx, zink_batch_state(ctx->last_fence));
2583
zink_vkfence_wait(screen, ctx->last_fence, PIPE_TIMEOUT_INFINITE);
2584
zink_batch_reset_all(ctx);
2585
}
2586
}
2587
2588
void
2589
zink_fence_wait(struct pipe_context *pctx)
2590
{
2591
struct zink_context *ctx = zink_context(pctx);
2592
2593
if (ctx->batch.has_work)
2594
pctx->flush(pctx, NULL, PIPE_FLUSH_HINT_FINISH);
2595
if (ctx->last_fence) {
2596
sync_flush(ctx, zink_batch_state(ctx->last_fence));
2597
zink_vkfence_wait(zink_screen(ctx->base.screen), ctx->last_fence, PIPE_TIMEOUT_INFINITE);
2598
zink_batch_reset_all(ctx);
2599
}
2600
}
2601
2602
void
2603
zink_wait_on_batch(struct zink_context *ctx, uint32_t batch_id)
2604
{
2605
struct zink_batch_state *bs = ctx->batch.state;
2606
assert(bs);
2607
if (!batch_id || bs->fence.batch_id == batch_id)
2608
/* not submitted yet */
2609
flush_batch(ctx, true);
2610
if (ctx->have_timelines) {
2611
if (!zink_screen_timeline_wait(zink_screen(ctx->base.screen), batch_id, UINT64_MAX))
2612
check_device_lost(ctx);
2613
return;
2614
}
2615
simple_mtx_lock(&ctx->batch_mtx);
2616
struct zink_fence *fence;
2617
2618
assert(batch_id || ctx->last_fence);
2619
if (ctx->last_fence && (!batch_id || batch_id == zink_batch_state(ctx->last_fence)->fence.batch_id))
2620
fence = ctx->last_fence;
2621
else {
2622
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&ctx->batch_states, batch_id, (void*)(uintptr_t)batch_id);
2623
if (!he) {
2624
simple_mtx_unlock(&ctx->batch_mtx);
2625
/* if we can't find it, it either must have finished already or is on a different context */
2626
if (!zink_screen_check_last_finished(zink_screen(ctx->base.screen), batch_id)) {
2627
/* if it hasn't finished, it's on another context, so force a flush so there's something to wait on */
2628
ctx->batch.has_work = true;
2629
zink_fence_wait(&ctx->base);
2630
}
2631
return;
2632
}
2633
fence = he->data;
2634
}
2635
simple_mtx_unlock(&ctx->batch_mtx);
2636
assert(fence);
2637
sync_flush(ctx, zink_batch_state(fence));
2638
zink_vkfence_wait(zink_screen(ctx->base.screen), fence, PIPE_TIMEOUT_INFINITE);
2639
}
2640
2641
bool
2642
zink_check_batch_completion(struct zink_context *ctx, uint32_t batch_id)
2643
{
2644
assert(ctx->batch.state);
2645
if (!batch_id)
2646
/* not submitted yet */
2647
return false;
2648
2649
if (zink_screen_check_last_finished(zink_screen(ctx->base.screen), batch_id))
2650
return true;
2651
2652
if (ctx->have_timelines) {
2653
bool success = zink_screen_timeline_wait(zink_screen(ctx->base.screen), batch_id, 0);
2654
if (!success)
2655
check_device_lost(ctx);
2656
return success;
2657
}
2658
struct zink_fence *fence;
2659
2660
simple_mtx_lock(&ctx->batch_mtx);
2661
2662
if (ctx->last_fence && batch_id == zink_batch_state(ctx->last_fence)->fence.batch_id)
2663
fence = ctx->last_fence;
2664
else {
2665
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(&ctx->batch_states, batch_id, (void*)(uintptr_t)batch_id);
2666
/* if we can't find it, it either must have finished already or is on a different context */
2667
if (!he) {
2668
simple_mtx_unlock(&ctx->batch_mtx);
2669
/* return compare against last_finished, since this has info from all contexts */
2670
return zink_screen_check_last_finished(zink_screen(ctx->base.screen), batch_id);
2671
}
2672
fence = he->data;
2673
}
2674
simple_mtx_unlock(&ctx->batch_mtx);
2675
assert(fence);
2676
if (zink_screen(ctx->base.screen)->threaded &&
2677
!util_queue_fence_is_signalled(&zink_batch_state(fence)->flush_completed))
2678
return false;
2679
return zink_vkfence_wait(zink_screen(ctx->base.screen), fence, 0);
2680
}
2681
2682
static void
2683
zink_texture_barrier(struct pipe_context *pctx, unsigned flags)
2684
{
2685
struct zink_context *ctx = zink_context(pctx);
2686
if (!ctx->framebuffer || !ctx->framebuffer->state.num_attachments)
2687
return;
2688
2689
VkMemoryBarrier bmb;
2690
bmb.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2691
bmb.pNext = NULL;
2692
bmb.srcAccessMask = 0;
2693
bmb.dstAccessMask = 0;
2694
struct zink_surface *surf = zink_surface(ctx->framebuffer->surfaces[ctx->framebuffer->state.num_attachments - 1]);
2695
struct zink_resource *res = zink_resource(surf->base.texture);
2696
zink_batch_no_rp(ctx);
2697
if (res->aspect != VK_IMAGE_ASPECT_COLOR_BIT) {
2698
VkMemoryBarrier dmb;
2699
dmb.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2700
dmb.pNext = NULL;
2701
dmb.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
2702
dmb.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
2703
vkCmdPipelineBarrier(
2704
ctx->batch.state->cmdbuf,
2705
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
2706
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
2707
0,
2708
1, &dmb,
2709
0, NULL,
2710
0, NULL
2711
);
2712
} else {
2713
bmb.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2714
bmb.dstAccessMask |= VK_ACCESS_SHADER_READ_BIT;
2715
}
2716
if (ctx->framebuffer->state.num_attachments > 1) {
2717
bmb.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
2718
bmb.dstAccessMask |= VK_ACCESS_SHADER_READ_BIT;
2719
}
2720
if (bmb.srcAccessMask)
2721
vkCmdPipelineBarrier(
2722
ctx->batch.state->cmdbuf,
2723
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2724
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
2725
0,
2726
1, &bmb,
2727
0, NULL,
2728
0, NULL
2729
);
2730
}
2731
2732
static inline void
2733
mem_barrier(struct zink_batch *batch, VkPipelineStageFlags src_stage, VkPipelineStageFlags dst_stage, VkAccessFlags src, VkAccessFlags dst)
2734
{
2735
VkMemoryBarrier mb;
2736
mb.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2737
mb.pNext = NULL;
2738
mb.srcAccessMask = src;
2739
mb.dstAccessMask = dst;
2740
vkCmdPipelineBarrier(batch->state->cmdbuf, src_stage, dst_stage, 0, 1, &mb, 0, NULL, 0, NULL);
2741
}
2742
2743
static void
2744
zink_memory_barrier(struct pipe_context *pctx, unsigned flags)
2745
{
2746
struct zink_context *ctx = zink_context(pctx);
2747
2748
VkPipelineStageFlags all_flags = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
2749
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
2750
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
2751
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT |
2752
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
2753
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
2754
2755
if (!(flags & ~PIPE_BARRIER_UPDATE))
2756
return;
2757
2758
struct zink_batch *batch = &ctx->batch;
2759
zink_end_render_pass(ctx, batch);
2760
2761
if (flags & PIPE_BARRIER_MAPPED_BUFFER) {
2762
/* TODO: this should flush all persistent buffers in use as I think */
2763
}
2764
2765
if (flags & (PIPE_BARRIER_TEXTURE | PIPE_BARRIER_SHADER_BUFFER | PIPE_BARRIER_IMAGE))
2766
mem_barrier(batch, all_flags, all_flags, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
2767
2768
if (flags & PIPE_BARRIER_QUERY_BUFFER)
2769
mem_barrier(batch, all_flags, VK_PIPELINE_STAGE_TRANSFER_BIT,
2770
VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT);
2771
2772
if (flags & PIPE_BARRIER_VERTEX_BUFFER)
2773
mem_barrier(batch, all_flags, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
2774
VK_ACCESS_SHADER_WRITE_BIT,
2775
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
2776
2777
if (flags & PIPE_BARRIER_INDEX_BUFFER)
2778
mem_barrier(batch, all_flags, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
2779
VK_ACCESS_SHADER_WRITE_BIT,
2780
VK_ACCESS_INDEX_READ_BIT);
2781
2782
if (flags & PIPE_BARRIER_CONSTANT_BUFFER)
2783
mem_barrier(batch, all_flags, all_flags,
2784
VK_ACCESS_SHADER_WRITE_BIT,
2785
VK_ACCESS_UNIFORM_READ_BIT);
2786
2787
if (flags & PIPE_BARRIER_INDIRECT_BUFFER)
2788
mem_barrier(batch, all_flags, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
2789
VK_ACCESS_SHADER_WRITE_BIT,
2790
VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
2791
2792
if (flags & PIPE_BARRIER_FRAMEBUFFER)
2793
zink_texture_barrier(pctx, 0);
2794
if (flags & PIPE_BARRIER_STREAMOUT_BUFFER)
2795
mem_barrier(batch, all_flags,
2796
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
2797
VK_ACCESS_SHADER_WRITE_BIT,
2798
VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT |
2799
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT);
2800
}
2801
2802
static void
2803
zink_flush_resource(struct pipe_context *pctx,
2804
struct pipe_resource *pres)
2805
{
2806
struct zink_context *ctx = zink_context(pctx);
2807
/* TODO: this is not futureproof and should be updated once proper
2808
* WSI support is added
2809
*/
2810
if (pres->bind & (PIPE_BIND_SHARED | PIPE_BIND_SCANOUT))
2811
pipe_resource_reference(&ctx->batch.state->flush_res, pres);
2812
}
2813
2814
void
2815
zink_copy_buffer(struct zink_context *ctx, struct zink_batch *batch, struct zink_resource *dst, struct zink_resource *src,
2816
unsigned dst_offset, unsigned src_offset, unsigned size)
2817
{
2818
VkBufferCopy region;
2819
region.srcOffset = src_offset;
2820
region.dstOffset = dst_offset;
2821
region.size = size;
2822
2823
if (!batch)
2824
batch = zink_batch_no_rp(ctx);
2825
assert(!batch->in_rp);
2826
zink_batch_reference_resource_rw(batch, src, false);
2827
zink_batch_reference_resource_rw(batch, dst, true);
2828
util_range_add(&dst->base.b, &dst->valid_buffer_range, dst_offset, dst_offset + size);
2829
zink_resource_buffer_barrier(ctx, batch, src, VK_ACCESS_TRANSFER_READ_BIT, 0);
2830
zink_resource_buffer_barrier(ctx, batch, dst, VK_ACCESS_TRANSFER_WRITE_BIT, 0);
2831
vkCmdCopyBuffer(batch->state->cmdbuf, src->obj->buffer, dst->obj->buffer, 1, &region);
2832
}
2833
2834
void
2835
zink_copy_image_buffer(struct zink_context *ctx, struct zink_batch *batch, struct zink_resource *dst, struct zink_resource *src,
2836
unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz,
2837
unsigned src_level, const struct pipe_box *src_box, enum pipe_map_flags map_flags)
2838
{
2839
struct zink_resource *img = dst->base.b.target == PIPE_BUFFER ? src : dst;
2840
struct zink_resource *buf = dst->base.b.target == PIPE_BUFFER ? dst : src;
2841
2842
if (!batch)
2843
batch = zink_batch_no_rp(ctx);
2844
2845
bool buf2img = buf == src;
2846
2847
if (buf2img) {
2848
zink_resource_image_barrier(ctx, batch, img, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0);
2849
zink_resource_buffer_barrier(ctx, batch, buf, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
2850
} else {
2851
zink_resource_image_barrier(ctx, batch, img, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0, 0);
2852
zink_resource_buffer_barrier(ctx, batch, buf, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
2853
util_range_add(&dst->base.b, &dst->valid_buffer_range, dstx, dstx + src_box->width);
2854
}
2855
2856
VkBufferImageCopy region = {0};
2857
region.bufferOffset = buf2img ? src_box->x : dstx;
2858
region.bufferRowLength = 0;
2859
region.bufferImageHeight = 0;
2860
region.imageSubresource.mipLevel = buf2img ? dst_level : src_level;
2861
switch (img->base.b.target) {
2862
case PIPE_TEXTURE_CUBE:
2863
case PIPE_TEXTURE_CUBE_ARRAY:
2864
case PIPE_TEXTURE_2D_ARRAY:
2865
case PIPE_TEXTURE_1D_ARRAY:
2866
/* these use layer */
2867
region.imageSubresource.baseArrayLayer = buf2img ? dstz : src_box->z;
2868
region.imageSubresource.layerCount = src_box->depth;
2869
region.imageOffset.z = 0;
2870
region.imageExtent.depth = 1;
2871
break;
2872
case PIPE_TEXTURE_3D:
2873
/* this uses depth */
2874
region.imageSubresource.baseArrayLayer = 0;
2875
region.imageSubresource.layerCount = 1;
2876
region.imageOffset.z = buf2img ? dstz : src_box->z;
2877
region.imageExtent.depth = src_box->depth;
2878
break;
2879
default:
2880
/* these must only copy one layer */
2881
region.imageSubresource.baseArrayLayer = 0;
2882
region.imageSubresource.layerCount = 1;
2883
region.imageOffset.z = 0;
2884
region.imageExtent.depth = 1;
2885
}
2886
region.imageOffset.x = buf2img ? dstx : src_box->x;
2887
region.imageOffset.y = buf2img ? dsty : src_box->y;
2888
2889
region.imageExtent.width = src_box->width;
2890
region.imageExtent.height = src_box->height;
2891
2892
zink_batch_reference_resource_rw(batch, img, buf2img);
2893
zink_batch_reference_resource_rw(batch, buf, !buf2img);
2894
2895
/* we're using u_transfer_helper_deinterleave, which means we'll be getting PIPE_MAP_* usage
2896
* to indicate whether to copy either the depth or stencil aspects
2897
*/
2898
unsigned aspects = 0;
2899
if (map_flags) {
2900
assert((map_flags & (PIPE_MAP_DEPTH_ONLY | PIPE_MAP_STENCIL_ONLY)) !=
2901
(PIPE_MAP_DEPTH_ONLY | PIPE_MAP_STENCIL_ONLY));
2902
if (map_flags & PIPE_MAP_DEPTH_ONLY)
2903
aspects = VK_IMAGE_ASPECT_DEPTH_BIT;
2904
else if (map_flags & PIPE_MAP_STENCIL_ONLY)
2905
aspects = VK_IMAGE_ASPECT_STENCIL_BIT;
2906
}
2907
if (!aspects)
2908
aspects = img->aspect;
2909
while (aspects) {
2910
int aspect = 1 << u_bit_scan(&aspects);
2911
region.imageSubresource.aspectMask = aspect;
2912
2913
/* this may or may not work with multisampled depth/stencil buffers depending on the driver implementation:
2914
*
2915
* srcImage must have a sample count equal to VK_SAMPLE_COUNT_1_BIT
2916
* - vkCmdCopyImageToBuffer spec
2917
*
2918
* dstImage must have a sample count equal to VK_SAMPLE_COUNT_1_BIT
2919
* - vkCmdCopyBufferToImage spec
2920
*/
2921
if (buf2img)
2922
vkCmdCopyBufferToImage(batch->state->cmdbuf, buf->obj->buffer, img->obj->image, img->layout, 1, &region);
2923
else
2924
vkCmdCopyImageToBuffer(batch->state->cmdbuf, img->obj->image, img->layout, buf->obj->buffer, 1, &region);
2925
}
2926
}
2927
2928
static void
2929
zink_resource_copy_region(struct pipe_context *pctx,
2930
struct pipe_resource *pdst,
2931
unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz,
2932
struct pipe_resource *psrc,
2933
unsigned src_level, const struct pipe_box *src_box)
2934
{
2935
struct zink_resource *dst = zink_resource(pdst);
2936
struct zink_resource *src = zink_resource(psrc);
2937
struct zink_context *ctx = zink_context(pctx);
2938
if (dst->base.b.target != PIPE_BUFFER && src->base.b.target != PIPE_BUFFER) {
2939
VkImageCopy region = {0};
2940
if (util_format_get_num_planes(src->base.b.format) == 1 &&
2941
util_format_get_num_planes(dst->base.b.format) == 1) {
2942
/* If neither the calling command’s srcImage nor the calling command’s dstImage
2943
* has a multi-planar image format then the aspectMask member of srcSubresource
2944
* and dstSubresource must match
2945
*
2946
* -VkImageCopy spec
2947
*/
2948
assert(src->aspect == dst->aspect);
2949
} else
2950
unreachable("planar formats not yet handled");
2951
2952
zink_fb_clears_apply_or_discard(ctx, pdst, (struct u_rect){dstx, dstx + src_box->width, dsty, dsty + src_box->height}, false);
2953
zink_fb_clears_apply_region(ctx, psrc, zink_rect_from_box(src_box));
2954
2955
region.srcSubresource.aspectMask = src->aspect;
2956
region.srcSubresource.mipLevel = src_level;
2957
switch (src->base.b.target) {
2958
case PIPE_TEXTURE_CUBE:
2959
case PIPE_TEXTURE_CUBE_ARRAY:
2960
case PIPE_TEXTURE_2D_ARRAY:
2961
case PIPE_TEXTURE_1D_ARRAY:
2962
/* these use layer */
2963
region.srcSubresource.baseArrayLayer = src_box->z;
2964
region.srcSubresource.layerCount = src_box->depth;
2965
region.srcOffset.z = 0;
2966
region.extent.depth = 1;
2967
break;
2968
case PIPE_TEXTURE_3D:
2969
/* this uses depth */
2970
region.srcSubresource.baseArrayLayer = 0;
2971
region.srcSubresource.layerCount = 1;
2972
region.srcOffset.z = src_box->z;
2973
region.extent.depth = src_box->depth;
2974
break;
2975
default:
2976
/* these must only copy one layer */
2977
region.srcSubresource.baseArrayLayer = 0;
2978
region.srcSubresource.layerCount = 1;
2979
region.srcOffset.z = 0;
2980
region.extent.depth = 1;
2981
}
2982
2983
region.srcOffset.x = src_box->x;
2984
region.srcOffset.y = src_box->y;
2985
2986
region.dstSubresource.aspectMask = dst->aspect;
2987
region.dstSubresource.mipLevel = dst_level;
2988
switch (dst->base.b.target) {
2989
case PIPE_TEXTURE_CUBE:
2990
case PIPE_TEXTURE_CUBE_ARRAY:
2991
case PIPE_TEXTURE_2D_ARRAY:
2992
case PIPE_TEXTURE_1D_ARRAY:
2993
/* these use layer */
2994
region.dstSubresource.baseArrayLayer = dstz;
2995
region.dstSubresource.layerCount = src_box->depth;
2996
region.dstOffset.z = 0;
2997
break;
2998
case PIPE_TEXTURE_3D:
2999
/* this uses depth */
3000
region.dstSubresource.baseArrayLayer = 0;
3001
region.dstSubresource.layerCount = 1;
3002
region.dstOffset.z = dstz;
3003
break;
3004
default:
3005
/* these must only copy one layer */
3006
region.dstSubresource.baseArrayLayer = 0;
3007
region.dstSubresource.layerCount = 1;
3008
region.dstOffset.z = 0;
3009
}
3010
3011
region.dstOffset.x = dstx;
3012
region.dstOffset.y = dsty;
3013
region.extent.width = src_box->width;
3014
region.extent.height = src_box->height;
3015
3016
struct zink_batch *batch = zink_batch_no_rp(ctx);
3017
zink_batch_reference_resource_rw(batch, src, false);
3018
zink_batch_reference_resource_rw(batch, dst, true);
3019
3020
zink_resource_setup_transfer_layouts(ctx, src, dst);
3021
vkCmdCopyImage(batch->state->cmdbuf, src->obj->image, src->layout,
3022
dst->obj->image, dst->layout,
3023
1, &region);
3024
} else if (dst->base.b.target == PIPE_BUFFER &&
3025
src->base.b.target == PIPE_BUFFER) {
3026
zink_copy_buffer(ctx, NULL, dst, src, dstx, src_box->x, src_box->width);
3027
} else
3028
zink_copy_image_buffer(ctx, NULL, dst, src, dst_level, dstx, dsty, dstz, src_level, src_box, 0);
3029
}
3030
3031
static struct pipe_stream_output_target *
3032
zink_create_stream_output_target(struct pipe_context *pctx,
3033
struct pipe_resource *pres,
3034
unsigned buffer_offset,
3035
unsigned buffer_size)
3036
{
3037
struct zink_so_target *t;
3038
t = CALLOC_STRUCT(zink_so_target);
3039
if (!t)
3040
return NULL;
3041
3042
/* using PIPE_BIND_CUSTOM here lets us create a custom pipe buffer resource,
3043
* which allows us to differentiate and use VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT
3044
* as we must for this case
3045
*/
3046
t->counter_buffer = pipe_buffer_create(pctx->screen, PIPE_BIND_STREAM_OUTPUT | PIPE_BIND_CUSTOM, PIPE_USAGE_DEFAULT, 4);
3047
if (!t->counter_buffer) {
3048
FREE(t);
3049
return NULL;
3050
}
3051
3052
t->base.reference.count = 1;
3053
t->base.context = pctx;
3054
pipe_resource_reference(&t->base.buffer, pres);
3055
t->base.buffer_offset = buffer_offset;
3056
t->base.buffer_size = buffer_size;
3057
3058
zink_resource(t->base.buffer)->bind_history |= ZINK_RESOURCE_USAGE_STREAMOUT;
3059
3060
return &t->base;
3061
}
3062
3063
static void
3064
zink_stream_output_target_destroy(struct pipe_context *pctx,
3065
struct pipe_stream_output_target *psot)
3066
{
3067
struct zink_so_target *t = (struct zink_so_target *)psot;
3068
pipe_resource_reference(&t->counter_buffer, NULL);
3069
pipe_resource_reference(&t->base.buffer, NULL);
3070
FREE(t);
3071
}
3072
3073
static void
3074
zink_set_stream_output_targets(struct pipe_context *pctx,
3075
unsigned num_targets,
3076
struct pipe_stream_output_target **targets,
3077
const unsigned *offsets)
3078
{
3079
struct zink_context *ctx = zink_context(pctx);
3080
3081
if (num_targets == 0) {
3082
for (unsigned i = 0; i < ctx->num_so_targets; i++)
3083
pipe_so_target_reference(&ctx->so_targets[i], NULL);
3084
ctx->num_so_targets = 0;
3085
} else {
3086
for (unsigned i = 0; i < num_targets; i++) {
3087
struct zink_so_target *t = zink_so_target(targets[i]);
3088
pipe_so_target_reference(&ctx->so_targets[i], targets[i]);
3089
if (!t)
3090
continue;
3091
struct zink_resource *res = zink_resource(t->counter_buffer);
3092
if (offsets[0] == (unsigned)-1)
3093
ctx->xfb_barrier |= zink_resource_buffer_needs_barrier(res,
3094
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,
3095
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
3096
else
3097
ctx->xfb_barrier |= zink_resource_buffer_needs_barrier(res,
3098
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,
3099
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT);
3100
}
3101
for (unsigned i = num_targets; i < ctx->num_so_targets; i++)
3102
pipe_so_target_reference(&ctx->so_targets[i], NULL);
3103
ctx->num_so_targets = num_targets;
3104
3105
/* TODO: possibly avoid rebinding on resume if resuming from same buffers? */
3106
ctx->dirty_so_targets = true;
3107
}
3108
}
3109
3110
void
3111
zink_rebind_framebuffer(struct zink_context *ctx, struct zink_resource *res)
3112
{
3113
if (!ctx->framebuffer)
3114
return;
3115
for (unsigned i = 0; i < ctx->framebuffer->state.num_attachments; i++) {
3116
if (!ctx->framebuffer->surfaces[i] ||
3117
zink_resource(ctx->framebuffer->surfaces[i]->texture) != res)
3118
continue;
3119
zink_rebind_surface(ctx, &ctx->framebuffer->surfaces[i]);
3120
zink_batch_no_rp(ctx);
3121
}
3122
if (rebind_fb_state(ctx, res, false))
3123
zink_batch_no_rp(ctx);
3124
}
3125
3126
static void
3127
rebind_buffer(struct zink_context *ctx, struct zink_resource *res)
3128
{
3129
const unsigned total_rebinds = res->bind_count[0] + res->bind_count[1];
3130
unsigned num_rebinds = 0, num_image_rebinds_remaining[2] = {res->image_bind_count[0], res->image_bind_count[1]};
3131
bool has_write = false;
3132
3133
if (res->vbo_bind_count) {
3134
ctx->vertex_buffers_dirty = true;
3135
num_rebinds += res->vbo_bind_count;
3136
}
3137
for (unsigned shader = 0; num_rebinds < total_rebinds && shader < PIPE_SHADER_TYPES; shader++) {
3138
u_foreach_bit(slot, res->ubo_bind_mask[shader]) {
3139
if (&res->base.b != ctx->ubos[shader][slot].buffer) //wrong context
3140
return;
3141
3142
update_descriptor_state_ubo(ctx, shader, slot);
3143
zink_screen(ctx->base.screen)->context_invalidate_descriptor_state(ctx, shader, ZINK_DESCRIPTOR_TYPE_UBO, slot, 1);
3144
num_rebinds++;
3145
}
3146
u_foreach_bit(slot, res->ssbo_bind_mask[shader]) {
3147
struct pipe_shader_buffer *ssbo = &ctx->ssbos[shader][slot];
3148
if (&res->base.b != ssbo->buffer) //wrong context
3149
return;
3150
3151
has_write |= ctx->writable_ssbos[shader] & BITFIELD64_BIT(slot);
3152
util_range_add(&res->base.b, &res->valid_buffer_range, ssbo->buffer_offset,
3153
ssbo->buffer_offset + ssbo->buffer_size);
3154
update_descriptor_state_ssbo(ctx, shader, slot);
3155
zink_screen(ctx->base.screen)->context_invalidate_descriptor_state(ctx, shader, ZINK_DESCRIPTOR_TYPE_SSBO, slot, 1);
3156
num_rebinds++;
3157
}
3158
u_foreach_bit(slot, res->sampler_binds[shader]) {
3159
struct zink_sampler_view *sampler_view = zink_sampler_view(ctx->sampler_views[shader][slot]);
3160
if (&res->base.b != sampler_view->base.texture) //wrong context
3161
return;
3162
3163
if (zink_batch_usage_exists(sampler_view->buffer_view->batch_uses))
3164
zink_batch_reference_bufferview(&ctx->batch, sampler_view->buffer_view);
3165
zink_buffer_view_reference(zink_screen(ctx->base.screen), &sampler_view->buffer_view, NULL);
3166
sampler_view->buffer_view = get_buffer_view(ctx, res, sampler_view->base.format,
3167
sampler_view->base.u.buf.offset, sampler_view->base.u.buf.size);
3168
update_descriptor_state_sampler(ctx, shader, slot);
3169
zink_screen(ctx->base.screen)->context_invalidate_descriptor_state(ctx, shader, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW, slot, 1);
3170
num_rebinds++;
3171
}
3172
if (unlikely(num_image_rebinds_remaining[shader == PIPE_SHADER_COMPUTE])) {
3173
for (unsigned slot = 0; num_image_rebinds_remaining[shader == PIPE_SHADER_COMPUTE] &&
3174
slot < ctx->di.num_images[shader]; slot++) {
3175
struct zink_resource *cres = zink_get_resource_for_descriptor(ctx, ZINK_DESCRIPTOR_TYPE_IMAGE, shader, slot);
3176
if (res != cres)
3177
continue;
3178
3179
struct zink_image_view *image_view = &ctx->image_views[shader][slot];
3180
zink_descriptor_set_refs_clear(&image_view->buffer_view->desc_set_refs, image_view->buffer_view);
3181
if (zink_batch_usage_exists(image_view->buffer_view->batch_uses))
3182
zink_batch_reference_bufferview(&ctx->batch, image_view->buffer_view);
3183
zink_buffer_view_reference(zink_screen(ctx->base.screen), &image_view->buffer_view, NULL);
3184
if (!zink_resource_object_init_storage(ctx, res)) {
3185
debug_printf("couldn't create storage image!");
3186
continue;
3187
}
3188
has_write |= image_view->base.access & PIPE_IMAGE_ACCESS_WRITE;
3189
image_view->buffer_view = get_buffer_view(ctx, res, image_view->base.format,
3190
image_view->base.u.buf.offset, image_view->base.u.buf.size);
3191
assert(image_view->buffer_view);
3192
util_range_add(&res->base.b, &res->valid_buffer_range, image_view->base.u.buf.offset,
3193
image_view->base.u.buf.offset + image_view->base.u.buf.size);
3194
update_descriptor_state_image(ctx, shader, slot);
3195
zink_screen(ctx->base.screen)->context_invalidate_descriptor_state(ctx, shader, ZINK_DESCRIPTOR_TYPE_IMAGE, slot, 1);
3196
num_image_rebinds_remaining[shader == PIPE_SHADER_COMPUTE]--;
3197
}
3198
}
3199
}
3200
zink_batch_resource_usage_set(&ctx->batch, res, has_write);
3201
}
3202
3203
static inline struct zink_screen **
3204
get_screen_ptr_for_commit(uint8_t *mem)
3205
{
3206
return (struct zink_screen**)(mem + sizeof(VkBindSparseInfo) + sizeof(VkSparseBufferMemoryBindInfo) + sizeof(VkSparseMemoryBind));
3207
}
3208
3209
static bool
3210
resource_commit(struct zink_screen *screen, VkBindSparseInfo *sparse)
3211
{
3212
VkQueue queue = screen->threaded ? screen->thread_queue : screen->queue;
3213
3214
VkResult ret = vkQueueBindSparse(queue, 1, sparse, VK_NULL_HANDLE);
3215
return zink_screen_handle_vkresult(screen, ret);
3216
}
3217
3218
static void
3219
submit_resource_commit(void *data, void *gdata, int thread_index)
3220
{
3221
struct zink_screen **screen = get_screen_ptr_for_commit(data);
3222
resource_commit(*screen, data);
3223
free(data);
3224
}
3225
3226
static bool
3227
zink_resource_commit(struct pipe_context *pctx, struct pipe_resource *pres, unsigned level, struct pipe_box *box, bool commit)
3228
{
3229
struct zink_context *ctx = zink_context(pctx);
3230
struct zink_resource *res = zink_resource(pres);
3231
struct zink_screen *screen = zink_screen(pctx->screen);
3232
3233
/* if any current usage exists, flush the queue */
3234
if (zink_batch_usage_is_unflushed(res->obj->reads) ||
3235
zink_batch_usage_is_unflushed(res->obj->writes))
3236
zink_flush_queue(ctx);
3237
3238
uint8_t *mem = malloc(sizeof(VkBindSparseInfo) + sizeof(VkSparseBufferMemoryBindInfo) + sizeof(VkSparseMemoryBind) + sizeof(void*));
3239
if (!mem)
3240
return false;
3241
VkBindSparseInfo *sparse = (void*)mem;
3242
sparse->sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO;
3243
sparse->pNext = NULL;
3244
sparse->waitSemaphoreCount = 0;
3245
sparse->bufferBindCount = 1;
3246
sparse->imageOpaqueBindCount = 0;
3247
sparse->imageBindCount = 0;
3248
sparse->signalSemaphoreCount = 0;
3249
3250
VkSparseBufferMemoryBindInfo *sparse_bind = (void*)(mem + sizeof(VkBindSparseInfo));
3251
sparse_bind->buffer = res->obj->buffer;
3252
sparse_bind->bindCount = 1;
3253
sparse->pBufferBinds = sparse_bind;
3254
3255
VkSparseMemoryBind *mem_bind = (void*)(mem + sizeof(VkBindSparseInfo) + sizeof(VkSparseBufferMemoryBindInfo));
3256
mem_bind->resourceOffset = box->x;
3257
mem_bind->size = box->width;
3258
mem_bind->memory = commit ? res->obj->mem : VK_NULL_HANDLE;
3259
/* currently sparse buffers allocate memory 1:1 for the max sparse size,
3260
* but probably it should dynamically allocate the committed regions;
3261
* if this ever changes, update the below line
3262
*/
3263
mem_bind->memoryOffset = box->x;
3264
mem_bind->flags = 0;
3265
sparse_bind->pBinds = mem_bind;
3266
3267
struct zink_screen **ptr = get_screen_ptr_for_commit(mem);
3268
*ptr = screen;
3269
3270
if (screen->threaded) {
3271
/* this doesn't need any kind of fencing because any access to this resource
3272
* will be automagically synchronized by queue dispatch */
3273
util_queue_add_job(&screen->flush_queue, mem, NULL, submit_resource_commit, NULL, 0);
3274
} else {
3275
bool ret = resource_commit(screen, sparse);
3276
if (!ret)
3277
check_device_lost(ctx);
3278
free(sparse);
3279
return ret;
3280
}
3281
return true;
3282
}
3283
3284
static void
3285
rebind_image(struct zink_context *ctx, struct zink_resource *res)
3286
{
3287
zink_rebind_framebuffer(ctx, res);
3288
if (!res->bind_count[0] && !res->bind_count[1])
3289
return;
3290
for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++) {
3291
if (res->sampler_binds[i]) {
3292
for (unsigned j = 0; j < ctx->di.num_sampler_views[i]; j++) {
3293
struct zink_sampler_view *sv = zink_sampler_view(ctx->sampler_views[i][j]);
3294
if (sv && sv->base.texture == &res->base.b) {
3295
struct pipe_surface *psurf = &sv->image_view->base;
3296
zink_rebind_surface(ctx, &psurf);
3297
sv->image_view = zink_surface(psurf);
3298
zink_screen(ctx->base.screen)->context_invalidate_descriptor_state(ctx, i, ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW, j, 1);
3299
update_descriptor_state_sampler(ctx, i, j);
3300
}
3301
}
3302
}
3303
if (!res->image_bind_count[i == PIPE_SHADER_COMPUTE])
3304
continue;
3305
for (unsigned j = 0; j < ctx->di.num_images[i]; j++) {
3306
if (zink_resource(ctx->image_views[i][j].base.resource) == res) {
3307
zink_screen(ctx->base.screen)->context_invalidate_descriptor_state(ctx, i, ZINK_DESCRIPTOR_TYPE_IMAGE, j, 1);
3308
update_descriptor_state_sampler(ctx, i, j);
3309
_mesa_set_add(ctx->need_barriers[i == PIPE_SHADER_COMPUTE], res);
3310
}
3311
}
3312
}
3313
}
3314
3315
void
3316
zink_resource_rebind(struct zink_context *ctx, struct zink_resource *res)
3317
{
3318
if (res->bind_history & ZINK_RESOURCE_USAGE_STREAMOUT)
3319
ctx->dirty_so_targets = true;
3320
/* force counter buffer reset */
3321
res->bind_history &= ~ZINK_RESOURCE_USAGE_STREAMOUT;
3322
3323
if (!res->bind_count[0] && !res->bind_count[1])
3324
return;
3325
if (res->base.b.target == PIPE_BUFFER)
3326
rebind_buffer(ctx, res);
3327
else
3328
rebind_image(ctx, res);
3329
}
3330
3331
static void
3332
zink_context_replace_buffer_storage(struct pipe_context *pctx, struct pipe_resource *dst,
3333
struct pipe_resource *src, unsigned num_rebinds,
3334
uint32_t rebind_mask, uint32_t delete_buffer_id)
3335
{
3336
struct zink_resource *d = zink_resource(dst);
3337
struct zink_resource *s = zink_resource(src);
3338
3339
assert(d->internal_format == s->internal_format);
3340
util_idalloc_mt_free(&zink_screen(pctx->screen)->buffer_ids, delete_buffer_id);
3341
if (zink_batch_usage_is_unflushed(d->obj->reads) ||
3342
zink_batch_usage_is_unflushed(d->obj->writes))
3343
zink_batch_reference_resource(&zink_context(pctx)->batch, d);
3344
zink_resource_object_reference(zink_screen(pctx->screen), &d->obj, s->obj);
3345
d->access = s->access;
3346
d->access_stage = s->access_stage;
3347
d->unordered_barrier = s->unordered_barrier;
3348
zink_resource_rebind(zink_context(pctx), d);
3349
}
3350
3351
ALWAYS_INLINE static bool
3352
is_usage_completed(struct zink_screen *screen, const struct zink_batch_usage *u)
3353
{
3354
if (!zink_batch_usage_exists(u))
3355
return true;
3356
if (zink_batch_usage_is_unflushed(u))
3357
return false;
3358
/* check fastpath first */
3359
if (zink_screen_check_last_finished(screen, u->usage))
3360
return true;
3361
/* if we have timelines, do a quick check */
3362
if (screen->info.have_KHR_timeline_semaphore)
3363
return zink_screen_timeline_wait(screen, u->usage, 0);
3364
3365
/* otherwise assume busy */
3366
return false;
3367
}
3368
3369
static bool
3370
zink_context_is_resource_busy(struct pipe_screen *pscreen, struct pipe_resource *pres, unsigned usage)
3371
{
3372
struct zink_screen *screen = zink_screen(pscreen);
3373
struct zink_resource *res = zink_resource(pres);
3374
const struct zink_batch_usage *reads = NULL, *writes = NULL;
3375
if (((usage & (PIPE_MAP_READ | PIPE_MAP_WRITE)) == (PIPE_MAP_READ | PIPE_MAP_WRITE)) ||
3376
usage & PIPE_MAP_WRITE) {
3377
reads = res->obj->reads;
3378
writes = res->obj->writes;
3379
} else if (usage & PIPE_MAP_READ)
3380
writes = res->obj->writes;
3381
3382
return !is_usage_completed(screen, reads) || !is_usage_completed(screen, writes);
3383
}
3384
3385
static void
3386
zink_emit_string_marker(struct pipe_context *pctx,
3387
const char *string, int len)
3388
{
3389
struct zink_screen *screen = zink_screen(pctx->screen);
3390
struct zink_batch *batch = &zink_context(pctx)->batch;
3391
3392
/* make sure string is nul-terminated */
3393
char buf[512], *temp = NULL;
3394
if (len < ARRAY_SIZE(buf)) {
3395
memcpy(buf, string, len);
3396
buf[len] = '\0';
3397
string = buf;
3398
} else
3399
string = temp = strndup(string, len);
3400
3401
VkDebugUtilsLabelEXT label = {
3402
VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, NULL,
3403
string,
3404
{ 0 }
3405
};
3406
screen->vk.CmdInsertDebugUtilsLabelEXT(batch->state->cmdbuf, &label);
3407
free(temp);
3408
}
3409
3410
struct pipe_context *
3411
zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
3412
{
3413
struct zink_screen *screen = zink_screen(pscreen);
3414
struct zink_context *ctx = rzalloc(NULL, struct zink_context);
3415
if (!ctx)
3416
goto fail;
3417
ctx->have_timelines = screen->info.have_KHR_timeline_semaphore;
3418
3419
ctx->gfx_pipeline_state.dirty = true;
3420
ctx->compute_pipeline_state.dirty = true;
3421
ctx->fb_changed = ctx->rp_changed = true;
3422
3423
ctx->base.screen = pscreen;
3424
ctx->base.priv = priv;
3425
3426
ctx->base.destroy = zink_context_destroy;
3427
ctx->base.get_device_reset_status = zink_get_device_reset_status;
3428
ctx->base.set_device_reset_callback = zink_set_device_reset_callback;
3429
3430
zink_context_state_init(&ctx->base);
3431
3432
ctx->base.create_sampler_state = zink_create_sampler_state;
3433
ctx->base.bind_sampler_states = zink_bind_sampler_states;
3434
ctx->base.delete_sampler_state = zink_delete_sampler_state;
3435
3436
ctx->base.create_sampler_view = zink_create_sampler_view;
3437
ctx->base.set_sampler_views = zink_set_sampler_views;
3438
ctx->base.sampler_view_destroy = zink_sampler_view_destroy;
3439
ctx->base.get_sample_position = zink_get_sample_position;
3440
ctx->base.set_sample_locations = zink_set_sample_locations;
3441
3442
zink_program_init(ctx);
3443
3444
ctx->base.set_polygon_stipple = zink_set_polygon_stipple;
3445
ctx->base.set_vertex_buffers = zink_set_vertex_buffers;
3446
ctx->base.set_viewport_states = zink_set_viewport_states;
3447
ctx->base.set_scissor_states = zink_set_scissor_states;
3448
ctx->base.set_inlinable_constants = zink_set_inlinable_constants;
3449
ctx->base.set_constant_buffer = zink_set_constant_buffer;
3450
ctx->base.set_shader_buffers = zink_set_shader_buffers;
3451
ctx->base.set_shader_images = zink_set_shader_images;
3452
ctx->base.set_framebuffer_state = zink_set_framebuffer_state;
3453
ctx->base.set_stencil_ref = zink_set_stencil_ref;
3454
ctx->base.set_clip_state = zink_set_clip_state;
3455
ctx->base.set_blend_color = zink_set_blend_color;
3456
ctx->base.set_tess_state = zink_set_tess_state;
3457
3458
ctx->base.set_sample_mask = zink_set_sample_mask;
3459
3460
ctx->base.clear = zink_clear;
3461
ctx->base.clear_texture = zink_clear_texture;
3462
ctx->base.clear_buffer = zink_clear_buffer;
3463
ctx->base.clear_render_target = zink_clear_render_target;
3464
ctx->base.clear_depth_stencil = zink_clear_depth_stencil;
3465
3466
ctx->base.draw_vbo = zink_draw_vbo;
3467
ctx->base.launch_grid = zink_launch_grid;
3468
ctx->base.fence_server_sync = zink_fence_server_sync;
3469
ctx->base.flush = zink_flush;
3470
ctx->base.memory_barrier = zink_memory_barrier;
3471
ctx->base.texture_barrier = zink_texture_barrier;
3472
ctx->base.evaluate_depth_buffer = zink_evaluate_depth_buffer;
3473
3474
ctx->base.resource_commit = zink_resource_commit;
3475
ctx->base.resource_copy_region = zink_resource_copy_region;
3476
ctx->base.blit = zink_blit;
3477
ctx->base.create_stream_output_target = zink_create_stream_output_target;
3478
ctx->base.stream_output_target_destroy = zink_stream_output_target_destroy;
3479
3480
ctx->base.set_stream_output_targets = zink_set_stream_output_targets;
3481
ctx->base.flush_resource = zink_flush_resource;
3482
3483
ctx->base.emit_string_marker = zink_emit_string_marker;
3484
3485
zink_context_surface_init(&ctx->base);
3486
zink_context_resource_init(&ctx->base);
3487
zink_context_query_init(&ctx->base);
3488
3489
_mesa_set_init(&ctx->update_barriers[0][0], ctx, _mesa_hash_pointer, _mesa_key_pointer_equal);
3490
_mesa_set_init(&ctx->update_barriers[1][0], ctx, _mesa_hash_pointer, _mesa_key_pointer_equal);
3491
_mesa_set_init(&ctx->update_barriers[0][1], ctx, _mesa_hash_pointer, _mesa_key_pointer_equal);
3492
_mesa_set_init(&ctx->update_barriers[1][1], ctx, _mesa_hash_pointer, _mesa_key_pointer_equal);
3493
ctx->need_barriers[0] = &ctx->update_barriers[0][0];
3494
ctx->need_barriers[1] = &ctx->update_barriers[1][0];
3495
3496
util_dynarray_init(&ctx->free_batch_states, ctx);
3497
_mesa_hash_table_init(&ctx->batch_states, ctx, NULL, _mesa_key_pointer_equal);
3498
3499
ctx->gfx_pipeline_state.have_EXT_extended_dynamic_state = screen->info.have_EXT_extended_dynamic_state;
3500
3501
slab_create_child(&ctx->transfer_pool, &screen->transfer_pool);
3502
slab_create_child(&ctx->transfer_pool_unsync, &screen->transfer_pool);
3503
3504
ctx->base.stream_uploader = u_upload_create_default(&ctx->base);
3505
ctx->base.const_uploader = u_upload_create_default(&ctx->base);
3506
for (int i = 0; i < ARRAY_SIZE(ctx->fb_clears); i++)
3507
util_dynarray_init(&ctx->fb_clears[i].clears, ctx);
3508
3509
ctx->blitter = util_blitter_create(&ctx->base);
3510
if (!ctx->blitter)
3511
goto fail;
3512
3513
ctx->program_cache = _mesa_hash_table_create(NULL,
3514
hash_gfx_program,
3515
equals_gfx_program);
3516
ctx->compute_program_cache = _mesa_hash_table_create(NULL,
3517
_mesa_hash_pointer,
3518
_mesa_key_pointer_equal);
3519
ctx->render_pass_cache = _mesa_hash_table_create(NULL,
3520
hash_render_pass_state,
3521
equals_render_pass_state);
3522
if (!ctx->program_cache || !ctx->compute_program_cache || !ctx->render_pass_cache)
3523
goto fail;
3524
3525
const uint8_t data[] = {0};
3526
ctx->dummy_vertex_buffer = pipe_buffer_create(&screen->base,
3527
PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_SHADER_IMAGE, PIPE_USAGE_IMMUTABLE, sizeof(data));
3528
if (!ctx->dummy_vertex_buffer)
3529
goto fail;
3530
ctx->dummy_xfb_buffer = pipe_buffer_create(&screen->base,
3531
PIPE_BIND_STREAM_OUTPUT, PIPE_USAGE_DEFAULT, sizeof(data));
3532
if (!ctx->dummy_xfb_buffer)
3533
goto fail;
3534
ctx->dummy_surface = zink_surface_create_null(ctx, PIPE_TEXTURE_2D, 1, 1, 1);
3535
if (!ctx->dummy_surface)
3536
goto fail;
3537
ctx->dummy_bufferview = get_buffer_view(ctx, zink_resource(ctx->dummy_vertex_buffer), PIPE_FORMAT_R8_UNORM, 0, sizeof(data));
3538
if (!ctx->dummy_bufferview)
3539
goto fail;
3540
3541
if (!zink_descriptor_layouts_init(ctx))
3542
goto fail;
3543
3544
if (!screen->descriptors_init(ctx)) {
3545
zink_screen_init_descriptor_funcs(screen, true);
3546
if (!screen->descriptors_init(ctx))
3547
goto fail;
3548
}
3549
3550
ctx->have_timelines = screen->info.have_KHR_timeline_semaphore;
3551
simple_mtx_init(&ctx->batch_mtx, mtx_plain);
3552
zink_start_batch(ctx, &ctx->batch);
3553
if (!ctx->batch.state)
3554
goto fail;
3555
3556
pipe_buffer_write(&ctx->base, ctx->dummy_vertex_buffer, 0, sizeof(data), data);
3557
pipe_buffer_write(&ctx->base, ctx->dummy_xfb_buffer, 0, sizeof(data), data);
3558
3559
for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++) {
3560
/* need to update these based on screen config for null descriptors */
3561
for (unsigned j = 0; j < 32; j++) {
3562
update_descriptor_state_ubo(ctx, i, j);
3563
update_descriptor_state_sampler(ctx, i, j);
3564
update_descriptor_state_ssbo(ctx, i, j);
3565
update_descriptor_state_image(ctx, i, j);
3566
}
3567
}
3568
p_atomic_inc(&screen->base.num_contexts);
3569
3570
if (!(flags & PIPE_CONTEXT_PREFER_THREADED) || flags & PIPE_CONTEXT_COMPUTE_ONLY) {
3571
return &ctx->base;
3572
}
3573
3574
struct threaded_context *tc = (struct threaded_context*)threaded_context_create(&ctx->base, &screen->transfer_pool,
3575
zink_context_replace_buffer_storage,
3576
zink_create_tc_fence_for_tc,
3577
zink_context_is_resource_busy, true, &ctx->tc);
3578
3579
if (tc && (struct zink_context*)tc != ctx) {
3580
tc->bytes_mapped_limit = screen->total_mem / 4;
3581
ctx->base.set_context_param = zink_set_context_param;
3582
}
3583
3584
return (struct pipe_context*)tc;
3585
3586
fail:
3587
if (ctx)
3588
zink_context_destroy(&ctx->base);
3589
return NULL;
3590
}
3591
3592