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
37 static const uint8_t swiz_identity[4] = {PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y,
38 PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W};
39
40 static void
fd6_emit_single_plane_descriptor(struct fd_ringbuffer * ring,struct pipe_resource * prsc,uint32_t * descriptor)41 fd6_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
66 static void
fd6_ssbo_descriptor(struct fd_context * ctx,const struct pipe_shader_buffer * buf,uint32_t * descriptor)67 fd6_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
78 static void
fd6_emit_image_descriptor(struct fd_context * ctx,struct fd_ringbuffer * ring,const struct pipe_image_view * buf,bool ibo)79 fd6_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
132 void
fd6_emit_image_tex(struct fd_context * ctx,struct fd_ringbuffer * ring,const struct pipe_image_view * pimg)133 fd6_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
139 void
fd6_emit_ssbo_tex(struct fd_context * ctx,struct fd_ringbuffer * ring,const struct pipe_shader_buffer * pbuf)140 fd6_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 */
149 struct fd_ringbuffer *
fd6_build_ibo_state(struct fd_context * ctx,const struct ir3_shader_variant * v,enum pipe_shader_type shader)150 fd6_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
176 static void
fd6_set_shader_images(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start,unsigned count,unsigned unbind_num_trailing_slots,const struct pipe_image_view * images)177 fd6_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
202 void
fd6_image_init(struct pipe_context * pctx)203 fd6_image_init(struct pipe_context *pctx)
204 {
205 pctx->set_shader_images = fd6_set_shader_images;
206 }
207