1 /*
2 * Copyright (C) 2019-2020 Collabora, Ltd.
3 * Copyright 2018-2019 Alyssa Rosenzweig
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 */
25
26 #include "pan_bo.h"
27 #include "pan_context.h"
28 #include "pan_util.h"
29
30 #include "util/format/u_format.h"
31
32 static void
panfrost_sfbd_format(struct pipe_surface * surf,struct MALI_SINGLE_TARGET_FRAMEBUFFER_PARAMETERS * fb)33 panfrost_sfbd_format(struct pipe_surface *surf,
34 struct MALI_SINGLE_TARGET_FRAMEBUFFER_PARAMETERS *fb)
35 {
36 /* Explode details on the format */
37
38 const struct util_format_description *desc =
39 util_format_description(surf->format);
40
41 /* The swizzle for rendering is inverted from texturing */
42
43 unsigned char swizzle[4];
44 panfrost_invert_swizzle(desc->swizzle, swizzle);
45
46 fb->swizzle = panfrost_translate_swizzle_4(swizzle);
47
48 struct pan_blendable_format fmt = panfrost_blend_format(surf->format);
49
50 if (fmt.internal) {
51 fb->internal_format = fmt.internal;
52 fb->color_writeback_format = fmt.writeback;
53 } else {
54 unreachable("raw formats not finished for SFBD");
55 }
56 }
57
58 static void
panfrost_sfbd_clear(struct panfrost_batch * batch,struct MALI_SINGLE_TARGET_FRAMEBUFFER_PARAMETERS * sfbd)59 panfrost_sfbd_clear(
60 struct panfrost_batch *batch,
61 struct MALI_SINGLE_TARGET_FRAMEBUFFER_PARAMETERS *sfbd)
62 {
63 if (batch->clear & PIPE_CLEAR_COLOR) {
64 sfbd->clear_color_0 = batch->clear_color[0][0];
65 sfbd->clear_color_1 = batch->clear_color[0][1];
66 sfbd->clear_color_2 = batch->clear_color[0][2];
67 sfbd->clear_color_3 = batch->clear_color[0][3];
68 }
69
70 if (batch->clear & PIPE_CLEAR_DEPTH)
71 sfbd->z_clear = batch->clear_depth;
72
73 if (batch->clear & PIPE_CLEAR_STENCIL)
74 sfbd->s_clear = batch->clear_stencil & 0xff;
75 }
76
77 static void
panfrost_sfbd_set_cbuf(struct MALI_SINGLE_TARGET_FRAMEBUFFER_PARAMETERS * fb,struct pipe_surface * surf)78 panfrost_sfbd_set_cbuf(
79 struct MALI_SINGLE_TARGET_FRAMEBUFFER_PARAMETERS *fb,
80 struct pipe_surface *surf)
81 {
82 struct panfrost_resource *rsrc = pan_resource(surf->texture);
83
84 unsigned level = surf->u.tex.level;
85 unsigned first_layer = surf->u.tex.first_layer;
86 assert(surf->u.tex.last_layer == first_layer);
87 signed stride = rsrc->slices[level].stride;
88
89 mali_ptr base = panfrost_get_texture_address(rsrc, level, first_layer, 0);
90
91 panfrost_sfbd_format(surf, fb);
92
93 fb->color_write_enable = true;
94 fb->color_writeback.base = base;
95 fb->color_writeback.row_stride = stride;
96
97 if (rsrc->modifier == DRM_FORMAT_MOD_LINEAR)
98 fb->color_block_format = MALI_BLOCK_FORMAT_LINEAR;
99 else if (rsrc->modifier == DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED) {
100 fb->color_block_format = MALI_BLOCK_FORMAT_TILED_U_INTERLEAVED;
101 fb->color_writeback.row_stride *= 16;
102 } else {
103 fprintf(stderr, "Invalid render modifier\n");
104 assert(0);
105 }
106 }
107
108 static void
panfrost_sfbd_set_zsbuf(struct MALI_SINGLE_TARGET_FRAMEBUFFER_PARAMETERS * fb,struct pipe_surface * surf)109 panfrost_sfbd_set_zsbuf(
110 struct MALI_SINGLE_TARGET_FRAMEBUFFER_PARAMETERS *fb,
111 struct pipe_surface *surf)
112 {
113 struct panfrost_resource *rsrc = pan_resource(surf->texture);
114
115 unsigned level = surf->u.tex.level;
116 assert(surf->u.tex.first_layer == 0);
117
118 if (rsrc->modifier != DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED)
119 unreachable("Invalid render modifier.");
120
121 fb->zs_block_format = MALI_BLOCK_FORMAT_TILED_U_INTERLEAVED;
122 fb->zs_writeback.base = rsrc->bo->ptr.gpu + rsrc->slices[level].offset;
123 fb->zs_writeback.row_stride = rsrc->slices[level].stride * 16;
124 switch (surf->format) {
125 case PIPE_FORMAT_Z16_UNORM:
126 fb->zs_format = MALI_ZS_FORMAT_D16;
127 break;
128 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
129 fb->zs_format = MALI_ZS_FORMAT_D24S8;
130 break;
131 case PIPE_FORMAT_Z24X8_UNORM:
132 fb->zs_format = MALI_ZS_FORMAT_D24X8;
133 break;
134 case PIPE_FORMAT_Z32_FLOAT:
135 fb->zs_format = MALI_ZS_FORMAT_D32;
136 break;
137 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
138 fb->zs_format = MALI_ZS_FORMAT_D32_S8X24;
139 break;
140 default:
141 unreachable("Unsupported depth/stencil format.");
142 }
143 }
144
145 static void
panfrost_init_sfbd_params(struct panfrost_batch * batch,struct MALI_SINGLE_TARGET_FRAMEBUFFER_PARAMETERS * sfbd)146 panfrost_init_sfbd_params(struct panfrost_batch *batch,
147 struct MALI_SINGLE_TARGET_FRAMEBUFFER_PARAMETERS *sfbd)
148 {
149 sfbd->bound_max_x = batch->key.width - 1;
150 sfbd->bound_max_y = batch->key.height - 1;
151 sfbd->dithering_enable = true;
152 sfbd->clean_pixel_write_enable = true;
153 sfbd->tie_break_rule = MALI_TIE_BREAK_RULE_MINUS_180_IN_0_OUT;
154 }
155
156 static void
panfrost_emit_sfdb_local_storage(struct panfrost_batch * batch,void * sfbd,unsigned vertex_count)157 panfrost_emit_sfdb_local_storage(struct panfrost_batch *batch, void *sfbd,
158 unsigned vertex_count)
159 {
160 struct panfrost_device *dev = pan_device(batch->ctx->base.screen);
161 /* TODO: Why do we need to make the stack bigger than other platforms? */
162 unsigned shift = panfrost_get_stack_shift(MAX2(batch->stack_size, 512));
163
164 pan_section_pack(sfbd, SINGLE_TARGET_FRAMEBUFFER, LOCAL_STORAGE, ls) {
165 ls.tls_size = shift;
166 ls.wls_instances = MALI_LOCAL_STORAGE_NO_WORKGROUP_MEM;
167 ls.tls_base_pointer =
168 panfrost_batch_get_scratchpad(batch,
169 shift,
170 dev->thread_tls_alloc,
171 dev->core_count)->ptr.gpu;
172 }
173 }
174
175 static void
panfrost_emit_sfdb_tiler(struct panfrost_batch * batch,void * sfbd,unsigned vertex_count)176 panfrost_emit_sfdb_tiler(struct panfrost_batch *batch, void *sfbd,
177 unsigned vertex_count)
178 {
179 void *tiler = pan_section_ptr(sfbd, SINGLE_TARGET_FRAMEBUFFER, TILER);
180
181 panfrost_emit_midg_tiler(batch, tiler, vertex_count);
182
183 /* All weights set to 0, nothing to do here */
184 pan_section_pack(sfbd, SINGLE_TARGET_FRAMEBUFFER, PADDING_1, padding) {}
185 pan_section_pack(sfbd, SINGLE_TARGET_FRAMEBUFFER, TILER_WEIGHTS, w) {}
186 }
187
188 void
panfrost_attach_sfbd(struct panfrost_batch * batch,unsigned vertex_count)189 panfrost_attach_sfbd(struct panfrost_batch *batch, unsigned vertex_count)
190 {
191 void *sfbd = batch->framebuffer.cpu;
192
193 panfrost_emit_sfdb_local_storage(batch, sfbd, vertex_count);
194 pan_section_pack(sfbd, SINGLE_TARGET_FRAMEBUFFER, PARAMETERS, params) {
195 panfrost_init_sfbd_params(batch, ¶ms);
196 }
197 panfrost_emit_sfdb_tiler(batch, sfbd, vertex_count);
198 pan_section_pack(sfbd, SINGLE_TARGET_FRAMEBUFFER, PADDING_2, padding) {}
199 }
200
201 /* Creates an SFBD for the FRAGMENT section of the bound framebuffer */
202
203 mali_ptr
panfrost_sfbd_fragment(struct panfrost_batch * batch,bool has_draws)204 panfrost_sfbd_fragment(struct panfrost_batch *batch, bool has_draws)
205 {
206 struct panfrost_ptr t =
207 panfrost_pool_alloc_aligned(&batch->pool,
208 MALI_SINGLE_TARGET_FRAMEBUFFER_LENGTH,
209 64);
210 void *sfbd = t.cpu;
211
212 panfrost_emit_sfdb_local_storage(batch, sfbd, has_draws);
213 pan_section_pack(sfbd, SINGLE_TARGET_FRAMEBUFFER, PARAMETERS, params) {
214 panfrost_init_sfbd_params(batch, ¶ms);
215 panfrost_sfbd_clear(batch, ¶ms);
216
217 /* SFBD does not support MRT natively; sanity check */
218 assert(batch->key.nr_cbufs <= 1);
219 if (batch->key.nr_cbufs) {
220 struct pipe_surface *surf = batch->key.cbufs[0];
221 struct panfrost_resource *rsrc = pan_resource(surf->texture);
222 struct panfrost_bo *bo = rsrc->bo;
223
224 panfrost_sfbd_set_cbuf(¶ms, surf);
225
226 if (rsrc->checksummed) {
227 unsigned level = surf->u.tex.level;
228 struct panfrost_slice *slice = &rsrc->slices[level];
229
230 params.crc_buffer.row_stride = slice->checksum_stride;
231 params.crc_buffer.base = bo->ptr.gpu + slice->checksum_offset;
232 }
233 }
234
235 if (batch->key.zsbuf)
236 panfrost_sfbd_set_zsbuf(¶ms, batch->key.zsbuf);
237
238 if (batch->requirements & PAN_REQ_MSAA) {
239 /* Only 4x MSAA supported right now. */
240 params.sample_count = 4;
241 params.msaa = MALI_MSAA_MULTIPLE;
242 }
243 }
244 panfrost_emit_sfdb_tiler(batch, sfbd, has_draws);
245 pan_section_pack(sfbd, SINGLE_TARGET_FRAMEBUFFER, PADDING_2, padding) {}
246
247 return t.gpu;
248 }
249