~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/drivers/etnaviv/etnaviv_texture.c

  • Committer: mmach
  • Date: 2022-09-22 19:58:36 UTC
  • Revision ID: netbit73@gmail.com-20220922195836-9nl9joew85y8d25o
2022-07-04 12:44:28

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2012-2015 Etnaviv Project
 
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, sub license,
 
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
 
12
 * next paragraph) shall be included in all copies or substantial portions
 
13
 * of the 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 NON-INFRINGEMENT. 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
 * Authors:
 
24
 *    Wladimir J. van der Laan <laanwj@gmail.com>
 
25
 */
 
26
 
 
27
#include "etnaviv_texture.h"
 
28
 
 
29
#include "hw/common.xml.h"
 
30
 
 
31
#include "etnaviv_clear_blit.h"
 
32
#include "etnaviv_context.h"
 
33
#include "etnaviv_emit.h"
 
34
#include "etnaviv_format.h"
 
35
#include "etnaviv_texture_desc.h"
 
36
#include "etnaviv_texture_state.h"
 
37
#include "etnaviv_translate.h"
 
38
#include "util/u_inlines.h"
 
39
#include "util/u_memory.h"
 
40
 
 
41
#include "drm-uapi/drm_fourcc.h"
 
42
 
 
43
static void
 
44
etna_bind_sampler_states(struct pipe_context *pctx, enum pipe_shader_type shader,
 
45
                         unsigned start_slot, unsigned num_samplers,
 
46
                         void **samplers)
 
47
{
 
48
   /* bind fragment sampler */
 
49
   struct etna_context *ctx = etna_context(pctx);
 
50
   struct etna_screen *screen = ctx->screen;
 
51
   int offset;
 
52
 
 
53
   switch (shader) {
 
54
   case PIPE_SHADER_FRAGMENT:
 
55
      offset = 0;
 
56
      ctx->num_fragment_samplers = num_samplers;
 
57
      break;
 
58
   case PIPE_SHADER_VERTEX:
 
59
      offset = screen->specs.vertex_sampler_offset;
 
60
      break;
 
61
   default:
 
62
      assert(!"Invalid shader");
 
63
      return;
 
64
   }
 
65
 
 
66
   uint32_t mask = 1 << offset;
 
67
   for (int idx = 0; idx < num_samplers; ++idx, mask <<= 1) {
 
68
      ctx->sampler[offset + idx] = samplers[idx];
 
69
      if (samplers[idx])
 
70
         ctx->active_samplers |= mask;
 
71
      else
 
72
         ctx->active_samplers &= ~mask;
 
73
   }
 
74
 
 
75
   ctx->dirty |= ETNA_DIRTY_SAMPLERS;
 
76
}
 
77
 
 
78
static bool
 
79
etna_configure_sampler_ts(struct etna_sampler_ts *sts, struct pipe_sampler_view *pview, bool enable)
 
80
{
 
81
   bool dirty = (sts->enable != enable);
 
82
 
 
83
   assert(sts);
 
84
   sts->enable = enable;
 
85
 
 
86
   if (!enable) {
 
87
      sts->TS_SAMPLER_CONFIG = 0;
 
88
      sts->TS_SAMPLER_STATUS_BASE.bo = NULL;
 
89
      return dirty;
 
90
   }
 
91
 
 
92
   struct etna_resource *rsc = etna_resource(pview->texture);
 
93
   struct etna_resource_level *lev = &rsc->levels[0];
 
94
 
 
95
   if (lev->clear_value != sts->TS_SAMPLER_CLEAR_VALUE)
 
96
      dirty = true;
 
97
 
 
98
   assert(rsc->ts_bo && lev->ts_valid);
 
99
 
 
100
   sts->mode = lev->ts_mode;
 
101
   sts->comp = lev->ts_compress_fmt >= 0;
 
102
   sts->TS_SAMPLER_CONFIG =
 
103
      VIVS_TS_SAMPLER_CONFIG_ENABLE |
 
104
      COND(lev->ts_compress_fmt >= 0, VIVS_TS_SAMPLER_CONFIG_COMPRESSION) |
 
105
      VIVS_TS_SAMPLER_CONFIG_COMPRESSION_FORMAT(lev->ts_compress_fmt);
 
106
   sts->TS_SAMPLER_CLEAR_VALUE = lev->clear_value;
 
107
   sts->TS_SAMPLER_CLEAR_VALUE2 = lev->clear_value >> 32;
 
108
   sts->TS_SAMPLER_STATUS_BASE.bo = rsc->ts_bo;
 
109
   sts->TS_SAMPLER_STATUS_BASE.offset = lev->ts_offset;
 
110
   sts->TS_SAMPLER_STATUS_BASE.flags = ETNA_RELOC_READ;
 
111
 
 
112
   return dirty;
 
113
}
 
114
 
 
115
/* Return true if the GPU can use sampler TS with this sampler view.
 
116
 * Sampler TS is an optimization used when rendering to textures, where
 
117
 * a resolve-in-place can be avoided when rendering has left a (valid) TS.
 
118
 */
 
119
static bool
 
120
etna_can_use_sampler_ts(struct pipe_sampler_view *view, int num)
 
121
{
 
122
    /* Can use sampler TS when:
 
123
     * - the hardware supports sampler TS.
 
124
     * - the sampler view will be bound to sampler <VIVS_TS_SAMPLER__LEN.
 
125
     *   HALTI5 adds a mapping from sampler to sampler TS unit, but this is AFAIK
 
126
     *   absent on earlier models.
 
127
     * - it is a texture, not a buffer.
 
128
     * - the sampler view has a supported format for sampler TS.
 
129
     * - the sampler will have one LOD, and it happens to be level 0.
 
130
     *   (it is not sure if the hw supports it for other levels, but available
 
131
     *   state strongly suggests only one at a time).
 
132
     * - the resource TS is valid for level 0.
 
133
     */
 
134
   struct etna_resource *rsc = etna_resource(view->texture);
 
135
   struct etna_screen *screen = etna_screen(rsc->base.screen);
 
136
 
 
137
   return VIV_FEATURE(screen, chipMinorFeatures2, TEXTURE_TILED_READ) &&
 
138
      num < VIVS_TS_SAMPLER__LEN &&
 
139
      rsc->base.target != PIPE_BUFFER &&
 
140
      (rsc->levels[0].ts_compress_fmt < 0 || screen->specs.v4_compression) &&
 
141
      view->u.tex.first_level == 0 && MIN2(view->u.tex.last_level, rsc->base.last_level) == 0 &&
 
142
      rsc->levels[0].ts_valid;
 
143
}
 
144
 
 
145
void
 
146
etna_update_sampler_source(struct pipe_sampler_view *view, int num)
 
147
{
 
148
   struct etna_resource *base = etna_resource(view->texture);
 
149
   struct etna_resource *to = base, *from = base;
 
150
   struct etna_context *ctx = etna_context(view->context);
 
151
   bool enable_sampler_ts = false;
 
152
 
 
153
   if (base->render && etna_resource_newer(etna_resource(base->render), base))
 
154
      from = etna_resource(base->render);
 
155
 
 
156
   if (base->texture)
 
157
      to = etna_resource(base->texture);
 
158
 
 
159
   if ((to != from) && etna_resource_older(to, from)) {
 
160
      etna_copy_resource(view->context, &to->base, &from->base, 0,
 
161
                         view->texture->last_level);
 
162
      to->seqno = from->seqno;
 
163
      ctx->dirty |= ETNA_DIRTY_TEXTURE_CACHES;
 
164
   } else if ((to == from) && etna_resource_needs_flush(to)) {
 
165
      if (ctx->ts_for_sampler_view && etna_can_use_sampler_ts(view, num)) {
 
166
         enable_sampler_ts = true;
 
167
         /* Do not set flush_seqno because the resolve-to-self was bypassed */
 
168
      } else {
 
169
         /* Resolve TS if needed */
 
170
         etna_copy_resource(view->context, &to->base, &from->base, 0,
 
171
                            view->texture->last_level);
 
172
         to->flush_seqno = from->seqno;
 
173
         ctx->dirty |= ETNA_DIRTY_TEXTURE_CACHES;
 
174
      }
 
175
  } else if ((to == from) && (to->flush_seqno < from->seqno)) {
 
176
      to->flush_seqno = from->seqno;
 
177
      ctx->dirty |= ETNA_DIRTY_TEXTURE_CACHES;
 
178
   }
 
179
   if (ctx->ts_for_sampler_view &&
 
180
       etna_configure_sampler_ts(ctx->ts_for_sampler_view(view), view, enable_sampler_ts)) {
 
181
      ctx->dirty |= ETNA_DIRTY_SAMPLER_VIEWS | ETNA_DIRTY_TEXTURE_CACHES;
 
182
      ctx->dirty_sampler_views |= (1 << num);
 
183
   }
 
184
}
 
185
 
 
186
static bool
 
187
etna_resource_sampler_compatible(struct etna_resource *res)
 
188
{
 
189
   if (util_format_is_compressed(res->base.format))
 
190
      return true;
 
191
 
 
192
   struct etna_screen *screen = etna_screen(res->base.screen);
 
193
   /* This GPU supports texturing from supertiled textures? */
 
194
   if (res->layout == ETNA_LAYOUT_SUPER_TILED && VIV_FEATURE(screen, chipMinorFeatures2, SUPERTILED_TEXTURE))
 
195
      return true;
 
196
 
 
197
   /* This GPU supports texturing from linear textures? */
 
198
   if (res->layout == ETNA_LAYOUT_LINEAR && VIV_FEATURE(screen, chipMinorFeatures1, LINEAR_TEXTURE_SUPPORT))
 
199
      return true;
 
200
 
 
201
   /* Otherwise, only support tiled layouts */
 
202
   if (res->layout != ETNA_LAYOUT_TILED)
 
203
      return false;
 
204
 
 
205
   /* If we have HALIGN support, we can allow for the RS padding */
 
206
   if (VIV_FEATURE(screen, chipMinorFeatures1, TEXTURE_HALIGN))
 
207
      return true;
 
208
 
 
209
   /* Non-HALIGN GPUs only accept 4x4 tile-aligned textures */
 
210
   if (res->halign != TEXTURE_HALIGN_FOUR)
 
211
      return false;
 
212
 
 
213
   return true;
 
214
}
 
215
 
 
216
struct etna_resource *
 
217
etna_texture_handle_incompatible(struct pipe_context *pctx, struct pipe_resource *prsc)
 
218
{
 
219
   struct etna_resource *res = etna_resource(prsc);
 
220
   if (!etna_resource_sampler_compatible(res)) {
 
221
      /* The original resource is not compatible with the sampler.
 
222
       * Allocate an appropriately tiled texture. */
 
223
      if (!res->texture) {
 
224
         struct pipe_resource templat = *prsc;
 
225
 
 
226
         templat.bind &= ~(PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET |
 
227
                           PIPE_BIND_BLENDABLE);
 
228
         res->texture =
 
229
            etna_resource_alloc(pctx->screen, ETNA_LAYOUT_TILED,
 
230
                                DRM_FORMAT_MOD_LINEAR, &templat);
 
231
      }
 
232
 
 
233
      if (!res->texture) {
 
234
         return NULL;
 
235
      }
 
236
      res = etna_resource(res->texture);
 
237
   }
 
238
   return res;
 
239
}
 
240
 
 
241
static void
 
242
set_sampler_views(struct etna_context *ctx, unsigned start, unsigned end,
 
243
                  unsigned nr, bool take_ownership, struct pipe_sampler_view **views)
 
244
{
 
245
   unsigned i, j;
 
246
   uint32_t mask = 1 << start;
 
247
   uint32_t prev_active_sampler_views = ctx->active_sampler_views;
 
248
 
 
249
   for (i = start, j = 0; j < nr; i++, j++, mask <<= 1) {
 
250
      struct pipe_sampler_view *view = views ? views[j] : NULL;
 
251
 
 
252
      if (take_ownership) {
 
253
         pipe_sampler_view_reference(&ctx->sampler_view[i], NULL);
 
254
         ctx->sampler_view[i] = view;
 
255
      } else {
 
256
         pipe_sampler_view_reference(&ctx->sampler_view[i], view);
 
257
      }
 
258
      if (view) {
 
259
         ctx->active_sampler_views |= mask;
 
260
         ctx->dirty_sampler_views |= mask;
 
261
      } else
 
262
         ctx->active_sampler_views &= ~mask;
 
263
   }
 
264
 
 
265
   for (; i < end; i++, mask <<= 1) {
 
266
      pipe_sampler_view_reference(&ctx->sampler_view[i], NULL);
 
267
      ctx->active_sampler_views &= ~mask;
 
268
   }
 
269
 
 
270
   /* sampler views that changed state (even to inactive) are also dirty */
 
271
   ctx->dirty_sampler_views |= ctx->active_sampler_views ^ prev_active_sampler_views;
 
272
}
 
273
 
 
274
static inline void
 
275
etna_fragtex_set_sampler_views(struct etna_context *ctx, unsigned nr,
 
276
                               bool take_ownership,
 
277
                               struct pipe_sampler_view **views)
 
278
{
 
279
   struct etna_screen *screen = ctx->screen;
 
280
   unsigned start = 0;
 
281
   unsigned end = start + screen->specs.fragment_sampler_count;
 
282
 
 
283
   set_sampler_views(ctx, start, end, nr, take_ownership, views);
 
284
   ctx->num_fragment_sampler_views = nr;
 
285
}
 
286
 
 
287
 
 
288
static inline void
 
289
etna_vertex_set_sampler_views(struct etna_context *ctx, unsigned nr,
 
290
                              bool take_ownership,
 
291
                              struct pipe_sampler_view **views)
 
292
{
 
293
   struct etna_screen *screen = ctx->screen;
 
294
   unsigned start = screen->specs.vertex_sampler_offset;
 
295
   unsigned end = start + screen->specs.vertex_sampler_count;
 
296
 
 
297
   set_sampler_views(ctx, start, end, nr, take_ownership, views);
 
298
}
 
299
 
 
300
static void
 
301
etna_set_sampler_views(struct pipe_context *pctx, enum pipe_shader_type shader,
 
302
                       unsigned start_slot, unsigned num_views,
 
303
                       unsigned unbind_num_trailing_slots,
 
304
                       bool take_ownership,
 
305
                       struct pipe_sampler_view **views)
 
306
{
 
307
   struct etna_context *ctx = etna_context(pctx);
 
308
   assert(start_slot == 0);
 
309
 
 
310
   ctx->dirty |= ETNA_DIRTY_SAMPLER_VIEWS | ETNA_DIRTY_TEXTURE_CACHES;
 
311
 
 
312
   switch (shader) {
 
313
   case PIPE_SHADER_FRAGMENT:
 
314
      etna_fragtex_set_sampler_views(ctx, num_views, take_ownership, views);
 
315
      break;
 
316
   case PIPE_SHADER_VERTEX:
 
317
      etna_vertex_set_sampler_views(ctx, num_views, take_ownership, views);
 
318
      break;
 
319
   default:;
 
320
   }
 
321
}
 
322
 
 
323
static void
 
324
etna_texture_barrier(struct pipe_context *pctx, unsigned flags)
 
325
{
 
326
   struct etna_context *ctx = etna_context(pctx);
 
327
   /* clear color and texture cache to make sure that texture unit reads
 
328
    * what has been written */
 
329
   mtx_lock(&ctx->lock);
 
330
   etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_TEXTURE);
 
331
   mtx_unlock(&ctx->lock);
 
332
}
 
333
 
 
334
uint32_t
 
335
active_samplers_bits(struct etna_context *ctx)
 
336
{
 
337
   return ctx->active_sampler_views & ctx->active_samplers;
 
338
}
 
339
 
 
340
void
 
341
etna_texture_init(struct pipe_context *pctx)
 
342
{
 
343
   struct etna_context *ctx = etna_context(pctx);
 
344
   struct etna_screen *screen = ctx->screen;
 
345
 
 
346
   pctx->bind_sampler_states = etna_bind_sampler_states;
 
347
   pctx->set_sampler_views = etna_set_sampler_views;
 
348
   pctx->texture_barrier = etna_texture_barrier;
 
349
 
 
350
   if (screen->specs.halti >= 5)
 
351
      etna_texture_desc_init(pctx);
 
352
   else
 
353
      etna_texture_state_init(pctx);
 
354
}