1/*
2 * Copyright (C) 2021 Collabora Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#ifndef PANVK_VARYINGS_H
25#define PANVK_VARYINGS_H
26
27#include "util/bitset.h"
28#include "util/format/u_format.h"
29
30#include "compiler/shader_enums.h"
31#include "panfrost-job.h"
32
33#include "pan_pool.h"
34
35struct pan_pool;
36struct panvk_device;
37
38enum panvk_varying_buf_id {
39   PANVK_VARY_BUF_GENERAL,
40   PANVK_VARY_BUF_POSITION,
41   PANVK_VARY_BUF_PSIZ,
42
43   /* Keep last */
44   PANVK_VARY_BUF_MAX,
45};
46
47struct panvk_varying {
48   unsigned buf;
49   unsigned offset;
50   enum pipe_format format;
51};
52
53struct panvk_varying_buf {
54   mali_ptr address;
55   void *cpu;
56   unsigned stride;
57   unsigned size;
58};
59
60struct panvk_varyings_info {
61   struct panvk_varying varying[VARYING_SLOT_MAX];
62   BITSET_DECLARE(active, VARYING_SLOT_MAX);
63   struct panvk_varying_buf buf[VARYING_SLOT_MAX];
64   struct {
65      unsigned count;
66      gl_varying_slot loc[VARYING_SLOT_MAX];
67   } stage[MESA_SHADER_STAGES];
68   unsigned buf_mask;
69};
70
71static inline unsigned
72panvk_varying_buf_index(const struct panvk_varyings_info *varyings,
73                        enum panvk_varying_buf_id b)
74{
75   return util_bitcount(varyings->buf_mask & BITFIELD_MASK(b));
76}
77
78static inline enum panvk_varying_buf_id
79panvk_varying_buf_id(gl_varying_slot loc)
80{
81   switch (loc) {
82   case VARYING_SLOT_POS:
83      return PANVK_VARY_BUF_POSITION;
84   case VARYING_SLOT_PSIZ:
85      return PANVK_VARY_BUF_PSIZ;
86   default:
87      return PANVK_VARY_BUF_GENERAL;
88   }
89}
90
91static inline unsigned
92panvk_varying_size(const struct panvk_varyings_info *varyings,
93                   gl_varying_slot loc)
94{
95   switch (loc) {
96   case VARYING_SLOT_POS:
97      return sizeof(float) * 4;
98   case VARYING_SLOT_PSIZ:
99      return sizeof(uint16_t);
100   default:
101      return util_format_get_blocksize(varyings->varying[loc].format);
102   }
103}
104
105static inline unsigned
106panvk_varyings_buf_count(struct panvk_varyings_info *varyings)
107{
108   return util_bitcount(varyings->buf_mask);
109}
110
111static inline void
112panvk_varyings_alloc(struct panvk_varyings_info *varyings,
113                     struct pan_pool *varying_mem_pool,
114                     unsigned vertex_count)
115{
116   for (unsigned i = 0; i < PANVK_VARY_BUF_MAX; i++) {
117      if (!(varyings->buf_mask & (1 << i))) continue;
118
119      unsigned buf_idx = panvk_varying_buf_index(varyings, i);
120      unsigned size = varyings->buf[buf_idx].stride * vertex_count;
121      if (!size)
122         continue;
123
124      struct panfrost_ptr ptr =
125         pan_pool_alloc_aligned(varying_mem_pool, size, 64);
126
127      varyings->buf[buf_idx].size = size;
128      varyings->buf[buf_idx].address = ptr.gpu;
129      varyings->buf[buf_idx].cpu = ptr.cpu;
130   }
131}
132
133#endif
134