Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/panfrost/vulkan/panvk_cmd_buffer.c
4560 views
1
/*
2
* Copyright © 2021 Collabora Ltd.
3
*
4
* Derived from tu_cmd_buffer.c which is:
5
* Copyright © 2016 Red Hat.
6
* Copyright © 2016 Bas Nieuwenhuizen
7
* Copyright © 2015 Intel Corporation
8
*
9
* Permission is hereby granted, free of charge, to any person obtaining a
10
* copy of this software and associated documentation files (the "Software"),
11
* to deal in the Software without restriction, including without limitation
12
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
* and/or sell copies of the Software, and to permit persons to whom the
14
* Software is furnished to do so, subject to the following conditions:
15
*
16
* The above copyright notice and this permission notice (including the next
17
* paragraph) shall be included in all copies or substantial portions of the
18
* Software.
19
*
20
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26
* DEALINGS IN THE SOFTWARE.
27
*/
28
29
#include "panvk_cs.h"
30
#include "panvk_private.h"
31
#include "panfrost-quirks.h"
32
33
#include "pan_blitter.h"
34
#include "pan_encoder.h"
35
36
#include "util/rounding.h"
37
#include "util/u_pack_color.h"
38
#include "vk_format.h"
39
40
static VkResult
41
panvk_reset_cmdbuf(struct panvk_cmd_buffer *cmdbuf)
42
{
43
struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;
44
45
cmdbuf->record_result = VK_SUCCESS;
46
47
list_for_each_entry_safe(struct panvk_batch, batch, &cmdbuf->batches, node) {
48
list_del(&batch->node);
49
util_dynarray_fini(&batch->jobs);
50
if (!pan_is_bifrost(pdev))
51
panfrost_bo_unreference(batch->tiler.ctx.midgard.polygon_list);
52
53
util_dynarray_fini(&batch->event_ops);
54
55
vk_free(&cmdbuf->pool->alloc, batch);
56
}
57
58
panvk_pool_reset(&cmdbuf->desc_pool);
59
panvk_pool_reset(&cmdbuf->tls_pool);
60
panvk_pool_reset(&cmdbuf->varying_pool);
61
cmdbuf->status = PANVK_CMD_BUFFER_STATUS_INITIAL;
62
63
for (unsigned i = 0; i < MAX_BIND_POINTS; i++)
64
memset(&cmdbuf->descriptors[i].sets, 0, sizeof(cmdbuf->descriptors[i].sets));
65
66
return cmdbuf->record_result;
67
}
68
69
static VkResult
70
panvk_create_cmdbuf(struct panvk_device *device,
71
struct panvk_cmd_pool *pool,
72
VkCommandBufferLevel level,
73
struct panvk_cmd_buffer **cmdbuf_out)
74
{
75
struct panvk_cmd_buffer *cmdbuf;
76
77
cmdbuf = vk_object_zalloc(&device->vk, NULL, sizeof(*cmdbuf),
78
VK_OBJECT_TYPE_COMMAND_BUFFER);
79
if (!cmdbuf)
80
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
81
82
cmdbuf->device = device;
83
cmdbuf->level = level;
84
cmdbuf->pool = pool;
85
86
if (pool) {
87
list_addtail(&cmdbuf->pool_link, &pool->active_cmd_buffers);
88
cmdbuf->queue_family_index = pool->queue_family_index;
89
} else {
90
/* Init the pool_link so we can safely call list_del when we destroy
91
* the command buffer
92
*/
93
list_inithead(&cmdbuf->pool_link);
94
cmdbuf->queue_family_index = PANVK_QUEUE_GENERAL;
95
}
96
97
panvk_pool_init(&cmdbuf->desc_pool, &device->physical_device->pdev,
98
pool ? &pool->desc_bo_pool : NULL, 0, 64 * 1024,
99
"Command buffer descriptor pool", true);
100
panvk_pool_init(&cmdbuf->tls_pool, &device->physical_device->pdev,
101
pool ? &pool->tls_bo_pool : NULL,
102
PAN_BO_INVISIBLE, 64 * 1024, "TLS pool", false);
103
panvk_pool_init(&cmdbuf->varying_pool, &device->physical_device->pdev,
104
pool ? &pool->varying_bo_pool : NULL,
105
PAN_BO_INVISIBLE, 64 * 1024, "Varyings pool", false);
106
list_inithead(&cmdbuf->batches);
107
cmdbuf->status = PANVK_CMD_BUFFER_STATUS_INITIAL;
108
*cmdbuf_out = cmdbuf;
109
return VK_SUCCESS;
110
}
111
112
static void
113
panvk_destroy_cmdbuf(struct panvk_cmd_buffer *cmdbuf)
114
{
115
struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;
116
struct panvk_device *device = cmdbuf->device;
117
118
list_del(&cmdbuf->pool_link);
119
120
list_for_each_entry_safe(struct panvk_batch, batch, &cmdbuf->batches, node) {
121
list_del(&batch->node);
122
util_dynarray_fini(&batch->jobs);
123
if (!pan_is_bifrost(pdev))
124
panfrost_bo_unreference(batch->tiler.ctx.midgard.polygon_list);
125
126
util_dynarray_fini(&batch->event_ops);
127
128
vk_free(&cmdbuf->pool->alloc, batch);
129
}
130
131
panvk_pool_cleanup(&cmdbuf->desc_pool);
132
panvk_pool_cleanup(&cmdbuf->tls_pool);
133
panvk_pool_cleanup(&cmdbuf->varying_pool);
134
vk_object_free(&device->vk, NULL, cmdbuf);
135
}
136
137
VkResult
138
panvk_AllocateCommandBuffers(VkDevice _device,
139
const VkCommandBufferAllocateInfo *pAllocateInfo,
140
VkCommandBuffer *pCommandBuffers)
141
{
142
VK_FROM_HANDLE(panvk_device, device, _device);
143
VK_FROM_HANDLE(panvk_cmd_pool, pool, pAllocateInfo->commandPool);
144
145
VkResult result = VK_SUCCESS;
146
unsigned i;
147
148
for (i = 0; i < pAllocateInfo->commandBufferCount; i++) {
149
struct panvk_cmd_buffer *cmdbuf = NULL;
150
151
if (!list_is_empty(&pool->free_cmd_buffers)) {
152
cmdbuf = list_first_entry(
153
&pool->free_cmd_buffers, struct panvk_cmd_buffer, pool_link);
154
155
list_del(&cmdbuf->pool_link);
156
list_addtail(&cmdbuf->pool_link, &pool->active_cmd_buffers);
157
158
cmdbuf->level = pAllocateInfo->level;
159
vk_object_base_reset(&cmdbuf->base);
160
} else {
161
result = panvk_create_cmdbuf(device, pool, pAllocateInfo->level, &cmdbuf);
162
}
163
164
if (result != VK_SUCCESS)
165
goto err_free_cmd_bufs;
166
167
pCommandBuffers[i] = panvk_cmd_buffer_to_handle(cmdbuf);
168
}
169
170
return VK_SUCCESS;
171
172
err_free_cmd_bufs:
173
panvk_FreeCommandBuffers(_device, pAllocateInfo->commandPool, i,
174
pCommandBuffers);
175
for (unsigned j = 0; j < i; j++)
176
pCommandBuffers[j] = VK_NULL_HANDLE;
177
178
return result;
179
}
180
181
void
182
panvk_FreeCommandBuffers(VkDevice device,
183
VkCommandPool commandPool,
184
uint32_t commandBufferCount,
185
const VkCommandBuffer *pCommandBuffers)
186
{
187
for (uint32_t i = 0; i < commandBufferCount; i++) {
188
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, pCommandBuffers[i]);
189
190
if (cmdbuf) {
191
if (cmdbuf->pool) {
192
list_del(&cmdbuf->pool_link);
193
panvk_reset_cmdbuf(cmdbuf);
194
list_addtail(&cmdbuf->pool_link,
195
&cmdbuf->pool->free_cmd_buffers);
196
} else
197
panvk_destroy_cmdbuf(cmdbuf);
198
}
199
}
200
}
201
202
VkResult
203
panvk_ResetCommandBuffer(VkCommandBuffer commandBuffer,
204
VkCommandBufferResetFlags flags)
205
{
206
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
207
208
return panvk_reset_cmdbuf(cmdbuf);
209
}
210
211
VkResult
212
panvk_BeginCommandBuffer(VkCommandBuffer commandBuffer,
213
const VkCommandBufferBeginInfo *pBeginInfo)
214
{
215
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
216
VkResult result = VK_SUCCESS;
217
218
if (cmdbuf->status != PANVK_CMD_BUFFER_STATUS_INITIAL) {
219
/* If the command buffer has already been reset with
220
* vkResetCommandBuffer, no need to do it again.
221
*/
222
result = panvk_reset_cmdbuf(cmdbuf);
223
if (result != VK_SUCCESS)
224
return result;
225
}
226
227
memset(&cmdbuf->state, 0, sizeof(cmdbuf->state));
228
229
cmdbuf->status = PANVK_CMD_BUFFER_STATUS_RECORDING;
230
231
return VK_SUCCESS;
232
}
233
234
void
235
panvk_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,
236
uint32_t firstBinding,
237
uint32_t bindingCount,
238
const VkBuffer *pBuffers,
239
const VkDeviceSize *pOffsets)
240
{
241
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
242
243
assert(firstBinding + bindingCount <= MAX_VBS);
244
245
for (uint32_t i = 0; i < bindingCount; i++) {
246
struct panvk_buffer *buf = panvk_buffer_from_handle(pBuffers[i]);
247
248
cmdbuf->state.vb.bufs[firstBinding + i].address = buf->bo->ptr.gpu + pOffsets[i];
249
cmdbuf->state.vb.bufs[firstBinding + i].size = buf->size - pOffsets[i];
250
}
251
cmdbuf->state.vb.count = MAX2(cmdbuf->state.vb.count, firstBinding + bindingCount);
252
cmdbuf->state.vb.attrib_bufs = cmdbuf->state.vb.attribs = 0;
253
}
254
255
void
256
panvk_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,
257
VkBuffer buffer,
258
VkDeviceSize offset,
259
VkIndexType indexType)
260
{
261
panvk_stub();
262
}
263
264
void
265
panvk_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
266
VkPipelineBindPoint pipelineBindPoint,
267
VkPipelineLayout _layout,
268
uint32_t firstSet,
269
uint32_t descriptorSetCount,
270
const VkDescriptorSet *pDescriptorSets,
271
uint32_t dynamicOffsetCount,
272
const uint32_t *pDynamicOffsets)
273
{
274
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
275
VK_FROM_HANDLE(panvk_pipeline_layout, layout, _layout);
276
277
struct panvk_descriptor_state *descriptors_state =
278
&cmdbuf->descriptors[pipelineBindPoint];
279
280
for (unsigned i = 0; i < descriptorSetCount; ++i) {
281
unsigned idx = i + firstSet;
282
VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorSets[i]);
283
284
descriptors_state->sets[idx].set = set;
285
286
if (layout->num_dynoffsets) {
287
assert(dynamicOffsetCount >= set->layout->num_dynoffsets);
288
289
descriptors_state->sets[idx].dynoffsets =
290
pan_pool_alloc_aligned(&cmdbuf->desc_pool.base,
291
ALIGN(layout->num_dynoffsets, 4) *
292
sizeof(*pDynamicOffsets),
293
16);
294
memcpy(descriptors_state->sets[idx].dynoffsets.cpu,
295
pDynamicOffsets,
296
sizeof(*pDynamicOffsets) * set->layout->num_dynoffsets);
297
dynamicOffsetCount -= set->layout->num_dynoffsets;
298
pDynamicOffsets += set->layout->num_dynoffsets;
299
}
300
301
if (set->layout->num_ubos || set->layout->num_dynoffsets)
302
descriptors_state->ubos = 0;
303
304
if (set->layout->num_textures)
305
descriptors_state->textures = 0;
306
307
if (set->layout->num_samplers)
308
descriptors_state->samplers = 0;
309
}
310
311
assert(!dynamicOffsetCount);
312
}
313
314
void
315
panvk_CmdPushConstants(VkCommandBuffer commandBuffer,
316
VkPipelineLayout layout,
317
VkShaderStageFlags stageFlags,
318
uint32_t offset,
319
uint32_t size,
320
const void *pValues)
321
{
322
panvk_stub();
323
}
324
325
VkResult
326
panvk_EndCommandBuffer(VkCommandBuffer commandBuffer)
327
{
328
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
329
330
cmdbuf->status = PANVK_CMD_BUFFER_STATUS_EXECUTABLE;
331
332
return cmdbuf->record_result;
333
}
334
335
void
336
panvk_CmdBindPipeline(VkCommandBuffer commandBuffer,
337
VkPipelineBindPoint pipelineBindPoint,
338
VkPipeline _pipeline)
339
{
340
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
341
VK_FROM_HANDLE(panvk_pipeline, pipeline, _pipeline);
342
343
cmdbuf->state.bind_point = pipelineBindPoint;
344
cmdbuf->state.pipeline = pipeline;
345
cmdbuf->state.varyings = pipeline->varyings;
346
cmdbuf->state.vb.attrib_bufs = cmdbuf->state.vb.attribs = 0;
347
cmdbuf->state.fs_rsd = 0;
348
memset(cmdbuf->descriptors[pipelineBindPoint].sysvals, 0,
349
sizeof(cmdbuf->descriptors[pipelineBindPoint].sysvals));
350
351
/* Sysvals are passed through UBOs, we need dirty the UBO array if the
352
* pipeline contain shaders using sysvals.
353
*/
354
if (pipeline->num_sysvals)
355
cmdbuf->descriptors[pipelineBindPoint].ubos = 0;
356
}
357
358
void
359
panvk_CmdSetViewport(VkCommandBuffer commandBuffer,
360
uint32_t firstViewport,
361
uint32_t viewportCount,
362
const VkViewport *pViewports)
363
{
364
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
365
assert(viewportCount == 1);
366
assert(!firstViewport);
367
368
cmdbuf->state.viewport = pViewports[0];
369
cmdbuf->state.vpd = 0;
370
cmdbuf->state.dirty |= PANVK_DYNAMIC_VIEWPORT;
371
}
372
373
void
374
panvk_CmdSetScissor(VkCommandBuffer commandBuffer,
375
uint32_t firstScissor,
376
uint32_t scissorCount,
377
const VkRect2D *pScissors)
378
{
379
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
380
assert(scissorCount == 1);
381
assert(!firstScissor);
382
383
cmdbuf->state.scissor = pScissors[0];
384
cmdbuf->state.vpd = 0;
385
cmdbuf->state.dirty |= PANVK_DYNAMIC_SCISSOR;
386
}
387
388
void
389
panvk_CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth)
390
{
391
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
392
393
cmdbuf->state.rast.line_width = lineWidth;
394
cmdbuf->state.dirty |= PANVK_DYNAMIC_LINE_WIDTH;
395
}
396
397
void
398
panvk_CmdSetDepthBias(VkCommandBuffer commandBuffer,
399
float depthBiasConstantFactor,
400
float depthBiasClamp,
401
float depthBiasSlopeFactor)
402
{
403
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
404
405
cmdbuf->state.rast.depth_bias.constant_factor = depthBiasConstantFactor;
406
cmdbuf->state.rast.depth_bias.clamp = depthBiasClamp;
407
cmdbuf->state.rast.depth_bias.slope_factor = depthBiasSlopeFactor;
408
cmdbuf->state.dirty |= PANVK_DYNAMIC_DEPTH_BIAS;
409
cmdbuf->state.fs_rsd = 0;
410
}
411
412
void
413
panvk_CmdSetBlendConstants(VkCommandBuffer commandBuffer,
414
const float blendConstants[4])
415
{
416
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
417
418
memcpy(cmdbuf->state.blend.constants, blendConstants,
419
sizeof(cmdbuf->state.blend.constants));
420
cmdbuf->state.dirty |= PANVK_DYNAMIC_BLEND_CONSTANTS;
421
cmdbuf->state.fs_rsd = 0;
422
}
423
424
void
425
panvk_CmdSetDepthBounds(VkCommandBuffer commandBuffer,
426
float minDepthBounds,
427
float maxDepthBounds)
428
{
429
panvk_stub();
430
}
431
432
void
433
panvk_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
434
VkStencilFaceFlags faceMask,
435
uint32_t compareMask)
436
{
437
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
438
439
if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
440
cmdbuf->state.zs.s_front.compare_mask = compareMask;
441
442
if (faceMask & VK_STENCIL_FACE_BACK_BIT)
443
cmdbuf->state.zs.s_back.compare_mask = compareMask;
444
445
cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_COMPARE_MASK;
446
cmdbuf->state.fs_rsd = 0;
447
}
448
449
void
450
panvk_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer,
451
VkStencilFaceFlags faceMask,
452
uint32_t writeMask)
453
{
454
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
455
456
if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
457
cmdbuf->state.zs.s_front.write_mask = writeMask;
458
459
if (faceMask & VK_STENCIL_FACE_BACK_BIT)
460
cmdbuf->state.zs.s_back.write_mask = writeMask;
461
462
cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_WRITE_MASK;
463
cmdbuf->state.fs_rsd = 0;
464
}
465
466
void
467
panvk_CmdSetStencilReference(VkCommandBuffer commandBuffer,
468
VkStencilFaceFlags faceMask,
469
uint32_t reference)
470
{
471
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
472
473
if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
474
cmdbuf->state.zs.s_front.ref = reference;
475
476
if (faceMask & VK_STENCIL_FACE_BACK_BIT)
477
cmdbuf->state.zs.s_back.ref = reference;
478
479
cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_REFERENCE;
480
cmdbuf->state.fs_rsd = 0;
481
}
482
483
void
484
panvk_CmdExecuteCommands(VkCommandBuffer commandBuffer,
485
uint32_t commandBufferCount,
486
const VkCommandBuffer *pCmdBuffers)
487
{
488
panvk_stub();
489
}
490
491
VkResult
492
panvk_CreateCommandPool(VkDevice _device,
493
const VkCommandPoolCreateInfo *pCreateInfo,
494
const VkAllocationCallbacks *pAllocator,
495
VkCommandPool *pCmdPool)
496
{
497
VK_FROM_HANDLE(panvk_device, device, _device);
498
struct panvk_cmd_pool *pool;
499
500
pool = vk_object_alloc(&device->vk, pAllocator, sizeof(*pool),
501
VK_OBJECT_TYPE_COMMAND_POOL);
502
if (pool == NULL)
503
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
504
505
if (pAllocator)
506
pool->alloc = *pAllocator;
507
else
508
pool->alloc = device->vk.alloc;
509
510
list_inithead(&pool->active_cmd_buffers);
511
list_inithead(&pool->free_cmd_buffers);
512
513
pool->queue_family_index = pCreateInfo->queueFamilyIndex;
514
panvk_bo_pool_init(&pool->desc_bo_pool);
515
panvk_bo_pool_init(&pool->varying_bo_pool);
516
panvk_bo_pool_init(&pool->tls_bo_pool);
517
*pCmdPool = panvk_cmd_pool_to_handle(pool);
518
return VK_SUCCESS;
519
}
520
521
void
522
panvk_DestroyCommandPool(VkDevice _device,
523
VkCommandPool commandPool,
524
const VkAllocationCallbacks *pAllocator)
525
{
526
VK_FROM_HANDLE(panvk_device, device, _device);
527
VK_FROM_HANDLE(panvk_cmd_pool, pool, commandPool);
528
529
list_for_each_entry_safe(struct panvk_cmd_buffer, cmdbuf,
530
&pool->active_cmd_buffers, pool_link)
531
panvk_destroy_cmdbuf(cmdbuf);
532
533
list_for_each_entry_safe(struct panvk_cmd_buffer, cmdbuf,
534
&pool->free_cmd_buffers, pool_link)
535
panvk_destroy_cmdbuf(cmdbuf);
536
537
panvk_bo_pool_cleanup(&pool->desc_bo_pool);
538
panvk_bo_pool_cleanup(&pool->varying_bo_pool);
539
panvk_bo_pool_cleanup(&pool->tls_bo_pool);
540
vk_object_free(&device->vk, pAllocator, pool);
541
}
542
543
VkResult
544
panvk_ResetCommandPool(VkDevice device,
545
VkCommandPool commandPool,
546
VkCommandPoolResetFlags flags)
547
{
548
VK_FROM_HANDLE(panvk_cmd_pool, pool, commandPool);
549
VkResult result;
550
551
list_for_each_entry(struct panvk_cmd_buffer, cmdbuf, &pool->active_cmd_buffers,
552
pool_link)
553
{
554
result = panvk_reset_cmdbuf(cmdbuf);
555
if (result != VK_SUCCESS)
556
return result;
557
}
558
559
return VK_SUCCESS;
560
}
561
562
void
563
panvk_TrimCommandPool(VkDevice device,
564
VkCommandPool commandPool,
565
VkCommandPoolTrimFlags flags)
566
{
567
VK_FROM_HANDLE(panvk_cmd_pool, pool, commandPool);
568
569
if (!pool)
570
return;
571
572
list_for_each_entry_safe(struct panvk_cmd_buffer, cmdbuf,
573
&pool->free_cmd_buffers, pool_link)
574
panvk_destroy_cmdbuf(cmdbuf);
575
}
576
577
static void
578
panvk_pack_color_32(uint32_t *packed, uint32_t v)
579
{
580
for (unsigned i = 0; i < 4; ++i)
581
packed[i] = v;
582
}
583
584
static void
585
panvk_pack_color_64(uint32_t *packed, uint32_t lo, uint32_t hi)
586
{
587
for (unsigned i = 0; i < 4; i += 2) {
588
packed[i + 0] = lo;
589
packed[i + 1] = hi;
590
}
591
}
592
593
void
594
panvk_pack_color(struct panvk_clear_value *out,
595
const VkClearColorValue *in,
596
enum pipe_format format)
597
{
598
const struct util_format_description *desc = util_format_description(format);
599
600
/* Alpha magicked to 1.0 if there is no alpha */
601
bool has_alpha = util_format_has_alpha(format);
602
float clear_alpha = has_alpha ? in->float32[3] : 1.0f;
603
uint32_t *packed = out->color;
604
605
if (util_format_is_rgba8_variant(desc) && desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) {
606
panvk_pack_color_32(packed,
607
((uint32_t) float_to_ubyte(clear_alpha) << 24) |
608
((uint32_t) float_to_ubyte(in->float32[2]) << 16) |
609
((uint32_t) float_to_ubyte(in->float32[1]) << 8) |
610
((uint32_t) float_to_ubyte(in->float32[0]) << 0));
611
} else if (format == PIPE_FORMAT_B5G6R5_UNORM) {
612
/* First, we convert the components to R5, G6, B5 separately */
613
unsigned r5 = _mesa_roundevenf(SATURATE(in->float32[0]) * 31.0);
614
unsigned g6 = _mesa_roundevenf(SATURATE(in->float32[1]) * 63.0);
615
unsigned b5 = _mesa_roundevenf(SATURATE(in->float32[2]) * 31.0);
616
617
/* Then we pack into a sparse u32. TODO: Why these shifts? */
618
panvk_pack_color_32(packed, (b5 << 25) | (g6 << 14) | (r5 << 5));
619
} else if (format == PIPE_FORMAT_B4G4R4A4_UNORM) {
620
/* Convert to 4-bits */
621
unsigned r4 = _mesa_roundevenf(SATURATE(in->float32[0]) * 15.0);
622
unsigned g4 = _mesa_roundevenf(SATURATE(in->float32[1]) * 15.0);
623
unsigned b4 = _mesa_roundevenf(SATURATE(in->float32[2]) * 15.0);
624
unsigned a4 = _mesa_roundevenf(SATURATE(clear_alpha) * 15.0);
625
626
/* Pack on *byte* intervals */
627
panvk_pack_color_32(packed, (a4 << 28) | (b4 << 20) | (g4 << 12) | (r4 << 4));
628
} else if (format == PIPE_FORMAT_B5G5R5A1_UNORM) {
629
/* Scale as expected but shift oddly */
630
unsigned r5 = _mesa_roundevenf(SATURATE(in->float32[0]) * 31.0);
631
unsigned g5 = _mesa_roundevenf(SATURATE(in->float32[1]) * 31.0);
632
unsigned b5 = _mesa_roundevenf(SATURATE(in->float32[2]) * 31.0);
633
unsigned a1 = _mesa_roundevenf(SATURATE(clear_alpha) * 1.0);
634
635
panvk_pack_color_32(packed, (a1 << 31) | (b5 << 25) | (g5 << 15) | (r5 << 5));
636
} else {
637
/* Otherwise, it's generic subject to replication */
638
639
union util_color out = { 0 };
640
unsigned size = util_format_get_blocksize(format);
641
642
util_pack_color(in->float32, format, &out);
643
644
if (size == 1) {
645
unsigned b = out.ui[0];
646
unsigned s = b | (b << 8);
647
panvk_pack_color_32(packed, s | (s << 16));
648
} else if (size == 2)
649
panvk_pack_color_32(packed, out.ui[0] | (out.ui[0] << 16));
650
else if (size == 3 || size == 4)
651
panvk_pack_color_32(packed, out.ui[0]);
652
else if (size == 6 || size == 8)
653
panvk_pack_color_64(packed, out.ui[0], out.ui[1]);
654
else if (size == 12 || size == 16)
655
memcpy(packed, out.ui, 16);
656
else
657
unreachable("Unknown generic format size packing clear colour");
658
}
659
}
660
661
static void
662
panvk_cmd_prepare_clear_values(struct panvk_cmd_buffer *cmdbuf,
663
const VkClearValue *in)
664
{
665
for (unsigned i = 0; i < cmdbuf->state.pass->attachment_count; i++) {
666
const struct panvk_render_pass_attachment *attachment =
667
&cmdbuf->state.pass->attachments[i];
668
enum pipe_format fmt = attachment->format;
669
670
if (util_format_is_depth_or_stencil(fmt)) {
671
if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR ||
672
attachment->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
673
cmdbuf->state.clear[i].depth = in[i].depthStencil.depth;
674
cmdbuf->state.clear[i].stencil = in[i].depthStencil.stencil;
675
}
676
} else if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
677
panvk_pack_color(&cmdbuf->state.clear[i], &in[i].color, fmt);
678
}
679
}
680
}
681
682
void
683
panvk_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,
684
const VkRenderPassBeginInfo *pRenderPassBegin,
685
const VkSubpassBeginInfo *pSubpassBeginInfo)
686
{
687
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
688
VK_FROM_HANDLE(panvk_render_pass, pass, pRenderPassBegin->renderPass);
689
VK_FROM_HANDLE(panvk_framebuffer, fb, pRenderPassBegin->framebuffer);
690
691
cmdbuf->state.pass = pass;
692
cmdbuf->state.subpass = pass->subpasses;
693
cmdbuf->state.framebuffer = fb;
694
cmdbuf->state.render_area = pRenderPassBegin->renderArea;
695
cmdbuf->state.batch = vk_zalloc(&cmdbuf->pool->alloc,
696
sizeof(*cmdbuf->state.batch), 8,
697
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
698
util_dynarray_init(&cmdbuf->state.batch->jobs, NULL);
699
util_dynarray_init(&cmdbuf->state.batch->event_ops, NULL);
700
cmdbuf->state.clear = vk_zalloc(&cmdbuf->pool->alloc,
701
sizeof(*cmdbuf->state.clear) *
702
pRenderPassBegin->clearValueCount, 8,
703
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
704
assert(pRenderPassBegin->clearValueCount == pass->attachment_count);
705
panvk_cmd_prepare_clear_values(cmdbuf, pRenderPassBegin->pClearValues);
706
memset(&cmdbuf->state.compute, 0, sizeof(cmdbuf->state.compute));
707
}
708
709
void
710
panvk_CmdBeginRenderPass(VkCommandBuffer cmd,
711
const VkRenderPassBeginInfo *info,
712
VkSubpassContents contents)
713
{
714
VkSubpassBeginInfo subpass_info = {
715
.sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
716
.contents = contents
717
};
718
719
return panvk_CmdBeginRenderPass2(cmd, info, &subpass_info);
720
}
721
722
static void
723
panvk_cmd_prepare_fragment_job(struct panvk_cmd_buffer *cmdbuf)
724
{
725
assert(cmdbuf->state.bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS);
726
727
struct panvk_batch *batch = cmdbuf->state.batch;
728
struct panfrost_ptr job_ptr =
729
pan_pool_alloc_desc(&cmdbuf->desc_pool.base, FRAGMENT_JOB);
730
731
panvk_emit_fragment_job(cmdbuf->device, cmdbuf->state.framebuffer,
732
cmdbuf->state.batch->fb.desc.gpu,
733
job_ptr.cpu);
734
cmdbuf->state.batch->fragment_job = job_ptr.gpu;
735
util_dynarray_append(&batch->jobs, void *, job_ptr.cpu);
736
}
737
738
void
739
panvk_cmd_get_midgard_polygon_list(struct panvk_cmd_buffer *cmdbuf,
740
unsigned width, unsigned height,
741
bool has_draws)
742
{
743
struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;
744
struct panvk_batch *batch = cmdbuf->state.batch;
745
746
assert(!pan_is_bifrost(pdev));
747
748
if (batch->tiler.ctx.midgard.polygon_list)
749
return;
750
751
unsigned size =
752
panfrost_tiler_get_polygon_list_size(pdev, width, height, has_draws);
753
size = util_next_power_of_two(size);
754
755
/* Create the BO as invisible if we can. In the non-hierarchical tiler case,
756
* we need to write the polygon list manually because there's not WRITE_VALUE
757
* job in the chain. */
758
bool init_polygon_list = !has_draws && (pdev->quirks & MIDGARD_NO_HIER_TILING);
759
batch->tiler.ctx.midgard.polygon_list =
760
panfrost_bo_create(pdev, size,
761
init_polygon_list ? 0 : PAN_BO_INVISIBLE,
762
"Polygon list");
763
764
765
if (init_polygon_list) {
766
assert(batch->tiler.ctx.midgard.polygon_list->ptr.cpu);
767
uint32_t *polygon_list_body =
768
batch->tiler.ctx.midgard.polygon_list->ptr.cpu +
769
MALI_MIDGARD_TILER_MINIMUM_HEADER_SIZE;
770
polygon_list_body[0] = 0xa0000000;
771
}
772
773
batch->tiler.ctx.midgard.disable = !has_draws;
774
}
775
776
void
777
panvk_cmd_close_batch(struct panvk_cmd_buffer *cmdbuf)
778
{
779
struct panvk_batch *batch = cmdbuf->state.batch;
780
781
assert(batch);
782
783
if (!batch->fragment_job && !batch->scoreboard.first_job) {
784
if (util_dynarray_num_elements(&batch->event_ops, struct panvk_event_op) == 0) {
785
/* Content-less batch, let's drop it */
786
vk_free(&cmdbuf->pool->alloc, batch);
787
} else {
788
/* Batch has no jobs but is needed for synchronization, let's add a
789
* NULL job so the SUBMIT ioctl doesn't choke on it.
790
*/
791
struct panfrost_ptr ptr = pan_pool_alloc_desc(&cmdbuf->desc_pool.base,
792
JOB_HEADER);
793
util_dynarray_append(&batch->jobs, void *, ptr.cpu);
794
panfrost_add_job(&cmdbuf->desc_pool.base, &batch->scoreboard,
795
MALI_JOB_TYPE_NULL, false, false, 0, 0,
796
&ptr, false);
797
list_addtail(&batch->node, &cmdbuf->batches);
798
}
799
cmdbuf->state.batch = NULL;
800
return;
801
}
802
803
struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;
804
805
list_addtail(&cmdbuf->state.batch->node, &cmdbuf->batches);
806
807
struct pan_tls_info tlsinfo = {
808
.tls.size = cmdbuf->state.pipeline->tls_size,
809
.wls.size = cmdbuf->state.pipeline->wls_size,
810
};
811
812
if (tlsinfo.tls.size) {
813
tlsinfo.tls.ptr =
814
pan_pool_alloc_aligned(&cmdbuf->tls_pool.base, tlsinfo.tls.size, 4096).gpu;
815
}
816
817
if (tlsinfo.wls.size) {
818
unsigned wls_size =
819
pan_wls_mem_size(pdev, &cmdbuf->state.compute.wg_count, tlsinfo.wls.size);
820
tlsinfo.wls.ptr =
821
pan_pool_alloc_aligned(&cmdbuf->tls_pool.base, wls_size, 4096).gpu;
822
}
823
824
if ((pan_is_bifrost(pdev) || !cmdbuf->state.batch->fb.desc.cpu) &&
825
cmdbuf->state.batch->tls.cpu) {
826
pan_emit_tls(pdev, &tlsinfo, cmdbuf->state.batch->tls.cpu);
827
}
828
829
if (cmdbuf->state.batch->fb.desc.cpu) {
830
if (!pan_is_bifrost(pdev)) {
831
panvk_cmd_get_midgard_polygon_list(cmdbuf,
832
batch->fb.info->width,
833
batch->fb.info->height,
834
false);
835
836
mali_ptr polygon_list =
837
cmdbuf->state.batch->tiler.ctx.midgard.polygon_list->ptr.gpu;
838
struct panfrost_ptr writeval_job =
839
panfrost_scoreboard_initialize_tiler(&cmdbuf->desc_pool.base,
840
&cmdbuf->state.batch->scoreboard,
841
polygon_list);
842
if (writeval_job.cpu)
843
util_dynarray_append(&cmdbuf->state.batch->jobs, void *, writeval_job.cpu);
844
}
845
846
cmdbuf->state.batch->fb.desc.gpu |=
847
panvk_emit_fb(cmdbuf->device,
848
cmdbuf->state.batch,
849
cmdbuf->state.subpass,
850
cmdbuf->state.pipeline,
851
cmdbuf->state.framebuffer,
852
cmdbuf->state.clear,
853
&tlsinfo, &cmdbuf->state.batch->tiler.ctx,
854
cmdbuf->state.batch->fb.desc.cpu);
855
856
if (!pan_is_bifrost(pdev)) {
857
memcpy(&cmdbuf->state.batch->tiler.templ.midgard,
858
pan_section_ptr(cmdbuf->state.batch->fb.desc.cpu,
859
MULTI_TARGET_FRAMEBUFFER, TILER),
860
sizeof(cmdbuf->state.batch->tiler.templ.midgard));
861
}
862
863
panvk_cmd_prepare_fragment_job(cmdbuf);
864
}
865
866
cmdbuf->state.batch = NULL;
867
}
868
869
void
870
panvk_cmd_open_batch(struct panvk_cmd_buffer *cmdbuf)
871
{
872
assert(!cmdbuf->state.batch);
873
cmdbuf->state.batch = vk_zalloc(&cmdbuf->pool->alloc,
874
sizeof(*cmdbuf->state.batch), 8,
875
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
876
assert(cmdbuf->state.batch);
877
}
878
879
void
880
panvk_CmdNextSubpass2(VkCommandBuffer commandBuffer,
881
const VkSubpassBeginInfo *pSubpassBeginInfo,
882
const VkSubpassEndInfo *pSubpassEndInfo)
883
{
884
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
885
886
panvk_cmd_close_batch(cmdbuf);
887
888
cmdbuf->state.subpass++;
889
panvk_cmd_open_batch(cmdbuf);
890
memset(&cmdbuf->state.compute, 0, sizeof(cmdbuf->state.compute));
891
}
892
893
void
894
panvk_CmdNextSubpass(VkCommandBuffer cmd, VkSubpassContents contents)
895
{
896
VkSubpassBeginInfo binfo = {
897
.sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
898
.contents = contents
899
};
900
VkSubpassEndInfo einfo = {
901
.sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
902
};
903
904
panvk_CmdNextSubpass2(cmd, &binfo, &einfo);
905
}
906
907
908
static void
909
panvk_cmd_alloc_fb_desc(struct panvk_cmd_buffer *cmdbuf)
910
{
911
if (!cmdbuf->state.pipeline->fs.required)
912
return;
913
914
struct panvk_batch *batch = cmdbuf->state.batch;
915
916
if (batch->fb.desc.gpu)
917
return;
918
919
const struct panvk_subpass *subpass = cmdbuf->state.subpass;
920
bool has_zs_ext = subpass->zs_attachment.idx != VK_ATTACHMENT_UNUSED;
921
unsigned tags = MALI_FBD_TAG_IS_MFBD;
922
923
batch->fb.info = cmdbuf->state.framebuffer;
924
batch->fb.desc =
925
pan_pool_alloc_desc_aggregate(&cmdbuf->desc_pool.base,
926
PAN_DESC(MULTI_TARGET_FRAMEBUFFER),
927
PAN_DESC_ARRAY(has_zs_ext ? 1 : 0, ZS_CRC_EXTENSION),
928
PAN_DESC_ARRAY(MAX2(subpass->color_count, 1), RENDER_TARGET));
929
930
/* Tag the pointer */
931
batch->fb.desc.gpu |= tags;
932
}
933
934
static void
935
panvk_cmd_alloc_tls_desc(struct panvk_cmd_buffer *cmdbuf)
936
{
937
const struct panfrost_device *pdev =
938
&cmdbuf->device->physical_device->pdev;
939
struct panvk_batch *batch = cmdbuf->state.batch;
940
941
assert(batch);
942
if (batch->tls.gpu)
943
return;
944
945
if (!pan_is_bifrost(pdev) &&
946
cmdbuf->state.bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
947
panvk_cmd_alloc_fb_desc(cmdbuf);
948
batch->tls = batch->fb.desc;
949
batch->tls.gpu &= ~63ULL;
950
} else {
951
batch->tls =
952
pan_pool_alloc_desc(&cmdbuf->desc_pool.base, LOCAL_STORAGE);
953
}
954
}
955
956
static void
957
panvk_cmd_upload_sysval(struct panvk_cmd_buffer *cmdbuf,
958
unsigned id, union panvk_sysval_data *data)
959
{
960
switch (PAN_SYSVAL_TYPE(id)) {
961
case PAN_SYSVAL_VIEWPORT_SCALE:
962
panvk_sysval_upload_viewport_scale(&cmdbuf->state.viewport, data);
963
break;
964
case PAN_SYSVAL_VIEWPORT_OFFSET:
965
panvk_sysval_upload_viewport_offset(&cmdbuf->state.viewport, data);
966
break;
967
case PAN_SYSVAL_VERTEX_INSTANCE_OFFSETS:
968
/* TODO: support base_{vertex,instance} */
969
data->u32[0] = data->u32[1] = data->u32[2] = 0;
970
break;
971
default:
972
unreachable("Invalid static sysval");
973
}
974
}
975
976
static void
977
panvk_cmd_prepare_sysvals(struct panvk_cmd_buffer *cmdbuf)
978
{
979
struct panvk_descriptor_state *desc_state =
980
&cmdbuf->descriptors[cmdbuf->state.bind_point];
981
const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;
982
983
if (!pipeline->num_sysvals)
984
return;
985
986
for (unsigned i = 0; i < ARRAY_SIZE(desc_state->sysvals); i++) {
987
unsigned sysval_count = pipeline->sysvals[i].ids.sysval_count;
988
if (!sysval_count ||
989
(desc_state->sysvals[i] &&
990
!(cmdbuf->state.dirty & pipeline->sysvals[i].dirty_mask)))
991
continue;
992
993
struct panfrost_ptr sysvals =
994
pan_pool_alloc_aligned(&cmdbuf->desc_pool.base, sysval_count * 16, 16);
995
union panvk_sysval_data *data = sysvals.cpu;
996
997
for (unsigned s = 0; s < pipeline->sysvals[i].ids.sysval_count; s++) {
998
panvk_cmd_upload_sysval(cmdbuf, pipeline->sysvals[i].ids.sysvals[s],
999
&data[s]);
1000
}
1001
1002
desc_state->sysvals[i] = sysvals.gpu;
1003
}
1004
}
1005
1006
static void
1007
panvk_cmd_prepare_ubos(struct panvk_cmd_buffer *cmdbuf)
1008
{
1009
struct panvk_descriptor_state *desc_state =
1010
&cmdbuf->descriptors[cmdbuf->state.bind_point];
1011
const struct panvk_pipeline *pipeline =
1012
cmdbuf->state.pipeline;
1013
1014
if (!pipeline->num_ubos || desc_state->ubos)
1015
return;
1016
1017
panvk_cmd_prepare_sysvals(cmdbuf);
1018
1019
struct panfrost_ptr ubos =
1020
pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,
1021
pipeline->num_ubos,
1022
UNIFORM_BUFFER);
1023
1024
panvk_emit_ubos(pipeline, desc_state, ubos.cpu);
1025
1026
desc_state->ubos = ubos.gpu;
1027
}
1028
1029
static void
1030
panvk_cmd_prepare_textures(struct panvk_cmd_buffer *cmdbuf)
1031
{
1032
struct panvk_descriptor_state *desc_state =
1033
&cmdbuf->descriptors[cmdbuf->state.bind_point];
1034
const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;
1035
unsigned num_textures = pipeline->layout->num_textures;
1036
1037
if (!num_textures || desc_state->textures)
1038
return;
1039
1040
const struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;
1041
unsigned tex_entry_size = pan_is_bifrost(pdev) ?
1042
sizeof(struct mali_bifrost_texture_packed) :
1043
sizeof(mali_ptr);
1044
struct panfrost_ptr textures =
1045
pan_pool_alloc_aligned(&cmdbuf->desc_pool.base,
1046
num_textures * tex_entry_size,
1047
tex_entry_size);
1048
1049
void *texture = textures.cpu;
1050
1051
for (unsigned i = 0; i < ARRAY_SIZE(desc_state->sets); i++) {
1052
if (!desc_state->sets[i].set) continue;
1053
1054
memcpy(texture,
1055
desc_state->sets[i].set->textures.midgard,
1056
desc_state->sets[i].set->layout->num_textures *
1057
tex_entry_size);
1058
1059
texture += desc_state->sets[i].set->layout->num_textures *
1060
tex_entry_size;
1061
}
1062
1063
desc_state->textures = textures.gpu;
1064
}
1065
1066
static void
1067
panvk_cmd_prepare_samplers(struct panvk_cmd_buffer *cmdbuf)
1068
{
1069
struct panvk_descriptor_state *desc_state =
1070
&cmdbuf->descriptors[cmdbuf->state.bind_point];
1071
const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;
1072
unsigned num_samplers = pipeline->layout->num_samplers;
1073
1074
if (!num_samplers || desc_state->samplers)
1075
return;
1076
1077
struct panfrost_ptr samplers =
1078
pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,
1079
num_samplers,
1080
MIDGARD_SAMPLER);
1081
1082
struct mali_midgard_sampler_packed *sampler = samplers.cpu;
1083
1084
for (unsigned i = 0; i < ARRAY_SIZE(desc_state->sets); i++) {
1085
if (!desc_state->sets[i].set) continue;
1086
1087
memcpy(sampler,
1088
desc_state->sets[i].set->samplers,
1089
desc_state->sets[i].set->layout->num_samplers *
1090
sizeof(*sampler));
1091
1092
sampler += desc_state->sets[i].set->layout->num_samplers;
1093
}
1094
1095
desc_state->samplers = samplers.gpu;
1096
}
1097
1098
static void
1099
panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf,
1100
struct panvk_draw_info *draw)
1101
{
1102
const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;
1103
1104
if (!pipeline->fs.dynamic_rsd) {
1105
draw->fs_rsd = pipeline->rsds[MESA_SHADER_FRAGMENT];
1106
return;
1107
}
1108
1109
if (!cmdbuf->state.fs_rsd) {
1110
struct panfrost_ptr rsd =
1111
pan_pool_alloc_desc_aggregate(&cmdbuf->desc_pool.base,
1112
PAN_DESC(RENDERER_STATE),
1113
PAN_DESC_ARRAY(pipeline->blend.state.rt_count,
1114
BLEND));
1115
1116
struct mali_renderer_state_packed rsd_dyn;
1117
1118
panvk_emit_dyn_fs_rsd(cmdbuf->device, pipeline, &cmdbuf->state, &rsd_dyn);
1119
pan_merge(rsd_dyn, pipeline->fs.rsd_template, RENDERER_STATE);
1120
memcpy(rsd.cpu, &rsd_dyn, sizeof(rsd_dyn));
1121
1122
void *bd = rsd.cpu + MALI_RENDERER_STATE_LENGTH;
1123
for (unsigned i = 0; i < pipeline->blend.state.rt_count; i++) {
1124
if (pipeline->blend.constant[i].index != ~0) {
1125
struct mali_blend_packed bd_dyn;
1126
1127
panvk_emit_blend_constant(cmdbuf->device, pipeline, i,
1128
cmdbuf->state.blend.constants[i],
1129
&bd_dyn);
1130
pan_merge(bd_dyn, pipeline->blend.bd_template[i], BLEND);
1131
memcpy(bd, &bd_dyn, sizeof(bd_dyn));
1132
}
1133
bd += MALI_BLEND_LENGTH;
1134
}
1135
1136
cmdbuf->state.fs_rsd = rsd.gpu;
1137
}
1138
1139
draw->fs_rsd = cmdbuf->state.fs_rsd;
1140
}
1141
1142
void
1143
panvk_cmd_get_bifrost_tiler_context(struct panvk_cmd_buffer *cmdbuf,
1144
unsigned width, unsigned height)
1145
{
1146
struct panvk_batch *batch = cmdbuf->state.batch;
1147
1148
if (batch->tiler.bifrost_descs.cpu)
1149
return;
1150
1151
batch->tiler.bifrost_descs =
1152
pan_pool_alloc_desc_aggregate(&cmdbuf->desc_pool.base,
1153
PAN_DESC(BIFROST_TILER),
1154
PAN_DESC(BIFROST_TILER_HEAP));
1155
1156
panvk_emit_bifrost_tiler_context(cmdbuf->device, width, height,
1157
&batch->tiler.bifrost_descs);
1158
memcpy(&batch->tiler.templ.bifrost, batch->tiler.bifrost_descs.cpu,
1159
sizeof(batch->tiler.templ.bifrost));
1160
batch->tiler.ctx.bifrost = batch->tiler.bifrost_descs.gpu;
1161
}
1162
1163
static void
1164
panvk_draw_prepare_tiler_context(struct panvk_cmd_buffer *cmdbuf,
1165
struct panvk_draw_info *draw)
1166
{
1167
const struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;
1168
struct panvk_batch *batch = cmdbuf->state.batch;
1169
1170
if (pan_is_bifrost(pdev)) {
1171
panvk_cmd_get_bifrost_tiler_context(cmdbuf,
1172
batch->fb.info->width,
1173
batch->fb.info->height);
1174
} else {
1175
panvk_cmd_get_midgard_polygon_list(cmdbuf,
1176
batch->fb.info->width,
1177
batch->fb.info->height,
1178
true);
1179
}
1180
1181
draw->tiler_ctx = &batch->tiler.ctx;
1182
}
1183
1184
static void
1185
panvk_draw_prepare_varyings(struct panvk_cmd_buffer *cmdbuf,
1186
struct panvk_draw_info *draw)
1187
{
1188
const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;
1189
struct panvk_varyings_info *varyings = &cmdbuf->state.varyings;
1190
1191
panvk_varyings_alloc(varyings, &cmdbuf->varying_pool.base,
1192
draw->vertex_count);
1193
1194
unsigned buf_count = panvk_varyings_buf_count(cmdbuf->device, varyings);
1195
struct panfrost_ptr bufs =
1196
pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,
1197
buf_count, ATTRIBUTE_BUFFER);
1198
1199
panvk_emit_varying_bufs(cmdbuf->device, varyings, bufs.cpu);
1200
if (BITSET_TEST(varyings->active, VARYING_SLOT_POS)) {
1201
draw->position = varyings->buf[varyings->varying[VARYING_SLOT_POS].buf].address +
1202
varyings->varying[VARYING_SLOT_POS].offset;
1203
}
1204
1205
if (BITSET_TEST(varyings->active, VARYING_SLOT_PSIZ)) {
1206
draw->psiz = varyings->buf[varyings->varying[VARYING_SLOT_PSIZ].buf].address +
1207
varyings->varying[VARYING_SLOT_POS].offset;
1208
} else if (pipeline->ia.topology == MALI_DRAW_MODE_LINES ||
1209
pipeline->ia.topology == MALI_DRAW_MODE_LINE_STRIP ||
1210
pipeline->ia.topology == MALI_DRAW_MODE_LINE_LOOP) {
1211
draw->line_width = pipeline->dynamic_state_mask & PANVK_DYNAMIC_LINE_WIDTH ?
1212
cmdbuf->state.rast.line_width : pipeline->rast.line_width;
1213
} else {
1214
draw->line_width = 1.0f;
1215
}
1216
draw->varying_bufs = bufs.gpu;
1217
1218
for (unsigned s = 0; s < MESA_SHADER_STAGES; s++) {
1219
if (!varyings->stage[s].count) continue;
1220
1221
struct panfrost_ptr attribs =
1222
pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,
1223
varyings->stage[s].count,
1224
ATTRIBUTE);
1225
1226
panvk_emit_varyings(cmdbuf->device, varyings, s, attribs.cpu);
1227
draw->stages[s].varyings = attribs.gpu;
1228
}
1229
}
1230
1231
static void
1232
panvk_draw_prepare_attributes(struct panvk_cmd_buffer *cmdbuf,
1233
struct panvk_draw_info *draw)
1234
{
1235
/* TODO: images */
1236
const struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;
1237
1238
if (!cmdbuf->state.pipeline->attribs.buf_count)
1239
return;
1240
1241
if (cmdbuf->state.vb.attribs) {
1242
draw->stages[MESA_SHADER_VERTEX].attributes = cmdbuf->state.vb.attribs;
1243
draw->attribute_bufs = cmdbuf->state.vb.attrib_bufs;
1244
return;
1245
}
1246
1247
unsigned buf_count = cmdbuf->state.pipeline->attribs.buf_count +
1248
(pan_is_bifrost(pdev) ? 1 : 0);
1249
struct panfrost_ptr bufs =
1250
pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,
1251
buf_count * 2, ATTRIBUTE_BUFFER);
1252
1253
panvk_emit_attrib_bufs(cmdbuf->device,
1254
&cmdbuf->state.pipeline->attribs,
1255
cmdbuf->state.vb.bufs, cmdbuf->state.vb.count,
1256
draw, bufs.cpu);
1257
cmdbuf->state.vb.attrib_bufs = bufs.gpu;
1258
1259
struct panfrost_ptr attribs =
1260
pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base,
1261
cmdbuf->state.pipeline->attribs.attrib_count,
1262
ATTRIBUTE);
1263
1264
panvk_emit_attribs(cmdbuf->device, &cmdbuf->state.pipeline->attribs,
1265
cmdbuf->state.vb.bufs, cmdbuf->state.vb.count,
1266
attribs.cpu);
1267
cmdbuf->state.vb.attribs = attribs.gpu;
1268
draw->stages[MESA_SHADER_VERTEX].attributes = cmdbuf->state.vb.attribs;
1269
draw->attribute_bufs = cmdbuf->state.vb.attrib_bufs;
1270
}
1271
1272
static void
1273
panvk_draw_prepare_viewport(struct panvk_cmd_buffer *cmdbuf,
1274
struct panvk_draw_info *draw)
1275
{
1276
const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;
1277
1278
if (pipeline->vpd) {
1279
draw->viewport = pipeline->vpd;
1280
} else if (cmdbuf->state.vpd) {
1281
draw->viewport = cmdbuf->state.vpd;
1282
} else {
1283
struct panfrost_ptr vp =
1284
pan_pool_alloc_desc(&cmdbuf->desc_pool.base, VIEWPORT);
1285
1286
const VkViewport *viewport =
1287
pipeline->dynamic_state_mask & PANVK_DYNAMIC_VIEWPORT ?
1288
&cmdbuf->state.viewport : &pipeline->viewport;
1289
const VkRect2D *scissor =
1290
pipeline->dynamic_state_mask & PANVK_DYNAMIC_SCISSOR ?
1291
&cmdbuf->state.scissor : &pipeline->scissor;
1292
1293
panvk_emit_viewport(viewport, scissor, vp.cpu);
1294
draw->viewport = cmdbuf->state.vpd = vp.gpu;
1295
}
1296
}
1297
1298
static void
1299
panvk_draw_prepare_vertex_job(struct panvk_cmd_buffer *cmdbuf,
1300
struct panvk_draw_info *draw)
1301
{
1302
struct panvk_batch *batch = cmdbuf->state.batch;
1303
struct panfrost_ptr ptr =
1304
pan_pool_alloc_desc(&cmdbuf->desc_pool.base, COMPUTE_JOB);
1305
1306
util_dynarray_append(&batch->jobs, void *, ptr.cpu);
1307
draw->jobs.vertex = ptr;
1308
panvk_emit_vertex_job(cmdbuf->device,
1309
cmdbuf->state.pipeline,
1310
draw, ptr.cpu);
1311
1312
}
1313
1314
static void
1315
panvk_draw_prepare_tiler_job(struct panvk_cmd_buffer *cmdbuf,
1316
struct panvk_draw_info *draw)
1317
{
1318
const struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev;
1319
struct panvk_batch *batch = cmdbuf->state.batch;
1320
struct panfrost_ptr ptr =
1321
pan_is_bifrost(pdev) ?
1322
pan_pool_alloc_desc(&cmdbuf->desc_pool.base, BIFROST_TILER_JOB) :
1323
pan_pool_alloc_desc(&cmdbuf->desc_pool.base, MIDGARD_TILER_JOB);
1324
1325
util_dynarray_append(&batch->jobs, void *, ptr.cpu);
1326
draw->jobs.tiler = ptr;
1327
panvk_emit_tiler_job(cmdbuf->device,
1328
cmdbuf->state.pipeline,
1329
draw, ptr.cpu);
1330
}
1331
1332
void
1333
panvk_CmdDraw(VkCommandBuffer commandBuffer,
1334
uint32_t vertexCount,
1335
uint32_t instanceCount,
1336
uint32_t firstVertex,
1337
uint32_t firstInstance)
1338
{
1339
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
1340
1341
struct panvk_batch *batch = cmdbuf->state.batch;
1342
1343
panvk_cmd_alloc_fb_desc(cmdbuf);
1344
panvk_cmd_alloc_tls_desc(cmdbuf);
1345
panvk_cmd_prepare_ubos(cmdbuf);
1346
panvk_cmd_prepare_textures(cmdbuf);
1347
panvk_cmd_prepare_samplers(cmdbuf);
1348
1349
/* TODO: indexed draws */
1350
1351
struct panvk_draw_info draw = {
1352
.first_vertex = firstVertex,
1353
.vertex_count = vertexCount,
1354
.first_instance = firstInstance,
1355
.instance_count = instanceCount,
1356
.padded_vertex_count = panfrost_padded_vertex_count(vertexCount),
1357
.offset_start = firstVertex,
1358
.tls = batch->tls.gpu,
1359
.fb = batch->fb.desc.gpu,
1360
.ubos = cmdbuf->descriptors[VK_PIPELINE_BIND_POINT_GRAPHICS].ubos,
1361
.textures = cmdbuf->descriptors[VK_PIPELINE_BIND_POINT_GRAPHICS].textures,
1362
.samplers = cmdbuf->descriptors[VK_PIPELINE_BIND_POINT_GRAPHICS].samplers,
1363
};
1364
1365
panfrost_pack_work_groups_compute(&draw.invocation, 1, vertexCount,
1366
instanceCount, 1, 1, 1, true, false);
1367
panvk_draw_prepare_fs_rsd(cmdbuf, &draw);
1368
panvk_draw_prepare_varyings(cmdbuf, &draw);
1369
panvk_draw_prepare_attributes(cmdbuf, &draw);
1370
panvk_draw_prepare_viewport(cmdbuf, &draw);
1371
panvk_draw_prepare_tiler_context(cmdbuf, &draw);
1372
panvk_draw_prepare_vertex_job(cmdbuf, &draw);
1373
panvk_draw_prepare_tiler_job(cmdbuf, &draw);
1374
1375
const struct panvk_pipeline *pipeline = cmdbuf->state.pipeline;
1376
unsigned vjob_id =
1377
panfrost_add_job(&cmdbuf->desc_pool.base, &batch->scoreboard,
1378
MALI_JOB_TYPE_VERTEX, false, false, 0, 0,
1379
&draw.jobs.vertex, false);
1380
1381
if (pipeline->fs.required) {
1382
panfrost_add_job(&cmdbuf->desc_pool.base, &batch->scoreboard,
1383
MALI_JOB_TYPE_TILER, false, false, vjob_id, 0,
1384
&draw.jobs.tiler, false);
1385
}
1386
1387
/* Clear the dirty flags all at once */
1388
cmdbuf->state.dirty = 0;
1389
}
1390
1391
void
1392
panvk_CmdDrawIndexed(VkCommandBuffer commandBuffer,
1393
uint32_t indexCount,
1394
uint32_t instanceCount,
1395
uint32_t firstIndex,
1396
int32_t vertexOffset,
1397
uint32_t firstInstance)
1398
{
1399
panvk_stub();
1400
}
1401
1402
void
1403
panvk_CmdDrawIndirect(VkCommandBuffer commandBuffer,
1404
VkBuffer _buffer,
1405
VkDeviceSize offset,
1406
uint32_t drawCount,
1407
uint32_t stride)
1408
{
1409
panvk_stub();
1410
}
1411
1412
void
1413
panvk_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,
1414
VkBuffer _buffer,
1415
VkDeviceSize offset,
1416
uint32_t drawCount,
1417
uint32_t stride)
1418
{
1419
panvk_stub();
1420
}
1421
1422
void
1423
panvk_CmdDispatchBase(VkCommandBuffer commandBuffer,
1424
uint32_t base_x,
1425
uint32_t base_y,
1426
uint32_t base_z,
1427
uint32_t x,
1428
uint32_t y,
1429
uint32_t z)
1430
{
1431
panvk_stub();
1432
}
1433
1434
void
1435
panvk_CmdDispatch(VkCommandBuffer commandBuffer,
1436
uint32_t x,
1437
uint32_t y,
1438
uint32_t z)
1439
{
1440
panvk_stub();
1441
}
1442
1443
void
1444
panvk_CmdDispatchIndirect(VkCommandBuffer commandBuffer,
1445
VkBuffer _buffer,
1446
VkDeviceSize offset)
1447
{
1448
panvk_stub();
1449
}
1450
1451
void
1452
panvk_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
1453
const VkSubpassEndInfoKHR *pSubpassEndInfo)
1454
{
1455
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
1456
1457
panvk_cmd_close_batch(cmdbuf);
1458
vk_free(&cmdbuf->pool->alloc, cmdbuf->state.clear);
1459
cmdbuf->state.batch = NULL;
1460
cmdbuf->state.pass = NULL;
1461
cmdbuf->state.subpass = NULL;
1462
cmdbuf->state.framebuffer = NULL;
1463
cmdbuf->state.clear = NULL;
1464
memset(&cmdbuf->state.compute, 0, sizeof(cmdbuf->state.compute));
1465
}
1466
1467
void
1468
panvk_CmdEndRenderPass(VkCommandBuffer cmd)
1469
{
1470
VkSubpassEndInfoKHR einfo = {
1471
.sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO,
1472
};
1473
1474
panvk_CmdEndRenderPass2(cmd, &einfo);
1475
}
1476
1477
1478
void
1479
panvk_CmdPipelineBarrier(VkCommandBuffer commandBuffer,
1480
VkPipelineStageFlags srcStageMask,
1481
VkPipelineStageFlags destStageMask,
1482
VkDependencyFlags dependencyFlags,
1483
uint32_t memoryBarrierCount,
1484
const VkMemoryBarrier *pMemoryBarriers,
1485
uint32_t bufferMemoryBarrierCount,
1486
const VkBufferMemoryBarrier *pBufferMemoryBarriers,
1487
uint32_t imageMemoryBarrierCount,
1488
const VkImageMemoryBarrier *pImageMemoryBarriers)
1489
{
1490
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
1491
1492
/* Caches are flushed/invalidated at batch boundaries for now, nothing to do
1493
* for memory barriers assuming we implement barriers with the creation of a
1494
* new batch.
1495
* FIXME: We can probably do better with a CacheFlush job that has the
1496
* barrier flag set to true.
1497
*/
1498
if (cmdbuf->state.batch) {
1499
panvk_cmd_close_batch(cmdbuf);
1500
panvk_cmd_open_batch(cmdbuf);
1501
}
1502
}
1503
1504
static void
1505
panvk_add_set_event_operation(struct panvk_cmd_buffer *cmdbuf,
1506
struct panvk_event *event,
1507
enum panvk_event_op_type type)
1508
{
1509
struct panvk_event_op op = {
1510
.type = type,
1511
.event = event,
1512
};
1513
1514
if (cmdbuf->state.batch == NULL) {
1515
/* No open batch, let's create a new one so this operation happens in
1516
* the right order.
1517
*/
1518
panvk_cmd_open_batch(cmdbuf);
1519
util_dynarray_append(&cmdbuf->state.batch->event_ops,
1520
struct panvk_event_op,
1521
op);
1522
panvk_cmd_close_batch(cmdbuf);
1523
} else {
1524
/* Let's close the current batch so the operation executes before any
1525
* future commands.
1526
*/
1527
util_dynarray_append(&cmdbuf->state.batch->event_ops,
1528
struct panvk_event_op,
1529
op);
1530
panvk_cmd_close_batch(cmdbuf);
1531
panvk_cmd_open_batch(cmdbuf);
1532
}
1533
}
1534
1535
static void
1536
panvk_add_wait_event_operation(struct panvk_cmd_buffer *cmdbuf,
1537
struct panvk_event *event)
1538
{
1539
struct panvk_event_op op = {
1540
.type = PANVK_EVENT_OP_WAIT,
1541
.event = event,
1542
};
1543
1544
if (cmdbuf->state.batch == NULL) {
1545
/* No open batch, let's create a new one and have it wait for this event. */
1546
panvk_cmd_open_batch(cmdbuf);
1547
util_dynarray_append(&cmdbuf->state.batch->event_ops,
1548
struct panvk_event_op,
1549
op);
1550
} else {
1551
/* Let's close the current batch so any future commands wait on the
1552
* event signal operation.
1553
*/
1554
if (cmdbuf->state.batch->fragment_job ||
1555
cmdbuf->state.batch->scoreboard.first_job) {
1556
panvk_cmd_close_batch(cmdbuf);
1557
panvk_cmd_open_batch(cmdbuf);
1558
}
1559
util_dynarray_append(&cmdbuf->state.batch->event_ops,
1560
struct panvk_event_op,
1561
op);
1562
}
1563
}
1564
1565
void
1566
panvk_CmdSetEvent(VkCommandBuffer commandBuffer,
1567
VkEvent _event,
1568
VkPipelineStageFlags stageMask)
1569
{
1570
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
1571
VK_FROM_HANDLE(panvk_event, event, _event);
1572
1573
/* vkCmdSetEvent cannot be called inside a render pass */
1574
assert(cmdbuf->state.pass == NULL);
1575
1576
panvk_add_set_event_operation(cmdbuf, event, PANVK_EVENT_OP_SET);
1577
}
1578
1579
void
1580
panvk_CmdResetEvent(VkCommandBuffer commandBuffer,
1581
VkEvent _event,
1582
VkPipelineStageFlags stageMask)
1583
{
1584
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
1585
VK_FROM_HANDLE(panvk_event, event, _event);
1586
1587
/* vkCmdResetEvent cannot be called inside a render pass */
1588
assert(cmdbuf->state.pass == NULL);
1589
1590
panvk_add_set_event_operation(cmdbuf, event, PANVK_EVENT_OP_RESET);
1591
}
1592
1593
void
1594
panvk_CmdWaitEvents(VkCommandBuffer commandBuffer,
1595
uint32_t eventCount,
1596
const VkEvent *pEvents,
1597
VkPipelineStageFlags srcStageMask,
1598
VkPipelineStageFlags dstStageMask,
1599
uint32_t memoryBarrierCount,
1600
const VkMemoryBarrier *pMemoryBarriers,
1601
uint32_t bufferMemoryBarrierCount,
1602
const VkBufferMemoryBarrier *pBufferMemoryBarriers,
1603
uint32_t imageMemoryBarrierCount,
1604
const VkImageMemoryBarrier *pImageMemoryBarriers)
1605
{
1606
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
1607
1608
assert(eventCount > 0);
1609
1610
for (uint32_t i = 0; i < eventCount; i++) {
1611
VK_FROM_HANDLE(panvk_event, event, pEvents[i]);
1612
panvk_add_wait_event_operation(cmdbuf, event);
1613
}
1614
}
1615
1616
void
1617
panvk_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask)
1618
{
1619
panvk_stub();
1620
}
1621
1622