1/*
2 * Copyright (C) 2017 Rob Clark <robclark@freedesktop.org>
3 * Copyright © 2018 Google, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * Authors:
25 *    Rob Clark <robclark@freedesktop.org>
26 */
27
28#include "pipe/p_state.h"
29
30#include "freedreno_resource.h"
31#include "freedreno_state.h"
32
33#include "fd6_image.h"
34#include "fd6_resource.h"
35#include "fd6_texture.h"
36
37static const uint8_t swiz_identity[4] = {PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
38                                         PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W};
39
40static void
41fd6_emit_single_plane_descriptor(struct fd_ringbuffer *ring,
42                                 struct pipe_resource *prsc,
43                                 uint32_t *descriptor)
44{
45   /* If the resource isn't present (holes are allowed), zero-fill the slot. */
46   if (!prsc) {
47      for (int i = 0; i < 16; i++)
48         OUT_RING(ring, 0);
49      return;
50   }
51
52   struct fd_resource *rsc = fd_resource(prsc);
53   for (int i = 0; i < 4; i++)
54      OUT_RING(ring, descriptor[i]);
55
56   OUT_RELOC(ring, rsc->bo, descriptor[4], (uint64_t)descriptor[5] << 32, 0);
57
58   OUT_RING(ring, descriptor[6]);
59
60   OUT_RELOC(ring, rsc->bo, descriptor[7], (uint64_t)descriptor[8] << 32, 0);
61
62   for (int i = 9; i < FDL6_TEX_CONST_DWORDS; i++)
63      OUT_RING(ring, descriptor[i]);
64}
65
66static void
67fd6_ssbo_descriptor(struct fd_context *ctx,
68                    const struct pipe_shader_buffer *buf, uint32_t *descriptor)
69{
70   fdl6_buffer_view_init(
71      descriptor,
72      ctx->screen->info->a6xx.storage_16bit ? PIPE_FORMAT_R16_UINT
73                                            : PIPE_FORMAT_R32_UINT,
74      swiz_identity, buf->buffer_offset, /* Using relocs for addresses */
75      buf->buffer_size);
76}
77
78static void
79fd6_emit_image_descriptor(struct fd_context *ctx, struct fd_ringbuffer *ring, const struct pipe_image_view *buf, bool ibo)
80{
81   struct fd_resource *rsc = fd_resource(buf->resource);
82   if (!rsc) {
83      for (int i = 0; i < FDL6_TEX_CONST_DWORDS; i++)
84         OUT_RING(ring, 0);
85      return;
86   }
87
88   if (buf->resource->target == PIPE_BUFFER) {
89   uint32_t descriptor[FDL6_TEX_CONST_DWORDS];
90      fdl6_buffer_view_init(descriptor, buf->format, swiz_identity,
91                           buf->u.buf.offset, /* Using relocs for addresses */
92                           buf->u.buf.size);
93   fd6_emit_single_plane_descriptor(ring, buf->resource, descriptor);
94   } else {
95      struct fdl_view_args args = {
96         /* Using relocs for addresses */
97         .iova = 0,
98
99         .base_miplevel = buf->u.tex.level,
100         .level_count = 1,
101
102         .base_array_layer = buf->u.tex.first_layer,
103         .layer_count = buf->u.tex.last_layer - buf->u.tex.first_layer + 1,
104
105         .format = buf->format,
106         .swiz = {PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z,
107                  PIPE_SWIZZLE_W},
108
109         .type = fdl_type_from_pipe_target(buf->resource->target),
110         .chroma_offsets = {FDL_CHROMA_LOCATION_COSITED_EVEN,
111                            FDL_CHROMA_LOCATION_COSITED_EVEN},
112      };
113
114      /* fdl6_view makes the storage descriptor treat cubes like a 2D array (so
115       * you can reference a specific layer), but we need to do that for the
116       * texture descriptor as well to get our layer.
117       */
118      if (args.type == FDL_VIEW_TYPE_CUBE)
119         args.type = FDL_VIEW_TYPE_2D;
120
121      struct fdl6_view view;
122      const struct fdl_layout *layouts[3] = {&rsc->layout, NULL, NULL};
123      fdl6_view_init(&view, layouts, &args,
124                     ctx->screen->info->a6xx.has_z24uint_s8uint);
125      if (ibo)
126         fd6_emit_single_plane_descriptor(ring, buf->resource, view.storage_descriptor);
127      else
128         fd6_emit_single_plane_descriptor(ring, buf->resource, view.descriptor);
129   }
130}
131
132void
133fd6_emit_image_tex(struct fd_context *ctx, struct fd_ringbuffer *ring,
134                   const struct pipe_image_view *pimg)
135{
136   fd6_emit_image_descriptor(ctx, ring, pimg, false);
137}
138
139void
140fd6_emit_ssbo_tex(struct fd_context *ctx, struct fd_ringbuffer *ring,
141                  const struct pipe_shader_buffer *pbuf)
142{
143   uint32_t descriptor[FDL6_TEX_CONST_DWORDS];
144   fd6_ssbo_descriptor(ctx, pbuf, descriptor);
145   fd6_emit_single_plane_descriptor(ring, pbuf->buffer, descriptor);
146}
147
148/* Build combined image/SSBO "IBO" state, returns ownership of state reference */
149struct fd_ringbuffer *
150fd6_build_ibo_state(struct fd_context *ctx, const struct ir3_shader_variant *v,
151                    enum pipe_shader_type shader)
152{
153   struct fd_shaderbuf_stateobj *bufso = &ctx->shaderbuf[shader];
154   struct fd_shaderimg_stateobj *imgso = &ctx->shaderimg[shader];
155
156   struct fd_ringbuffer *state = fd_submit_new_ringbuffer(
157      ctx->batch->submit,
158      ir3_shader_nibo(v) * 16 * 4,
159      FD_RINGBUFFER_STREAMING);
160
161   assert(shader == PIPE_SHADER_COMPUTE || shader == PIPE_SHADER_FRAGMENT);
162
163   uint32_t descriptor[FDL6_TEX_CONST_DWORDS];
164   for (unsigned i = 0; i < v->num_ssbos; i++) {
165      fd6_ssbo_descriptor(ctx, &bufso->sb[i], descriptor);
166      fd6_emit_single_plane_descriptor(state, bufso->sb[i].buffer, descriptor);
167   }
168
169   for (unsigned i = v->num_ssbos; i < v->num_ibos; i++) {
170      fd6_emit_image_descriptor(ctx, state, &imgso->si[i - v->num_ssbos], true);
171   }
172
173   return state;
174}
175
176static void
177fd6_set_shader_images(struct pipe_context *pctx, enum pipe_shader_type shader,
178                      unsigned start, unsigned count,
179                      unsigned unbind_num_trailing_slots,
180                      const struct pipe_image_view *images) in_dt
181{
182   struct fd_context *ctx = fd_context(pctx);
183   struct fd_shaderimg_stateobj *so = &ctx->shaderimg[shader];
184
185   fd_set_shader_images(pctx, shader, start, count, unbind_num_trailing_slots,
186                        images);
187
188   if (!images)
189      return;
190
191   for (unsigned i = 0; i < count; i++) {
192      unsigned n = i + start;
193      struct pipe_image_view *buf = &so->si[n];
194
195      if (!buf->resource)
196         continue;
197
198      fd6_validate_format(ctx, fd_resource(buf->resource), buf->format);
199   }
200}
201
202void
203fd6_image_init(struct pipe_context *pctx)
204{
205   pctx->set_shader_images = fd6_set_shader_images;
206}
207