panvk_cmd_buffer.c revision 7ec681f3
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_private.h"
30#include "panfrost-quirks.h"
31
32#include "pan_encoder.h"
33
34#include "util/rounding.h"
35#include "vk_format.h"
36
37void
38panvk_CmdBindVertexBuffers(VkCommandBuffer commandBuffer,
39                           uint32_t firstBinding,
40                           uint32_t bindingCount,
41                           const VkBuffer *pBuffers,
42                           const VkDeviceSize *pOffsets)
43{
44   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
45
46   assert(firstBinding + bindingCount <= MAX_VBS);
47
48   for (uint32_t i = 0; i < bindingCount; i++) {
49      struct panvk_buffer *buf = panvk_buffer_from_handle(pBuffers[i]);
50
51      cmdbuf->state.vb.bufs[firstBinding + i].address = buf->bo->ptr.gpu + pOffsets[i];
52      cmdbuf->state.vb.bufs[firstBinding + i].size = buf->size - pOffsets[i];
53   }
54   cmdbuf->state.vb.count = MAX2(cmdbuf->state.vb.count, firstBinding + bindingCount);
55   cmdbuf->state.vb.attrib_bufs = cmdbuf->state.vb.attribs = 0;
56}
57
58void
59panvk_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,
60                         VkBuffer buffer,
61                         VkDeviceSize offset,
62                         VkIndexType indexType)
63{
64   panvk_stub();
65}
66
67void
68panvk_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
69                            VkPipelineBindPoint pipelineBindPoint,
70                            VkPipelineLayout _layout,
71                            uint32_t firstSet,
72                            uint32_t descriptorSetCount,
73                            const VkDescriptorSet *pDescriptorSets,
74                            uint32_t dynamicOffsetCount,
75                            const uint32_t *pDynamicOffsets)
76{
77   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
78   VK_FROM_HANDLE(panvk_pipeline_layout, layout, _layout);
79
80   struct panvk_descriptor_state *descriptors_state =
81      &cmdbuf->bind_points[pipelineBindPoint].desc_state;
82
83   for (unsigned i = 0; i < descriptorSetCount; ++i) {
84      unsigned idx = i + firstSet;
85      VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorSets[i]);
86
87      descriptors_state->sets[idx].set = set;
88
89      if (layout->num_dynoffsets) {
90         assert(dynamicOffsetCount >= set->layout->num_dynoffsets);
91
92         descriptors_state->sets[idx].dynoffsets =
93            pan_pool_alloc_aligned(&cmdbuf->desc_pool.base,
94                                   ALIGN(layout->num_dynoffsets, 4) *
95                                   sizeof(*pDynamicOffsets),
96                                   16);
97         memcpy(descriptors_state->sets[idx].dynoffsets.cpu,
98                pDynamicOffsets,
99                sizeof(*pDynamicOffsets) * set->layout->num_dynoffsets);
100         dynamicOffsetCount -= set->layout->num_dynoffsets;
101         pDynamicOffsets += set->layout->num_dynoffsets;
102      }
103
104      if (set->layout->num_ubos || set->layout->num_dynoffsets)
105         descriptors_state->ubos = 0;
106
107      if (set->layout->num_textures)
108         descriptors_state->textures = 0;
109
110      if (set->layout->num_samplers)
111         descriptors_state->samplers = 0;
112   }
113
114   assert(!dynamicOffsetCount);
115}
116
117void
118panvk_CmdPushConstants(VkCommandBuffer commandBuffer,
119                       VkPipelineLayout layout,
120                       VkShaderStageFlags stageFlags,
121                       uint32_t offset,
122                       uint32_t size,
123                       const void *pValues)
124{
125   panvk_stub();
126}
127
128void
129panvk_CmdBindPipeline(VkCommandBuffer commandBuffer,
130                      VkPipelineBindPoint pipelineBindPoint,
131                      VkPipeline _pipeline)
132{
133   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
134   VK_FROM_HANDLE(panvk_pipeline, pipeline, _pipeline);
135
136   cmdbuf->bind_points[pipelineBindPoint].pipeline = pipeline;
137   cmdbuf->state.fs_rsd = 0;
138   memset(cmdbuf->bind_points[pipelineBindPoint].desc_state.sysvals, 0,
139          sizeof(cmdbuf->bind_points[0].desc_state.sysvals));
140
141   if (pipelineBindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) {
142      cmdbuf->state.varyings = pipeline->varyings;
143
144      if (!(pipeline->dynamic_state_mask & BITFIELD_BIT(VK_DYNAMIC_STATE_VIEWPORT)))
145         cmdbuf->state.viewport = pipeline->viewport;
146      if (!(pipeline->dynamic_state_mask & BITFIELD_BIT(VK_DYNAMIC_STATE_SCISSOR)))
147         cmdbuf->state.scissor = pipeline->scissor;
148   }
149
150   /* Sysvals are passed through UBOs, we need dirty the UBO array if the
151    * pipeline contain shaders using sysvals.
152    */
153   if (pipeline->num_sysvals)
154      cmdbuf->bind_points[pipelineBindPoint].desc_state.ubos = 0;
155}
156
157void
158panvk_CmdSetViewport(VkCommandBuffer commandBuffer,
159                     uint32_t firstViewport,
160                     uint32_t viewportCount,
161                     const VkViewport *pViewports)
162{
163   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
164   assert(viewportCount == 1);
165   assert(!firstViewport);
166
167   cmdbuf->state.viewport = pViewports[0];
168   cmdbuf->state.vpd = 0;
169   cmdbuf->state.dirty |= PANVK_DYNAMIC_VIEWPORT;
170}
171
172void
173panvk_CmdSetScissor(VkCommandBuffer commandBuffer,
174                    uint32_t firstScissor,
175                    uint32_t scissorCount,
176                    const VkRect2D *pScissors)
177{
178   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
179   assert(scissorCount == 1);
180   assert(!firstScissor);
181
182   cmdbuf->state.scissor = pScissors[0];
183   cmdbuf->state.vpd = 0;
184   cmdbuf->state.dirty |= PANVK_DYNAMIC_SCISSOR;
185}
186
187void
188panvk_CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth)
189{
190   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
191
192   cmdbuf->state.rast.line_width = lineWidth;
193   cmdbuf->state.dirty |= PANVK_DYNAMIC_LINE_WIDTH;
194}
195
196void
197panvk_CmdSetDepthBias(VkCommandBuffer commandBuffer,
198                      float depthBiasConstantFactor,
199                      float depthBiasClamp,
200                      float depthBiasSlopeFactor)
201{
202   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
203
204   cmdbuf->state.rast.depth_bias.constant_factor = depthBiasConstantFactor;
205   cmdbuf->state.rast.depth_bias.clamp = depthBiasClamp;
206   cmdbuf->state.rast.depth_bias.slope_factor = depthBiasSlopeFactor;
207   cmdbuf->state.dirty |= PANVK_DYNAMIC_DEPTH_BIAS;
208   cmdbuf->state.fs_rsd = 0;
209}
210
211void
212panvk_CmdSetBlendConstants(VkCommandBuffer commandBuffer,
213                           const float blendConstants[4])
214{
215   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
216
217   for (unsigned i = 0; i < 4; i++)
218      cmdbuf->state.blend.constants[i] = CLAMP(blendConstants[i], 0.0f, 1.0f);
219
220   cmdbuf->state.dirty |= PANVK_DYNAMIC_BLEND_CONSTANTS;
221   cmdbuf->state.fs_rsd = 0;
222}
223
224void
225panvk_CmdSetDepthBounds(VkCommandBuffer commandBuffer,
226                        float minDepthBounds,
227                        float maxDepthBounds)
228{
229   panvk_stub();
230}
231
232void
233panvk_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
234                               VkStencilFaceFlags faceMask,
235                               uint32_t compareMask)
236{
237   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
238
239   if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
240      cmdbuf->state.zs.s_front.compare_mask = compareMask;
241
242   if (faceMask & VK_STENCIL_FACE_BACK_BIT)
243      cmdbuf->state.zs.s_back.compare_mask = compareMask;
244
245   cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_COMPARE_MASK;
246   cmdbuf->state.fs_rsd = 0;
247}
248
249void
250panvk_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer,
251                             VkStencilFaceFlags faceMask,
252                             uint32_t writeMask)
253{
254   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
255
256   if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
257      cmdbuf->state.zs.s_front.write_mask = writeMask;
258
259   if (faceMask & VK_STENCIL_FACE_BACK_BIT)
260      cmdbuf->state.zs.s_back.write_mask = writeMask;
261
262   cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_WRITE_MASK;
263   cmdbuf->state.fs_rsd = 0;
264}
265
266void
267panvk_CmdSetStencilReference(VkCommandBuffer commandBuffer,
268                             VkStencilFaceFlags faceMask,
269                             uint32_t reference)
270{
271   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
272
273   if (faceMask & VK_STENCIL_FACE_FRONT_BIT)
274      cmdbuf->state.zs.s_front.ref = reference;
275
276   if (faceMask & VK_STENCIL_FACE_BACK_BIT)
277      cmdbuf->state.zs.s_back.ref = reference;
278
279   cmdbuf->state.dirty |= PANVK_DYNAMIC_STENCIL_REFERENCE;
280   cmdbuf->state.fs_rsd = 0;
281}
282
283void
284panvk_CmdExecuteCommands(VkCommandBuffer commandBuffer,
285                         uint32_t commandBufferCount,
286                         const VkCommandBuffer *pCmdBuffers)
287{
288   panvk_stub();
289}
290
291VkResult
292panvk_CreateCommandPool(VkDevice _device,
293                        const VkCommandPoolCreateInfo *pCreateInfo,
294                        const VkAllocationCallbacks *pAllocator,
295                        VkCommandPool *pCmdPool)
296{
297   VK_FROM_HANDLE(panvk_device, device, _device);
298   struct panvk_cmd_pool *pool;
299
300   pool = vk_object_alloc(&device->vk, pAllocator, sizeof(*pool),
301                          VK_OBJECT_TYPE_COMMAND_POOL);
302   if (pool == NULL)
303      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
304
305   if (pAllocator)
306      pool->alloc = *pAllocator;
307   else
308      pool->alloc = device->vk.alloc;
309
310   list_inithead(&pool->active_cmd_buffers);
311   list_inithead(&pool->free_cmd_buffers);
312
313   pool->queue_family_index = pCreateInfo->queueFamilyIndex;
314   panvk_bo_pool_init(&pool->desc_bo_pool);
315   panvk_bo_pool_init(&pool->varying_bo_pool);
316   panvk_bo_pool_init(&pool->tls_bo_pool);
317   *pCmdPool = panvk_cmd_pool_to_handle(pool);
318   return VK_SUCCESS;
319}
320
321static void
322panvk_cmd_prepare_clear_values(struct panvk_cmd_buffer *cmdbuf,
323                               const VkClearValue *in)
324{
325   for (unsigned i = 0; i < cmdbuf->state.pass->attachment_count; i++) {
326       const struct panvk_render_pass_attachment *attachment =
327          &cmdbuf->state.pass->attachments[i];
328       enum pipe_format fmt = attachment->format;
329
330       if (util_format_is_depth_or_stencil(fmt)) {
331          if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR ||
332              attachment->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
333             cmdbuf->state.clear[i].depth = in[i].depthStencil.depth;
334             cmdbuf->state.clear[i].stencil = in[i].depthStencil.stencil;
335          } else {
336             cmdbuf->state.clear[i].depth = 0;
337             cmdbuf->state.clear[i].stencil = 0;
338          }
339       } else {
340          if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
341             union pipe_color_union *col = (union pipe_color_union *) &in[i].color;
342             pan_pack_color(cmdbuf->state.clear[i].color, col, fmt, false);
343          } else {
344             memset(cmdbuf->state.clear[i].color, 0, sizeof(cmdbuf->state.clear[0].color));
345          }
346       }
347   }
348}
349
350void
351panvk_cmd_fb_info_set_subpass(struct panvk_cmd_buffer *cmdbuf)
352{
353   const struct panvk_subpass *subpass = cmdbuf->state.subpass;
354   struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info;
355   const struct panvk_framebuffer *fb = cmdbuf->state.framebuffer;
356   const struct panvk_clear_value *clears = cmdbuf->state.clear;
357   struct panvk_image_view *view;
358
359   fbinfo->nr_samples = 1;
360   fbinfo->rt_count = subpass->color_count;
361   memset(&fbinfo->bifrost.pre_post.dcds, 0, sizeof(fbinfo->bifrost.pre_post.dcds));
362
363   for (unsigned cb = 0; cb < subpass->color_count; cb++) {
364      int idx = subpass->color_attachments[cb].idx;
365      view = idx != VK_ATTACHMENT_UNUSED ?
366             fb->attachments[idx].iview : NULL;
367      if (!view)
368         continue;
369      fbinfo->rts[cb].view = &view->pview;
370      fbinfo->rts[cb].clear = subpass->color_attachments[cb].clear;
371      fbinfo->rts[cb].preload = subpass->color_attachments[cb].preload;
372      fbinfo->rts[cb].crc_valid = &cmdbuf->state.fb.crc_valid[cb];
373
374      memcpy(fbinfo->rts[cb].clear_value, clears[idx].color,
375             sizeof(fbinfo->rts[cb].clear_value));
376      fbinfo->nr_samples =
377         MAX2(fbinfo->nr_samples, view->pview.image->layout.nr_samples);
378   }
379
380   if (subpass->zs_attachment.idx != VK_ATTACHMENT_UNUSED) {
381      view = fb->attachments[subpass->zs_attachment.idx].iview;
382      const struct util_format_description *fdesc =
383         util_format_description(view->pview.format);
384
385      fbinfo->nr_samples =
386         MAX2(fbinfo->nr_samples, view->pview.image->layout.nr_samples);
387
388      if (util_format_has_depth(fdesc)) {
389         fbinfo->zs.clear.z = subpass->zs_attachment.clear;
390         fbinfo->zs.clear_value.depth = clears[subpass->zs_attachment.idx].depth;
391         fbinfo->zs.view.zs = &view->pview;
392      }
393
394      if (util_format_has_stencil(fdesc)) {
395         fbinfo->zs.clear.s = subpass->zs_attachment.clear;
396         fbinfo->zs.clear_value.stencil = clears[subpass->zs_attachment.idx].stencil;
397         if (!fbinfo->zs.view.zs)
398            fbinfo->zs.view.s = &view->pview;
399      }
400   }
401}
402
403void
404panvk_cmd_fb_info_init(struct panvk_cmd_buffer *cmdbuf)
405{
406   struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info;
407   const struct panvk_framebuffer *fb = cmdbuf->state.framebuffer;
408
409   memset(cmdbuf->state.fb.crc_valid, 0, sizeof(cmdbuf->state.fb.crc_valid));
410
411   *fbinfo = (struct pan_fb_info) {
412      .width = fb->width,
413      .height = fb->height,
414      .extent.maxx = fb->width - 1,
415      .extent.maxy = fb->height - 1,
416   };
417}
418
419void
420panvk_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,
421                          const VkRenderPassBeginInfo *pRenderPassBegin,
422                          const VkSubpassBeginInfo *pSubpassBeginInfo)
423{
424   VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
425   VK_FROM_HANDLE(panvk_render_pass, pass, pRenderPassBegin->renderPass);
426   VK_FROM_HANDLE(panvk_framebuffer, fb, pRenderPassBegin->framebuffer);
427
428   cmdbuf->state.pass = pass;
429   cmdbuf->state.subpass = pass->subpasses;
430   cmdbuf->state.framebuffer = fb;
431   cmdbuf->state.render_area = pRenderPassBegin->renderArea;
432   cmdbuf->state.batch = vk_zalloc(&cmdbuf->pool->alloc,
433                                   sizeof(*cmdbuf->state.batch), 8,
434                                   VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
435   util_dynarray_init(&cmdbuf->state.batch->jobs, NULL);
436   util_dynarray_init(&cmdbuf->state.batch->event_ops, NULL);
437   assert(pRenderPassBegin->clearValueCount <= pass->attachment_count);
438   cmdbuf->state.clear =
439      vk_zalloc(&cmdbuf->pool->alloc,
440                sizeof(*cmdbuf->state.clear) * pass->attachment_count,
441                8, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
442   panvk_cmd_prepare_clear_values(cmdbuf, pRenderPassBegin->pClearValues);
443   panvk_cmd_fb_info_init(cmdbuf);
444   panvk_cmd_fb_info_set_subpass(cmdbuf);
445}
446
447void
448panvk_CmdBeginRenderPass(VkCommandBuffer cmd,
449                         const VkRenderPassBeginInfo *info,
450                         VkSubpassContents contents)
451{
452   VkSubpassBeginInfo subpass_info = {
453      .sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO,
454      .contents = contents
455   };
456
457   return panvk_CmdBeginRenderPass2(cmd, info, &subpass_info);
458}
459
460void
461panvk_cmd_preload_fb_after_batch_split(struct panvk_cmd_buffer *cmdbuf)
462{
463   for (unsigned i = 0; i < cmdbuf->state.fb.info.rt_count; i++) {
464      if (cmdbuf->state.fb.info.rts[i].view) {
465         cmdbuf->state.fb.info.rts[i].clear = false;
466         cmdbuf->state.fb.info.rts[i].preload = true;
467      }
468   }
469
470   if (cmdbuf->state.fb.info.zs.view.zs) {
471      cmdbuf->state.fb.info.zs.clear.z = false;
472      cmdbuf->state.fb.info.zs.preload.z = true;
473   }
474
475   if (cmdbuf->state.fb.info.zs.view.s ||
476       (cmdbuf->state.fb.info.zs.view.zs &&
477        util_format_is_depth_and_stencil(cmdbuf->state.fb.info.zs.view.zs->format))) {
478      cmdbuf->state.fb.info.zs.clear.s = false;
479      cmdbuf->state.fb.info.zs.preload.s = true;
480   }
481}
482
483struct panvk_batch *
484panvk_cmd_open_batch(struct panvk_cmd_buffer *cmdbuf)
485{
486   assert(!cmdbuf->state.batch);
487   cmdbuf->state.batch = vk_zalloc(&cmdbuf->pool->alloc,
488                                   sizeof(*cmdbuf->state.batch), 8,
489                                   VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
490   assert(cmdbuf->state.batch);
491   return cmdbuf->state.batch;
492}
493
494void
495panvk_CmdDrawIndexed(VkCommandBuffer commandBuffer,
496                     uint32_t indexCount,
497                     uint32_t instanceCount,
498                     uint32_t firstIndex,
499                     int32_t vertexOffset,
500                     uint32_t firstInstance)
501{
502   panvk_stub();
503}
504
505void
506panvk_CmdDrawIndirect(VkCommandBuffer commandBuffer,
507                      VkBuffer _buffer,
508                      VkDeviceSize offset,
509                      uint32_t drawCount,
510                      uint32_t stride)
511{
512   panvk_stub();
513}
514
515void
516panvk_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,
517                             VkBuffer _buffer,
518                             VkDeviceSize offset,
519                             uint32_t drawCount,
520                             uint32_t stride)
521{
522   panvk_stub();
523}
524
525void
526panvk_CmdDispatchBase(VkCommandBuffer commandBuffer,
527                      uint32_t base_x,
528                      uint32_t base_y,
529                      uint32_t base_z,
530                      uint32_t x,
531                      uint32_t y,
532                      uint32_t z)
533{
534   panvk_stub();
535}
536
537void
538panvk_CmdDispatch(VkCommandBuffer commandBuffer,
539                  uint32_t x,
540                  uint32_t y,
541                  uint32_t z)
542{
543   panvk_stub();
544}
545
546void
547panvk_CmdDispatchIndirect(VkCommandBuffer commandBuffer,
548                          VkBuffer _buffer,
549                          VkDeviceSize offset)
550{
551   panvk_stub();
552}
553
554void
555panvk_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask)
556{
557   panvk_stub();
558}
559