1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2021 Collabora Ltd.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "genxml/gen_macros.h"
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "util/macros.h"
27bf215546Sopenharmony_ci#include "compiler/shader_enums.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "vk_util.h"
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include "pan_cs.h"
32bf215546Sopenharmony_ci#include "pan_encoder.h"
33bf215546Sopenharmony_ci#include "pan_pool.h"
34bf215546Sopenharmony_ci#include "pan_shader.h"
35bf215546Sopenharmony_ci#include "pan_earlyzs.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci#include "panvk_cs.h"
38bf215546Sopenharmony_ci#include "panvk_private.h"
39bf215546Sopenharmony_ci#include "panvk_varyings.h"
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#include "vk_sampler.h"
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_cistatic enum mali_mipmap_mode
44bf215546Sopenharmony_cipanvk_translate_sampler_mipmap_mode(VkSamplerMipmapMode mode)
45bf215546Sopenharmony_ci{
46bf215546Sopenharmony_ci   switch (mode) {
47bf215546Sopenharmony_ci   case VK_SAMPLER_MIPMAP_MODE_NEAREST: return MALI_MIPMAP_MODE_NEAREST;
48bf215546Sopenharmony_ci   case VK_SAMPLER_MIPMAP_MODE_LINEAR: return MALI_MIPMAP_MODE_TRILINEAR;
49bf215546Sopenharmony_ci   default: unreachable("Invalid mipmap mode");
50bf215546Sopenharmony_ci   }
51bf215546Sopenharmony_ci}
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_cistatic unsigned
54bf215546Sopenharmony_cipanvk_translate_sampler_address_mode(VkSamplerAddressMode mode)
55bf215546Sopenharmony_ci{
56bf215546Sopenharmony_ci   switch (mode) {
57bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_REPEAT: return MALI_WRAP_MODE_REPEAT;
58bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return MALI_WRAP_MODE_MIRRORED_REPEAT;
59bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return MALI_WRAP_MODE_CLAMP_TO_EDGE;
60bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return MALI_WRAP_MODE_CLAMP_TO_BORDER;
61bf215546Sopenharmony_ci   case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: return MALI_WRAP_MODE_MIRRORED_CLAMP_TO_EDGE;
62bf215546Sopenharmony_ci   default: unreachable("Invalid wrap");
63bf215546Sopenharmony_ci   }
64bf215546Sopenharmony_ci}
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_cistatic mali_pixel_format
67bf215546Sopenharmony_cipanvk_varying_hw_format(const struct panvk_device *dev,
68bf215546Sopenharmony_ci                        const struct panvk_varyings_info *varyings,
69bf215546Sopenharmony_ci                        gl_shader_stage stage, unsigned idx)
70bf215546Sopenharmony_ci{
71bf215546Sopenharmony_ci   const struct panfrost_device *pdev = &dev->physical_device->pdev;
72bf215546Sopenharmony_ci   gl_varying_slot loc = varyings->stage[stage].loc[idx];
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci   switch (loc) {
75bf215546Sopenharmony_ci   case VARYING_SLOT_PNTC:
76bf215546Sopenharmony_ci   case VARYING_SLOT_PSIZ:
77bf215546Sopenharmony_ci#if PAN_ARCH <= 6
78bf215546Sopenharmony_ci      return (MALI_R16F << 12) | panfrost_get_default_swizzle(1);
79bf215546Sopenharmony_ci#else
80bf215546Sopenharmony_ci      return (MALI_R16F << 12) | MALI_RGB_COMPONENT_ORDER_R000;
81bf215546Sopenharmony_ci#endif
82bf215546Sopenharmony_ci   case VARYING_SLOT_POS:
83bf215546Sopenharmony_ci#if PAN_ARCH <= 6
84bf215546Sopenharmony_ci      return (MALI_SNAP_4 << 12) | panfrost_get_default_swizzle(4);
85bf215546Sopenharmony_ci#else
86bf215546Sopenharmony_ci      return (MALI_SNAP_4 << 12) | MALI_RGB_COMPONENT_ORDER_RGBA;
87bf215546Sopenharmony_ci#endif
88bf215546Sopenharmony_ci   default:
89bf215546Sopenharmony_ci      if (varyings->varying[loc].format != PIPE_FORMAT_NONE)
90bf215546Sopenharmony_ci         return pdev->formats[varyings->varying[loc].format].hw;
91bf215546Sopenharmony_ci#if PAN_ARCH >= 7
92bf215546Sopenharmony_ci      return (MALI_CONSTANT << 12) | MALI_RGB_COMPONENT_ORDER_0000;
93bf215546Sopenharmony_ci#else
94bf215546Sopenharmony_ci      return (MALI_CONSTANT << 12) | PAN_V6_SWIZZLE(0, 0, 0, 0);
95bf215546Sopenharmony_ci#endif
96bf215546Sopenharmony_ci   }
97bf215546Sopenharmony_ci}
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_cistatic void
100bf215546Sopenharmony_cipanvk_emit_varying(const struct panvk_device *dev,
101bf215546Sopenharmony_ci                   const struct panvk_varyings_info *varyings,
102bf215546Sopenharmony_ci                   gl_shader_stage stage, unsigned idx,
103bf215546Sopenharmony_ci                   void *attrib)
104bf215546Sopenharmony_ci{
105bf215546Sopenharmony_ci   gl_varying_slot loc = varyings->stage[stage].loc[idx];
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   pan_pack(attrib, ATTRIBUTE, cfg) {
108bf215546Sopenharmony_ci      cfg.buffer_index = varyings->varying[loc].buf;
109bf215546Sopenharmony_ci      cfg.offset = varyings->varying[loc].offset;
110bf215546Sopenharmony_ci      cfg.format = panvk_varying_hw_format(dev, varyings, stage, idx);
111bf215546Sopenharmony_ci   }
112bf215546Sopenharmony_ci}
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_civoid
115bf215546Sopenharmony_cipanvk_per_arch(emit_varyings)(const struct panvk_device *dev,
116bf215546Sopenharmony_ci                              const struct panvk_varyings_info *varyings,
117bf215546Sopenharmony_ci                              gl_shader_stage stage,
118bf215546Sopenharmony_ci                              void *descs)
119bf215546Sopenharmony_ci{
120bf215546Sopenharmony_ci   struct mali_attribute_packed *attrib = descs;
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   for (unsigned i = 0; i < varyings->stage[stage].count; i++)
123bf215546Sopenharmony_ci      panvk_emit_varying(dev, varyings, stage, i, attrib++);
124bf215546Sopenharmony_ci}
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_cistatic void
127bf215546Sopenharmony_cipanvk_emit_varying_buf(const struct panvk_varyings_info *varyings,
128bf215546Sopenharmony_ci                       enum panvk_varying_buf_id id, void *buf)
129bf215546Sopenharmony_ci{
130bf215546Sopenharmony_ci   unsigned buf_idx = panvk_varying_buf_index(varyings, id);
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   pan_pack(buf, ATTRIBUTE_BUFFER, cfg) {
133bf215546Sopenharmony_ci      unsigned offset = varyings->buf[buf_idx].address & 63;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci      cfg.stride = varyings->buf[buf_idx].stride;
136bf215546Sopenharmony_ci      cfg.size = varyings->buf[buf_idx].size + offset;
137bf215546Sopenharmony_ci      cfg.pointer = varyings->buf[buf_idx].address & ~63ULL;
138bf215546Sopenharmony_ci   }
139bf215546Sopenharmony_ci}
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_civoid
142bf215546Sopenharmony_cipanvk_per_arch(emit_varying_bufs)(const struct panvk_varyings_info *varyings,
143bf215546Sopenharmony_ci                                  void *descs)
144bf215546Sopenharmony_ci{
145bf215546Sopenharmony_ci   struct mali_attribute_buffer_packed *buf = descs;
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci   for (unsigned i = 0; i < PANVK_VARY_BUF_MAX; i++) {
148bf215546Sopenharmony_ci      if (varyings->buf_mask & (1 << i))
149bf215546Sopenharmony_ci         panvk_emit_varying_buf(varyings, i, buf++);
150bf215546Sopenharmony_ci   }
151bf215546Sopenharmony_ci}
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_cistatic void
154bf215546Sopenharmony_cipanvk_emit_attrib_buf(const struct panvk_attribs_info *info,
155bf215546Sopenharmony_ci                      const struct panvk_draw_info *draw,
156bf215546Sopenharmony_ci                      const struct panvk_attrib_buf *bufs,
157bf215546Sopenharmony_ci                      unsigned buf_count,
158bf215546Sopenharmony_ci                      unsigned idx, void *desc)
159bf215546Sopenharmony_ci{
160bf215546Sopenharmony_ci   const struct panvk_attrib_buf_info *buf_info = &info->buf[idx];
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   assert(idx < buf_count);
163bf215546Sopenharmony_ci   const struct panvk_attrib_buf *buf = &bufs[idx];
164bf215546Sopenharmony_ci   mali_ptr addr = buf->address & ~63ULL;
165bf215546Sopenharmony_ci   unsigned size = buf->size + (buf->address & 63);
166bf215546Sopenharmony_ci   unsigned divisor =
167bf215546Sopenharmony_ci      draw->padded_vertex_count * buf_info->instance_divisor;
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci   /* TODO: support instanced arrays */
170bf215546Sopenharmony_ci   if (draw->instance_count <= 1) {
171bf215546Sopenharmony_ci      pan_pack(desc, ATTRIBUTE_BUFFER, cfg) {
172bf215546Sopenharmony_ci         cfg.type = MALI_ATTRIBUTE_TYPE_1D;
173bf215546Sopenharmony_ci         cfg.stride = buf_info->per_instance ? 0 : buf_info->stride;
174bf215546Sopenharmony_ci         cfg.pointer = addr;
175bf215546Sopenharmony_ci         cfg.size = size;
176bf215546Sopenharmony_ci      }
177bf215546Sopenharmony_ci   } else if (!buf_info->per_instance) {
178bf215546Sopenharmony_ci      pan_pack(desc, ATTRIBUTE_BUFFER, cfg) {
179bf215546Sopenharmony_ci         cfg.type = MALI_ATTRIBUTE_TYPE_1D_MODULUS;
180bf215546Sopenharmony_ci         cfg.divisor = draw->padded_vertex_count;
181bf215546Sopenharmony_ci         cfg.stride = buf_info->stride;
182bf215546Sopenharmony_ci         cfg.pointer = addr;
183bf215546Sopenharmony_ci         cfg.size = size;
184bf215546Sopenharmony_ci      }
185bf215546Sopenharmony_ci   } else if (!divisor) {
186bf215546Sopenharmony_ci      /* instance_divisor == 0 means all instances share the same value.
187bf215546Sopenharmony_ci       * Make it a 1D array with a zero stride.
188bf215546Sopenharmony_ci       */
189bf215546Sopenharmony_ci      pan_pack(desc, ATTRIBUTE_BUFFER, cfg) {
190bf215546Sopenharmony_ci         cfg.type = MALI_ATTRIBUTE_TYPE_1D;
191bf215546Sopenharmony_ci         cfg.stride = 0;
192bf215546Sopenharmony_ci         cfg.pointer = addr;
193bf215546Sopenharmony_ci         cfg.size = size;
194bf215546Sopenharmony_ci      }
195bf215546Sopenharmony_ci   } else if (util_is_power_of_two_or_zero(divisor)) {
196bf215546Sopenharmony_ci      pan_pack(desc, ATTRIBUTE_BUFFER, cfg) {
197bf215546Sopenharmony_ci         cfg.type = MALI_ATTRIBUTE_TYPE_1D_POT_DIVISOR;
198bf215546Sopenharmony_ci         cfg.stride = buf_info->stride;
199bf215546Sopenharmony_ci         cfg.pointer = addr;
200bf215546Sopenharmony_ci         cfg.size = size;
201bf215546Sopenharmony_ci         cfg.divisor_r = __builtin_ctz(divisor);
202bf215546Sopenharmony_ci      }
203bf215546Sopenharmony_ci   } else {
204bf215546Sopenharmony_ci      unsigned divisor_r = 0, divisor_e = 0;
205bf215546Sopenharmony_ci      unsigned divisor_num =
206bf215546Sopenharmony_ci         panfrost_compute_magic_divisor(divisor, &divisor_r, &divisor_e);
207bf215546Sopenharmony_ci      pan_pack(desc, ATTRIBUTE_BUFFER, cfg) {
208bf215546Sopenharmony_ci         cfg.type = MALI_ATTRIBUTE_TYPE_1D_NPOT_DIVISOR;
209bf215546Sopenharmony_ci         cfg.stride = buf_info->stride;
210bf215546Sopenharmony_ci         cfg.pointer = addr;
211bf215546Sopenharmony_ci         cfg.size = size;
212bf215546Sopenharmony_ci         cfg.divisor_r = divisor_r;
213bf215546Sopenharmony_ci         cfg.divisor_e = divisor_e;
214bf215546Sopenharmony_ci      }
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci      desc += pan_size(ATTRIBUTE_BUFFER);
217bf215546Sopenharmony_ci      pan_pack(desc, ATTRIBUTE_BUFFER_CONTINUATION_NPOT, cfg) {
218bf215546Sopenharmony_ci         cfg.divisor_numerator = divisor_num;
219bf215546Sopenharmony_ci         cfg.divisor = buf_info->instance_divisor;
220bf215546Sopenharmony_ci      }
221bf215546Sopenharmony_ci   }
222bf215546Sopenharmony_ci}
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_civoid
225bf215546Sopenharmony_cipanvk_per_arch(emit_attrib_bufs)(const struct panvk_attribs_info *info,
226bf215546Sopenharmony_ci                                 const struct panvk_attrib_buf *bufs,
227bf215546Sopenharmony_ci                                 unsigned buf_count,
228bf215546Sopenharmony_ci                                 const struct panvk_draw_info *draw,
229bf215546Sopenharmony_ci                                 void *descs)
230bf215546Sopenharmony_ci{
231bf215546Sopenharmony_ci   struct mali_attribute_buffer_packed *buf = descs;
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci   for (unsigned i = 0; i < info->buf_count; i++) {
234bf215546Sopenharmony_ci      panvk_emit_attrib_buf(info, draw, bufs, buf_count, i, buf);
235bf215546Sopenharmony_ci      buf += 2;
236bf215546Sopenharmony_ci   }
237bf215546Sopenharmony_ci}
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_civoid
240bf215546Sopenharmony_cipanvk_per_arch(emit_sampler)(const VkSamplerCreateInfo *pCreateInfo,
241bf215546Sopenharmony_ci                             void *desc)
242bf215546Sopenharmony_ci{
243bf215546Sopenharmony_ci   VkClearColorValue border_color =
244bf215546Sopenharmony_ci      vk_sampler_border_color_value(pCreateInfo, NULL);
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci   pan_pack(desc, SAMPLER, cfg) {
247bf215546Sopenharmony_ci      cfg.magnify_nearest = pCreateInfo->magFilter == VK_FILTER_NEAREST;
248bf215546Sopenharmony_ci      cfg.minify_nearest = pCreateInfo->minFilter == VK_FILTER_NEAREST;
249bf215546Sopenharmony_ci      cfg.mipmap_mode = panvk_translate_sampler_mipmap_mode(pCreateInfo->mipmapMode);
250bf215546Sopenharmony_ci      cfg.normalized_coordinates = !pCreateInfo->unnormalizedCoordinates;
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci      cfg.lod_bias = FIXED_16(pCreateInfo->mipLodBias, true);
253bf215546Sopenharmony_ci      cfg.minimum_lod = FIXED_16(pCreateInfo->minLod, false);
254bf215546Sopenharmony_ci      cfg.maximum_lod = FIXED_16(pCreateInfo->maxLod, false);
255bf215546Sopenharmony_ci      cfg.wrap_mode_s = panvk_translate_sampler_address_mode(pCreateInfo->addressModeU);
256bf215546Sopenharmony_ci      cfg.wrap_mode_t = panvk_translate_sampler_address_mode(pCreateInfo->addressModeV);
257bf215546Sopenharmony_ci      cfg.wrap_mode_r = panvk_translate_sampler_address_mode(pCreateInfo->addressModeW);
258bf215546Sopenharmony_ci      cfg.compare_function = panvk_per_arch(translate_sampler_compare_func)(pCreateInfo);
259bf215546Sopenharmony_ci      cfg.border_color_r = border_color.uint32[0];
260bf215546Sopenharmony_ci      cfg.border_color_g = border_color.uint32[1];
261bf215546Sopenharmony_ci      cfg.border_color_b = border_color.uint32[2];
262bf215546Sopenharmony_ci      cfg.border_color_a = border_color.uint32[3];
263bf215546Sopenharmony_ci   }
264bf215546Sopenharmony_ci}
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_cistatic void
267bf215546Sopenharmony_cipanvk_emit_attrib(const struct panvk_device *dev,
268bf215546Sopenharmony_ci                  const struct panvk_draw_info *draw,
269bf215546Sopenharmony_ci                  const struct panvk_attribs_info *attribs,
270bf215546Sopenharmony_ci                  const struct panvk_attrib_buf *bufs,
271bf215546Sopenharmony_ci                  unsigned buf_count,
272bf215546Sopenharmony_ci                  unsigned idx, void *attrib)
273bf215546Sopenharmony_ci{
274bf215546Sopenharmony_ci   const struct panfrost_device *pdev = &dev->physical_device->pdev;
275bf215546Sopenharmony_ci   unsigned buf_idx = attribs->attrib[idx].buf;
276bf215546Sopenharmony_ci   const struct panvk_attrib_buf_info *buf_info = &attribs->buf[buf_idx];
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci   pan_pack(attrib, ATTRIBUTE, cfg) {
279bf215546Sopenharmony_ci      cfg.buffer_index = buf_idx * 2;
280bf215546Sopenharmony_ci      cfg.offset = attribs->attrib[idx].offset +
281bf215546Sopenharmony_ci                   (bufs[buf_idx].address & 63);
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci      if (buf_info->per_instance)
284bf215546Sopenharmony_ci         cfg.offset += draw->first_instance * buf_info->stride;
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci      cfg.format = pdev->formats[attribs->attrib[idx].format].hw;
287bf215546Sopenharmony_ci   }
288bf215546Sopenharmony_ci}
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_civoid
291bf215546Sopenharmony_cipanvk_per_arch(emit_attribs)(const struct panvk_device *dev,
292bf215546Sopenharmony_ci                             const struct panvk_draw_info *draw,
293bf215546Sopenharmony_ci                             const struct panvk_attribs_info *attribs,
294bf215546Sopenharmony_ci                             const struct panvk_attrib_buf *bufs,
295bf215546Sopenharmony_ci                             unsigned buf_count,
296bf215546Sopenharmony_ci                             void *descs)
297bf215546Sopenharmony_ci{
298bf215546Sopenharmony_ci   struct mali_attribute_packed *attrib = descs;
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci   for (unsigned i = 0; i < attribs->attrib_count; i++)
301bf215546Sopenharmony_ci      panvk_emit_attrib(dev, draw, attribs, bufs, buf_count, i, attrib++);
302bf215546Sopenharmony_ci}
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_civoid
305bf215546Sopenharmony_cipanvk_per_arch(emit_ubo)(mali_ptr address, size_t size,  void *desc)
306bf215546Sopenharmony_ci{
307bf215546Sopenharmony_ci   pan_pack(desc, UNIFORM_BUFFER, cfg) {
308bf215546Sopenharmony_ci      cfg.pointer = address;
309bf215546Sopenharmony_ci      cfg.entries = DIV_ROUND_UP(size, 16);
310bf215546Sopenharmony_ci   }
311bf215546Sopenharmony_ci}
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_civoid
314bf215546Sopenharmony_cipanvk_per_arch(emit_ubos)(const struct panvk_pipeline *pipeline,
315bf215546Sopenharmony_ci                          const struct panvk_descriptor_state *state,
316bf215546Sopenharmony_ci                          void *descs)
317bf215546Sopenharmony_ci{
318bf215546Sopenharmony_ci   struct mali_uniform_buffer_packed *ubos = descs;
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_ci   panvk_per_arch(emit_ubo)(state->sysvals_ptr,
321bf215546Sopenharmony_ci                            sizeof(state->sysvals),
322bf215546Sopenharmony_ci                            &ubos[PANVK_SYSVAL_UBO_INDEX]);
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ci   if (pipeline->layout->push_constants.size) {
325bf215546Sopenharmony_ci      panvk_per_arch(emit_ubo)(state->push_constants,
326bf215546Sopenharmony_ci                               ALIGN_POT(pipeline->layout->push_constants.size, 16),
327bf215546Sopenharmony_ci                               &ubos[PANVK_PUSH_CONST_UBO_INDEX]);
328bf215546Sopenharmony_ci   } else {
329bf215546Sopenharmony_ci      memset(&ubos[PANVK_PUSH_CONST_UBO_INDEX], 0, sizeof(*ubos));
330bf215546Sopenharmony_ci   }
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci   for (unsigned s = 0; s < pipeline->layout->vk.set_count; s++) {
333bf215546Sopenharmony_ci      const struct panvk_descriptor_set_layout *set_layout =
334bf215546Sopenharmony_ci         vk_to_panvk_descriptor_set_layout(pipeline->layout->vk.set_layouts[s]);
335bf215546Sopenharmony_ci      const struct panvk_descriptor_set *set = state->sets[s];
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci      unsigned ubo_start =
338bf215546Sopenharmony_ci         panvk_pipeline_layout_ubo_start(pipeline->layout, s, false);
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_ci      if (!set) {
341bf215546Sopenharmony_ci         unsigned all_ubos = set_layout->num_ubos + set_layout->num_dyn_ubos;
342bf215546Sopenharmony_ci         memset(&ubos[ubo_start], 0, all_ubos * sizeof(*ubos));
343bf215546Sopenharmony_ci      } else {
344bf215546Sopenharmony_ci         memcpy(&ubos[ubo_start], set->ubos,
345bf215546Sopenharmony_ci                set_layout->num_ubos * sizeof(*ubos));
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci         unsigned dyn_ubo_start =
348bf215546Sopenharmony_ci            panvk_pipeline_layout_ubo_start(pipeline->layout, s, true);
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci         for (unsigned i = 0; i < set_layout->num_dyn_ubos; i++) {
351bf215546Sopenharmony_ci            const struct panvk_buffer_desc *bdesc =
352bf215546Sopenharmony_ci               &state->dyn.ubos[pipeline->layout->sets[s].dyn_ubo_offset + i];
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci            mali_ptr address = panvk_buffer_gpu_ptr(bdesc->buffer,
355bf215546Sopenharmony_ci                                                    bdesc->offset);
356bf215546Sopenharmony_ci            size_t size = panvk_buffer_range(bdesc->buffer,
357bf215546Sopenharmony_ci                                             bdesc->offset, bdesc->size);
358bf215546Sopenharmony_ci            if (size) {
359bf215546Sopenharmony_ci               panvk_per_arch(emit_ubo)(address, size,
360bf215546Sopenharmony_ci                                        &ubos[dyn_ubo_start + i]);
361bf215546Sopenharmony_ci            } else {
362bf215546Sopenharmony_ci               memset(&ubos[dyn_ubo_start + i], 0, sizeof(*ubos));
363bf215546Sopenharmony_ci            }
364bf215546Sopenharmony_ci         }
365bf215546Sopenharmony_ci      }
366bf215546Sopenharmony_ci   }
367bf215546Sopenharmony_ci}
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_civoid
370bf215546Sopenharmony_cipanvk_per_arch(emit_vertex_job)(const struct panvk_pipeline *pipeline,
371bf215546Sopenharmony_ci                                const struct panvk_draw_info *draw,
372bf215546Sopenharmony_ci                                void *job)
373bf215546Sopenharmony_ci{
374bf215546Sopenharmony_ci   void *section = pan_section_ptr(job, COMPUTE_JOB, INVOCATION);
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci   memcpy(section, &draw->invocation, pan_size(INVOCATION));
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci   pan_section_pack(job, COMPUTE_JOB, PARAMETERS, cfg) {
379bf215546Sopenharmony_ci      cfg.job_task_split = 5;
380bf215546Sopenharmony_ci   }
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci   pan_section_pack(job, COMPUTE_JOB, DRAW, cfg) {
383bf215546Sopenharmony_ci      cfg.state = pipeline->rsds[MESA_SHADER_VERTEX];
384bf215546Sopenharmony_ci      cfg.attributes = draw->stages[MESA_SHADER_VERTEX].attributes;
385bf215546Sopenharmony_ci      cfg.attribute_buffers = draw->stages[MESA_SHADER_VERTEX].attribute_bufs;
386bf215546Sopenharmony_ci      cfg.varyings = draw->stages[MESA_SHADER_VERTEX].varyings;
387bf215546Sopenharmony_ci      cfg.varying_buffers = draw->varying_bufs;
388bf215546Sopenharmony_ci      cfg.thread_storage = draw->tls;
389bf215546Sopenharmony_ci      cfg.offset_start = draw->offset_start;
390bf215546Sopenharmony_ci      cfg.instance_size = draw->instance_count > 1 ?
391bf215546Sopenharmony_ci                          draw->padded_vertex_count : 1;
392bf215546Sopenharmony_ci      cfg.uniform_buffers = draw->ubos;
393bf215546Sopenharmony_ci      cfg.push_uniforms = draw->stages[PIPE_SHADER_VERTEX].push_constants;
394bf215546Sopenharmony_ci      cfg.textures = draw->textures;
395bf215546Sopenharmony_ci      cfg.samplers = draw->samplers;
396bf215546Sopenharmony_ci   }
397bf215546Sopenharmony_ci}
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_civoid
400bf215546Sopenharmony_cipanvk_per_arch(emit_compute_job)(const struct panvk_pipeline *pipeline,
401bf215546Sopenharmony_ci                                 const struct panvk_dispatch_info *dispatch,
402bf215546Sopenharmony_ci                                 void *job)
403bf215546Sopenharmony_ci{
404bf215546Sopenharmony_ci   panfrost_pack_work_groups_compute(pan_section_ptr(job, COMPUTE_JOB, INVOCATION),
405bf215546Sopenharmony_ci                                     dispatch->wg_count.x,
406bf215546Sopenharmony_ci                                     dispatch->wg_count.y,
407bf215546Sopenharmony_ci                                     dispatch->wg_count.z,
408bf215546Sopenharmony_ci                                     pipeline->cs.local_size.x,
409bf215546Sopenharmony_ci                                     pipeline->cs.local_size.y,
410bf215546Sopenharmony_ci                                     pipeline->cs.local_size.z,
411bf215546Sopenharmony_ci                                     false, false);
412bf215546Sopenharmony_ci
413bf215546Sopenharmony_ci   pan_section_pack(job, COMPUTE_JOB, PARAMETERS, cfg) {
414bf215546Sopenharmony_ci      cfg.job_task_split =
415bf215546Sopenharmony_ci         util_logbase2_ceil(pipeline->cs.local_size.x + 1) +
416bf215546Sopenharmony_ci         util_logbase2_ceil(pipeline->cs.local_size.y + 1) +
417bf215546Sopenharmony_ci         util_logbase2_ceil(pipeline->cs.local_size.z + 1);
418bf215546Sopenharmony_ci   }
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci   pan_section_pack(job, COMPUTE_JOB, DRAW, cfg) {
421bf215546Sopenharmony_ci      cfg.state = pipeline->rsds[MESA_SHADER_COMPUTE];
422bf215546Sopenharmony_ci      cfg.attributes = dispatch->attributes;
423bf215546Sopenharmony_ci      cfg.attribute_buffers = dispatch->attribute_bufs;
424bf215546Sopenharmony_ci      cfg.thread_storage = dispatch->tsd;
425bf215546Sopenharmony_ci      cfg.uniform_buffers = dispatch->ubos;
426bf215546Sopenharmony_ci      cfg.push_uniforms = dispatch->push_uniforms;
427bf215546Sopenharmony_ci      cfg.textures = dispatch->textures;
428bf215546Sopenharmony_ci      cfg.samplers = dispatch->samplers;
429bf215546Sopenharmony_ci   }
430bf215546Sopenharmony_ci}
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_cistatic void
433bf215546Sopenharmony_cipanvk_emit_tiler_primitive(const struct panvk_pipeline *pipeline,
434bf215546Sopenharmony_ci                           const struct panvk_draw_info *draw,
435bf215546Sopenharmony_ci                           void *prim)
436bf215546Sopenharmony_ci{
437bf215546Sopenharmony_ci   pan_pack(prim, PRIMITIVE, cfg) {
438bf215546Sopenharmony_ci      cfg.draw_mode = pipeline->ia.topology;
439bf215546Sopenharmony_ci      if (pipeline->ia.writes_point_size)
440bf215546Sopenharmony_ci         cfg.point_size_array_format = MALI_POINT_SIZE_ARRAY_FORMAT_FP16;
441bf215546Sopenharmony_ci
442bf215546Sopenharmony_ci      cfg.first_provoking_vertex = true;
443bf215546Sopenharmony_ci      if (pipeline->ia.primitive_restart)
444bf215546Sopenharmony_ci         cfg.primitive_restart = MALI_PRIMITIVE_RESTART_IMPLICIT;
445bf215546Sopenharmony_ci      cfg.job_task_split = 6;
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci      if (draw->index_size) {
448bf215546Sopenharmony_ci         cfg.index_count = draw->index_count;
449bf215546Sopenharmony_ci         cfg.indices = draw->indices;
450bf215546Sopenharmony_ci         cfg.base_vertex_offset = draw->vertex_offset - draw->offset_start;
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci         switch (draw->index_size) {
453bf215546Sopenharmony_ci         case 32: cfg.index_type = MALI_INDEX_TYPE_UINT32; break;
454bf215546Sopenharmony_ci         case 16: cfg.index_type = MALI_INDEX_TYPE_UINT16; break;
455bf215546Sopenharmony_ci         case 8: cfg.index_type = MALI_INDEX_TYPE_UINT8; break;
456bf215546Sopenharmony_ci         default: unreachable("Invalid index size");
457bf215546Sopenharmony_ci         }
458bf215546Sopenharmony_ci      } else {
459bf215546Sopenharmony_ci         cfg.index_count = draw->vertex_count;
460bf215546Sopenharmony_ci         cfg.index_type = MALI_INDEX_TYPE_NONE;
461bf215546Sopenharmony_ci      }
462bf215546Sopenharmony_ci   }
463bf215546Sopenharmony_ci}
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_cistatic void
466bf215546Sopenharmony_cipanvk_emit_tiler_primitive_size(const struct panvk_pipeline *pipeline,
467bf215546Sopenharmony_ci                                const struct panvk_draw_info *draw,
468bf215546Sopenharmony_ci                                void *primsz)
469bf215546Sopenharmony_ci{
470bf215546Sopenharmony_ci   pan_pack(primsz, PRIMITIVE_SIZE, cfg) {
471bf215546Sopenharmony_ci      if (pipeline->ia.writes_point_size) {
472bf215546Sopenharmony_ci         cfg.size_array = draw->psiz;
473bf215546Sopenharmony_ci      } else {
474bf215546Sopenharmony_ci         cfg.constant = draw->line_width;
475bf215546Sopenharmony_ci      }
476bf215546Sopenharmony_ci   }
477bf215546Sopenharmony_ci}
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_cistatic void
480bf215546Sopenharmony_cipanvk_emit_tiler_dcd(const struct panvk_pipeline *pipeline,
481bf215546Sopenharmony_ci                     const struct panvk_draw_info *draw,
482bf215546Sopenharmony_ci                     void *dcd)
483bf215546Sopenharmony_ci{
484bf215546Sopenharmony_ci   pan_pack(dcd, DRAW, cfg) {
485bf215546Sopenharmony_ci      cfg.front_face_ccw = pipeline->rast.front_ccw;
486bf215546Sopenharmony_ci      cfg.cull_front_face = pipeline->rast.cull_front_face;
487bf215546Sopenharmony_ci      cfg.cull_back_face = pipeline->rast.cull_back_face;
488bf215546Sopenharmony_ci      cfg.position = draw->position;
489bf215546Sopenharmony_ci      cfg.state = draw->fs_rsd;
490bf215546Sopenharmony_ci      cfg.attributes = draw->stages[MESA_SHADER_FRAGMENT].attributes;
491bf215546Sopenharmony_ci      cfg.attribute_buffers = draw->stages[MESA_SHADER_FRAGMENT].attribute_bufs;
492bf215546Sopenharmony_ci      cfg.viewport = draw->viewport;
493bf215546Sopenharmony_ci      cfg.varyings = draw->stages[MESA_SHADER_FRAGMENT].varyings;
494bf215546Sopenharmony_ci      cfg.varying_buffers = cfg.varyings ? draw->varying_bufs : 0;
495bf215546Sopenharmony_ci      cfg.thread_storage = draw->tls;
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci      /* For all primitives but lines DRAW.flat_shading_vertex must
498bf215546Sopenharmony_ci       * be set to 0 and the provoking vertex is selected with the
499bf215546Sopenharmony_ci       * PRIMITIVE.first_provoking_vertex field.
500bf215546Sopenharmony_ci       */
501bf215546Sopenharmony_ci      if (pipeline->ia.topology == MALI_DRAW_MODE_LINES ||
502bf215546Sopenharmony_ci          pipeline->ia.topology == MALI_DRAW_MODE_LINE_STRIP ||
503bf215546Sopenharmony_ci          pipeline->ia.topology == MALI_DRAW_MODE_LINE_LOOP) {
504bf215546Sopenharmony_ci         cfg.flat_shading_vertex = true;
505bf215546Sopenharmony_ci      }
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci      cfg.offset_start = draw->offset_start;
508bf215546Sopenharmony_ci      cfg.instance_size = draw->instance_count > 1 ?
509bf215546Sopenharmony_ci                         draw->padded_vertex_count : 1;
510bf215546Sopenharmony_ci      cfg.uniform_buffers = draw->ubos;
511bf215546Sopenharmony_ci      cfg.push_uniforms = draw->stages[PIPE_SHADER_FRAGMENT].push_constants;
512bf215546Sopenharmony_ci      cfg.textures = draw->textures;
513bf215546Sopenharmony_ci      cfg.samplers = draw->samplers;
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci      /* TODO: occlusion queries */
516bf215546Sopenharmony_ci   }
517bf215546Sopenharmony_ci}
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_civoid
520bf215546Sopenharmony_cipanvk_per_arch(emit_tiler_job)(const struct panvk_pipeline *pipeline,
521bf215546Sopenharmony_ci                               const struct panvk_draw_info *draw,
522bf215546Sopenharmony_ci                               void *job)
523bf215546Sopenharmony_ci{
524bf215546Sopenharmony_ci   void *section;
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci   section = pan_section_ptr(job, TILER_JOB, INVOCATION);
527bf215546Sopenharmony_ci   memcpy(section, &draw->invocation, pan_size(INVOCATION));
528bf215546Sopenharmony_ci
529bf215546Sopenharmony_ci   section = pan_section_ptr(job, TILER_JOB, PRIMITIVE);
530bf215546Sopenharmony_ci   panvk_emit_tiler_primitive(pipeline, draw, section);
531bf215546Sopenharmony_ci
532bf215546Sopenharmony_ci   section = pan_section_ptr(job, TILER_JOB, PRIMITIVE_SIZE);
533bf215546Sopenharmony_ci   panvk_emit_tiler_primitive_size(pipeline, draw, section);
534bf215546Sopenharmony_ci
535bf215546Sopenharmony_ci   section = pan_section_ptr(job, TILER_JOB, DRAW);
536bf215546Sopenharmony_ci   panvk_emit_tiler_dcd(pipeline, draw, section);
537bf215546Sopenharmony_ci
538bf215546Sopenharmony_ci   pan_section_pack(job, TILER_JOB, TILER, cfg) {
539bf215546Sopenharmony_ci      cfg.address = draw->tiler_ctx->bifrost;
540bf215546Sopenharmony_ci   }
541bf215546Sopenharmony_ci   pan_section_pack(job, TILER_JOB, PADDING, padding);
542bf215546Sopenharmony_ci}
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_civoid
545bf215546Sopenharmony_cipanvk_per_arch(emit_viewport)(const VkViewport *viewport,
546bf215546Sopenharmony_ci                              const VkRect2D *scissor,
547bf215546Sopenharmony_ci                              void *vpd)
548bf215546Sopenharmony_ci{
549bf215546Sopenharmony_ci   /* The spec says "width must be greater than 0.0" */
550bf215546Sopenharmony_ci   assert(viewport->x >= 0);
551bf215546Sopenharmony_ci   int minx = (int)viewport->x;
552bf215546Sopenharmony_ci   int maxx = (int)(viewport->x + viewport->width);
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci   /* Viewport height can be negative */
555bf215546Sopenharmony_ci   int miny = MIN2((int)viewport->y, (int)(viewport->y + viewport->height));
556bf215546Sopenharmony_ci   int maxy = MAX2((int)viewport->y, (int)(viewport->y + viewport->height));
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci   assert(scissor->offset.x >= 0 && scissor->offset.y >= 0);
559bf215546Sopenharmony_ci   miny = MAX2(scissor->offset.x, minx);
560bf215546Sopenharmony_ci   miny = MAX2(scissor->offset.y, miny);
561bf215546Sopenharmony_ci   maxx = MIN2(scissor->offset.x + scissor->extent.width, maxx);
562bf215546Sopenharmony_ci   maxy = MIN2(scissor->offset.y + scissor->extent.height, maxy);
563bf215546Sopenharmony_ci
564bf215546Sopenharmony_ci   /* Make sure we don't end up with a max < min when width/height is 0 */
565bf215546Sopenharmony_ci   maxx = maxx > minx ? maxx - 1 : maxx;
566bf215546Sopenharmony_ci   maxy = maxy > miny ? maxy - 1 : maxy;
567bf215546Sopenharmony_ci
568bf215546Sopenharmony_ci   assert(viewport->minDepth >= 0.0f && viewport->minDepth <= 1.0f);
569bf215546Sopenharmony_ci   assert(viewport->maxDepth >= 0.0f && viewport->maxDepth <= 1.0f);
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci   pan_pack(vpd, VIEWPORT, cfg) {
572bf215546Sopenharmony_ci      cfg.scissor_minimum_x = minx;
573bf215546Sopenharmony_ci      cfg.scissor_minimum_y = miny;
574bf215546Sopenharmony_ci      cfg.scissor_maximum_x = maxx;
575bf215546Sopenharmony_ci      cfg.scissor_maximum_y = maxy;
576bf215546Sopenharmony_ci      cfg.minimum_z = MIN2(viewport->minDepth, viewport->maxDepth);
577bf215546Sopenharmony_ci      cfg.maximum_z = MAX2(viewport->minDepth, viewport->maxDepth);
578bf215546Sopenharmony_ci   }
579bf215546Sopenharmony_ci}
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_cistatic enum mali_register_file_format
582bf215546Sopenharmony_cibifrost_blend_type_from_nir(nir_alu_type nir_type)
583bf215546Sopenharmony_ci{
584bf215546Sopenharmony_ci   switch(nir_type) {
585bf215546Sopenharmony_ci   case 0: /* Render target not in use */
586bf215546Sopenharmony_ci      return 0;
587bf215546Sopenharmony_ci   case nir_type_float16:
588bf215546Sopenharmony_ci      return MALI_REGISTER_FILE_FORMAT_F16;
589bf215546Sopenharmony_ci   case nir_type_float32:
590bf215546Sopenharmony_ci      return MALI_REGISTER_FILE_FORMAT_F32;
591bf215546Sopenharmony_ci   case nir_type_int32:
592bf215546Sopenharmony_ci      return MALI_REGISTER_FILE_FORMAT_I32;
593bf215546Sopenharmony_ci   case nir_type_uint32:
594bf215546Sopenharmony_ci      return MALI_REGISTER_FILE_FORMAT_U32;
595bf215546Sopenharmony_ci   case nir_type_int16:
596bf215546Sopenharmony_ci      return MALI_REGISTER_FILE_FORMAT_I16;
597bf215546Sopenharmony_ci   case nir_type_uint16:
598bf215546Sopenharmony_ci      return MALI_REGISTER_FILE_FORMAT_U16;
599bf215546Sopenharmony_ci   default:
600bf215546Sopenharmony_ci      unreachable("Unsupported blend shader type for NIR alu type");
601bf215546Sopenharmony_ci   }
602bf215546Sopenharmony_ci}
603bf215546Sopenharmony_ci
604bf215546Sopenharmony_civoid
605bf215546Sopenharmony_cipanvk_per_arch(emit_blend)(const struct panvk_device *dev,
606bf215546Sopenharmony_ci                           const struct panvk_pipeline *pipeline,
607bf215546Sopenharmony_ci                           unsigned rt, void *bd)
608bf215546Sopenharmony_ci{
609bf215546Sopenharmony_ci   const struct pan_blend_state *blend = &pipeline->blend.state;
610bf215546Sopenharmony_ci   const struct pan_blend_rt_state *rts = &blend->rts[rt];
611bf215546Sopenharmony_ci   bool dithered = false;
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_ci   pan_pack(bd, BLEND, cfg) {
614bf215546Sopenharmony_ci      if (!blend->rt_count || !rts->equation.color_mask) {
615bf215546Sopenharmony_ci         cfg.enable = false;
616bf215546Sopenharmony_ci         cfg.internal.mode = MALI_BLEND_MODE_OFF;
617bf215546Sopenharmony_ci         continue;
618bf215546Sopenharmony_ci      }
619bf215546Sopenharmony_ci
620bf215546Sopenharmony_ci      cfg.srgb = util_format_is_srgb(rts->format);
621bf215546Sopenharmony_ci      cfg.load_destination = pan_blend_reads_dest(blend->rts[rt].equation);
622bf215546Sopenharmony_ci      cfg.round_to_fb_precision = !dithered;
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_ci      const struct panfrost_device *pdev = &dev->physical_device->pdev;
625bf215546Sopenharmony_ci      const struct util_format_description *format_desc =
626bf215546Sopenharmony_ci         util_format_description(rts->format);
627bf215546Sopenharmony_ci      unsigned chan_size = 0;
628bf215546Sopenharmony_ci      for (unsigned i = 0; i < format_desc->nr_channels; i++)
629bf215546Sopenharmony_ci         chan_size = MAX2(format_desc->channel[i].size, chan_size);
630bf215546Sopenharmony_ci
631bf215546Sopenharmony_ci      pan_blend_to_fixed_function_equation(blend->rts[rt].equation,
632bf215546Sopenharmony_ci                                           &cfg.equation);
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci      /* Fixed point constant */
635bf215546Sopenharmony_ci      float fconst =
636bf215546Sopenharmony_ci         pan_blend_get_constant(pan_blend_constant_mask(blend->rts[rt].equation),
637bf215546Sopenharmony_ci                                blend->constants);
638bf215546Sopenharmony_ci      u16 constant = fconst * ((1 << chan_size) - 1);
639bf215546Sopenharmony_ci      constant <<= 16 - chan_size;
640bf215546Sopenharmony_ci      cfg.constant = constant;
641bf215546Sopenharmony_ci
642bf215546Sopenharmony_ci      if (pan_blend_is_opaque(blend->rts[rt].equation)) {
643bf215546Sopenharmony_ci         cfg.internal.mode = MALI_BLEND_MODE_OPAQUE;
644bf215546Sopenharmony_ci      } else {
645bf215546Sopenharmony_ci         cfg.internal.mode = MALI_BLEND_MODE_FIXED_FUNCTION;
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_ci         cfg.internal.fixed_function.alpha_zero_nop =
648bf215546Sopenharmony_ci                 pan_blend_alpha_zero_nop(blend->rts[rt].equation);
649bf215546Sopenharmony_ci         cfg.internal.fixed_function.alpha_one_store =
650bf215546Sopenharmony_ci                 pan_blend_alpha_one_store(blend->rts[rt].equation);
651bf215546Sopenharmony_ci      }
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci      /* If we want the conversion to work properly,
654bf215546Sopenharmony_ci       * num_comps must be set to 4
655bf215546Sopenharmony_ci       */
656bf215546Sopenharmony_ci      cfg.internal.fixed_function.num_comps = 4;
657bf215546Sopenharmony_ci      cfg.internal.fixed_function.conversion.memory_format =
658bf215546Sopenharmony_ci         panfrost_format_to_bifrost_blend(pdev, rts->format, dithered);
659bf215546Sopenharmony_ci      cfg.internal.fixed_function.conversion.register_format =
660bf215546Sopenharmony_ci         bifrost_blend_type_from_nir(pipeline->fs.info.bifrost.blend[rt].type);
661bf215546Sopenharmony_ci      cfg.internal.fixed_function.rt = rt;
662bf215546Sopenharmony_ci   }
663bf215546Sopenharmony_ci}
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_civoid
666bf215546Sopenharmony_cipanvk_per_arch(emit_blend_constant)(const struct panvk_device *dev,
667bf215546Sopenharmony_ci                                    const struct panvk_pipeline *pipeline,
668bf215546Sopenharmony_ci                                    unsigned rt, const float *constants,
669bf215546Sopenharmony_ci                                    void *bd)
670bf215546Sopenharmony_ci{
671bf215546Sopenharmony_ci   float constant = constants[pipeline->blend.constant[rt].index];
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci   pan_pack(bd, BLEND, cfg) {
674bf215546Sopenharmony_ci      cfg.enable = false;
675bf215546Sopenharmony_ci      cfg.constant = constant * pipeline->blend.constant[rt].bifrost_factor;
676bf215546Sopenharmony_ci   }
677bf215546Sopenharmony_ci}
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_civoid
680bf215546Sopenharmony_cipanvk_per_arch(emit_dyn_fs_rsd)(const struct panvk_pipeline *pipeline,
681bf215546Sopenharmony_ci                                const struct panvk_cmd_state *state,
682bf215546Sopenharmony_ci                                void *rsd)
683bf215546Sopenharmony_ci{
684bf215546Sopenharmony_ci   pan_pack(rsd, RENDERER_STATE, cfg) {
685bf215546Sopenharmony_ci      if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_DEPTH_BIAS)) {
686bf215546Sopenharmony_ci         cfg.depth_units = state->rast.depth_bias.constant_factor * 2.0f;
687bf215546Sopenharmony_ci         cfg.depth_factor = state->rast.depth_bias.slope_factor;
688bf215546Sopenharmony_ci         cfg.depth_bias_clamp = state->rast.depth_bias.clamp;
689bf215546Sopenharmony_ci      }
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci      if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK)) {
692bf215546Sopenharmony_ci         cfg.stencil_front.mask = state->zs.s_front.compare_mask;
693bf215546Sopenharmony_ci         cfg.stencil_back.mask = state->zs.s_back.compare_mask;
694bf215546Sopenharmony_ci      }
695bf215546Sopenharmony_ci
696bf215546Sopenharmony_ci      if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK)) {
697bf215546Sopenharmony_ci         cfg.stencil_mask_misc.stencil_mask_front = state->zs.s_front.write_mask;
698bf215546Sopenharmony_ci         cfg.stencil_mask_misc.stencil_mask_back = state->zs.s_back.write_mask;
699bf215546Sopenharmony_ci      }
700bf215546Sopenharmony_ci
701bf215546Sopenharmony_ci      if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE)) {
702bf215546Sopenharmony_ci         cfg.stencil_front.reference_value = state->zs.s_front.ref;
703bf215546Sopenharmony_ci         cfg.stencil_back.reference_value = state->zs.s_back.ref;
704bf215546Sopenharmony_ci      }
705bf215546Sopenharmony_ci   }
706bf215546Sopenharmony_ci}
707bf215546Sopenharmony_ci
708bf215546Sopenharmony_civoid
709bf215546Sopenharmony_cipanvk_per_arch(emit_base_fs_rsd)(const struct panvk_device *dev,
710bf215546Sopenharmony_ci                                 const struct panvk_pipeline *pipeline,
711bf215546Sopenharmony_ci                                 void *rsd)
712bf215546Sopenharmony_ci{
713bf215546Sopenharmony_ci   const struct pan_shader_info *info = &pipeline->fs.info;
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ci   pan_pack(rsd, RENDERER_STATE, cfg) {
716bf215546Sopenharmony_ci      if (pipeline->fs.required) {
717bf215546Sopenharmony_ci         pan_shader_prepare_rsd(info, pipeline->fs.address, &cfg);
718bf215546Sopenharmony_ci
719bf215546Sopenharmony_ci         uint8_t rt_written = pipeline->fs.info.outputs_written >> FRAG_RESULT_DATA0;
720bf215546Sopenharmony_ci         uint8_t rt_mask = pipeline->fs.rt_mask;
721bf215546Sopenharmony_ci         cfg.properties.allow_forward_pixel_to_kill =
722bf215546Sopenharmony_ci                 pipeline->fs.info.fs.can_fpk &&
723bf215546Sopenharmony_ci                 !(rt_mask & ~rt_written) &&
724bf215546Sopenharmony_ci                 !pipeline->ms.alpha_to_coverage &&
725bf215546Sopenharmony_ci                 !pipeline->blend.reads_dest;
726bf215546Sopenharmony_ci
727bf215546Sopenharmony_ci         bool writes_zs = pipeline->zs.z_write || pipeline->zs.s_test;
728bf215546Sopenharmony_ci         bool zs_always_passes = !pipeline->zs.z_test && !pipeline->zs.s_test;
729bf215546Sopenharmony_ci         bool oq = false; /* TODO: Occlusion queries */
730bf215546Sopenharmony_ci
731bf215546Sopenharmony_ci         struct pan_earlyzs_state earlyzs =
732bf215546Sopenharmony_ci            pan_earlyzs_get(pan_earlyzs_analyze(info), writes_zs || oq,
733bf215546Sopenharmony_ci                            pipeline->ms.alpha_to_coverage, zs_always_passes);
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_ci         cfg.properties.pixel_kill_operation = earlyzs.kill;
736bf215546Sopenharmony_ci         cfg.properties.zs_update_operation = earlyzs.update;
737bf215546Sopenharmony_ci      } else {
738bf215546Sopenharmony_ci         cfg.properties.depth_source = MALI_DEPTH_SOURCE_FIXED_FUNCTION;
739bf215546Sopenharmony_ci         cfg.properties.allow_forward_pixel_to_kill = true;
740bf215546Sopenharmony_ci         cfg.properties.allow_forward_pixel_to_be_killed = true;
741bf215546Sopenharmony_ci         cfg.properties.zs_update_operation = MALI_PIXEL_KILL_STRONG_EARLY;
742bf215546Sopenharmony_ci      }
743bf215546Sopenharmony_ci
744bf215546Sopenharmony_ci      bool msaa = pipeline->ms.rast_samples > 1;
745bf215546Sopenharmony_ci      cfg.multisample_misc.multisample_enable = msaa;
746bf215546Sopenharmony_ci      cfg.multisample_misc.sample_mask =
747bf215546Sopenharmony_ci         msaa ? pipeline->ms.sample_mask : UINT16_MAX;
748bf215546Sopenharmony_ci
749bf215546Sopenharmony_ci      cfg.multisample_misc.depth_function =
750bf215546Sopenharmony_ci         pipeline->zs.z_test ? pipeline->zs.z_compare_func : MALI_FUNC_ALWAYS;
751bf215546Sopenharmony_ci
752bf215546Sopenharmony_ci      cfg.multisample_misc.depth_write_mask = pipeline->zs.z_write;
753bf215546Sopenharmony_ci      cfg.multisample_misc.fixed_function_near_discard = !pipeline->rast.clamp_depth;
754bf215546Sopenharmony_ci      cfg.multisample_misc.fixed_function_far_discard = !pipeline->rast.clamp_depth;
755bf215546Sopenharmony_ci      cfg.multisample_misc.shader_depth_range_fixed = true;
756bf215546Sopenharmony_ci
757bf215546Sopenharmony_ci      cfg.stencil_mask_misc.stencil_enable = pipeline->zs.s_test;
758bf215546Sopenharmony_ci      cfg.stencil_mask_misc.alpha_to_coverage = pipeline->ms.alpha_to_coverage;
759bf215546Sopenharmony_ci      cfg.stencil_mask_misc.alpha_test_compare_function = MALI_FUNC_ALWAYS;
760bf215546Sopenharmony_ci      cfg.stencil_mask_misc.front_facing_depth_bias = pipeline->rast.depth_bias.enable;
761bf215546Sopenharmony_ci      cfg.stencil_mask_misc.back_facing_depth_bias = pipeline->rast.depth_bias.enable;
762bf215546Sopenharmony_ci      cfg.stencil_mask_misc.single_sampled_lines = pipeline->ms.rast_samples <= 1;
763bf215546Sopenharmony_ci
764bf215546Sopenharmony_ci      if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_DEPTH_BIAS))) {
765bf215546Sopenharmony_ci         cfg.depth_units = pipeline->rast.depth_bias.constant_factor * 2.0f;
766bf215546Sopenharmony_ci         cfg.depth_factor = pipeline->rast.depth_bias.slope_factor;
767bf215546Sopenharmony_ci         cfg.depth_bias_clamp = pipeline->rast.depth_bias.clamp;
768bf215546Sopenharmony_ci      }
769bf215546Sopenharmony_ci
770bf215546Sopenharmony_ci      if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK))) {
771bf215546Sopenharmony_ci         cfg.stencil_front.mask = pipeline->zs.s_front.compare_mask;
772bf215546Sopenharmony_ci         cfg.stencil_back.mask = pipeline->zs.s_back.compare_mask;
773bf215546Sopenharmony_ci      }
774bf215546Sopenharmony_ci
775bf215546Sopenharmony_ci      if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK))) {
776bf215546Sopenharmony_ci         cfg.stencil_mask_misc.stencil_mask_front = pipeline->zs.s_front.write_mask;
777bf215546Sopenharmony_ci         cfg.stencil_mask_misc.stencil_mask_back = pipeline->zs.s_back.write_mask;
778bf215546Sopenharmony_ci      }
779bf215546Sopenharmony_ci
780bf215546Sopenharmony_ci      if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE))) {
781bf215546Sopenharmony_ci         cfg.stencil_front.reference_value = pipeline->zs.s_front.ref;
782bf215546Sopenharmony_ci         cfg.stencil_back.reference_value = pipeline->zs.s_back.ref;
783bf215546Sopenharmony_ci      }
784bf215546Sopenharmony_ci
785bf215546Sopenharmony_ci      cfg.stencil_front.compare_function = pipeline->zs.s_front.compare_func;
786bf215546Sopenharmony_ci      cfg.stencil_front.stencil_fail = pipeline->zs.s_front.fail_op;
787bf215546Sopenharmony_ci      cfg.stencil_front.depth_fail = pipeline->zs.s_front.z_fail_op;
788bf215546Sopenharmony_ci      cfg.stencil_front.depth_pass = pipeline->zs.s_front.pass_op;
789bf215546Sopenharmony_ci      cfg.stencil_back.compare_function = pipeline->zs.s_back.compare_func;
790bf215546Sopenharmony_ci      cfg.stencil_back.stencil_fail = pipeline->zs.s_back.fail_op;
791bf215546Sopenharmony_ci      cfg.stencil_back.depth_fail = pipeline->zs.s_back.z_fail_op;
792bf215546Sopenharmony_ci      cfg.stencil_back.depth_pass = pipeline->zs.s_back.pass_op;
793bf215546Sopenharmony_ci   }
794bf215546Sopenharmony_ci}
795bf215546Sopenharmony_ci
796bf215546Sopenharmony_civoid
797bf215546Sopenharmony_cipanvk_per_arch(emit_non_fs_rsd)(const struct panvk_device *dev,
798bf215546Sopenharmony_ci                                const struct pan_shader_info *shader_info,
799bf215546Sopenharmony_ci                                mali_ptr shader_ptr,
800bf215546Sopenharmony_ci                                void *rsd)
801bf215546Sopenharmony_ci{
802bf215546Sopenharmony_ci   assert(shader_info->stage != MESA_SHADER_FRAGMENT);
803bf215546Sopenharmony_ci
804bf215546Sopenharmony_ci   pan_pack(rsd, RENDERER_STATE, cfg) {
805bf215546Sopenharmony_ci      pan_shader_prepare_rsd(shader_info, shader_ptr, &cfg);
806bf215546Sopenharmony_ci   }
807bf215546Sopenharmony_ci}
808bf215546Sopenharmony_ci
809bf215546Sopenharmony_civoid
810bf215546Sopenharmony_cipanvk_per_arch(emit_tiler_context)(const struct panvk_device *dev,
811bf215546Sopenharmony_ci                                   unsigned width, unsigned height,
812bf215546Sopenharmony_ci                                   const struct panfrost_ptr *descs)
813bf215546Sopenharmony_ci{
814bf215546Sopenharmony_ci   const struct panfrost_device *pdev = &dev->physical_device->pdev;
815bf215546Sopenharmony_ci
816bf215546Sopenharmony_ci   pan_pack(descs->cpu + pan_size(TILER_CONTEXT), TILER_HEAP, cfg) {
817bf215546Sopenharmony_ci      cfg.size = pdev->tiler_heap->size;
818bf215546Sopenharmony_ci      cfg.base = pdev->tiler_heap->ptr.gpu;
819bf215546Sopenharmony_ci      cfg.bottom = pdev->tiler_heap->ptr.gpu;
820bf215546Sopenharmony_ci      cfg.top = pdev->tiler_heap->ptr.gpu + pdev->tiler_heap->size;
821bf215546Sopenharmony_ci   }
822bf215546Sopenharmony_ci
823bf215546Sopenharmony_ci   pan_pack(descs->cpu, TILER_CONTEXT, cfg) {
824bf215546Sopenharmony_ci      cfg.hierarchy_mask = 0x28;
825bf215546Sopenharmony_ci      cfg.fb_width = width;
826bf215546Sopenharmony_ci      cfg.fb_height = height;
827bf215546Sopenharmony_ci      cfg.heap = descs->gpu + pan_size(TILER_CONTEXT);
828bf215546Sopenharmony_ci   }
829bf215546Sopenharmony_ci}
830