1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Rob Clark <robclark@freedesktop.org>
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "pipe/p_state.h"
28bf215546Sopenharmony_ci#include "util/format/u_format.h"
29bf215546Sopenharmony_ci#include "util/u_draw.h"
30bf215546Sopenharmony_ci#include "util/u_helpers.h"
31bf215546Sopenharmony_ci#include "util/u_memory.h"
32bf215546Sopenharmony_ci#include "util/u_prim.h"
33bf215546Sopenharmony_ci#include "util/u_string.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "freedreno_blitter.h"
36bf215546Sopenharmony_ci#include "freedreno_context.h"
37bf215546Sopenharmony_ci#include "freedreno_draw.h"
38bf215546Sopenharmony_ci#include "freedreno_fence.h"
39bf215546Sopenharmony_ci#include "freedreno_query_acc.h"
40bf215546Sopenharmony_ci#include "freedreno_query_hw.h"
41bf215546Sopenharmony_ci#include "freedreno_resource.h"
42bf215546Sopenharmony_ci#include "freedreno_state.h"
43bf215546Sopenharmony_ci#include "freedreno_util.h"
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_cistatic void
46bf215546Sopenharmony_ciresource_read(struct fd_batch *batch, struct pipe_resource *prsc) assert_dt
47bf215546Sopenharmony_ci{
48bf215546Sopenharmony_ci   if (!prsc)
49bf215546Sopenharmony_ci      return;
50bf215546Sopenharmony_ci   fd_batch_resource_read(batch, fd_resource(prsc));
51bf215546Sopenharmony_ci}
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_cistatic void
54bf215546Sopenharmony_ciresource_written(struct fd_batch *batch, struct pipe_resource *prsc) assert_dt
55bf215546Sopenharmony_ci{
56bf215546Sopenharmony_ci   if (!prsc)
57bf215546Sopenharmony_ci      return;
58bf215546Sopenharmony_ci   fd_batch_resource_write(batch, fd_resource(prsc));
59bf215546Sopenharmony_ci}
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_cistatic void
62bf215546Sopenharmony_cibatch_draw_tracking_for_dirty_bits(struct fd_batch *batch) assert_dt
63bf215546Sopenharmony_ci{
64bf215546Sopenharmony_ci   struct fd_context *ctx = batch->ctx;
65bf215546Sopenharmony_ci   struct pipe_framebuffer_state *pfb = &batch->framebuffer;
66bf215546Sopenharmony_ci   unsigned buffers = 0, restore_buffers = 0;
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci   if (ctx->dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_ZSA)) {
69bf215546Sopenharmony_ci      if (fd_depth_enabled(ctx)) {
70bf215546Sopenharmony_ci         if (fd_resource(pfb->zsbuf->texture)->valid) {
71bf215546Sopenharmony_ci            restore_buffers |= FD_BUFFER_DEPTH;
72bf215546Sopenharmony_ci            /* storing packed d/s depth also stores stencil, so we need
73bf215546Sopenharmony_ci             * the stencil restored too to avoid invalidating it.
74bf215546Sopenharmony_ci             */
75bf215546Sopenharmony_ci            if (pfb->zsbuf->texture->format == PIPE_FORMAT_Z24_UNORM_S8_UINT)
76bf215546Sopenharmony_ci               restore_buffers |= FD_BUFFER_STENCIL;
77bf215546Sopenharmony_ci         } else {
78bf215546Sopenharmony_ci            batch->invalidated |= FD_BUFFER_DEPTH;
79bf215546Sopenharmony_ci         }
80bf215546Sopenharmony_ci         batch->gmem_reason |= FD_GMEM_DEPTH_ENABLED;
81bf215546Sopenharmony_ci         if (fd_depth_write_enabled(ctx)) {
82bf215546Sopenharmony_ci            buffers |= FD_BUFFER_DEPTH;
83bf215546Sopenharmony_ci            resource_written(batch, pfb->zsbuf->texture);
84bf215546Sopenharmony_ci         } else {
85bf215546Sopenharmony_ci            resource_read(batch, pfb->zsbuf->texture);
86bf215546Sopenharmony_ci         }
87bf215546Sopenharmony_ci      }
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci      if (fd_stencil_enabled(ctx)) {
90bf215546Sopenharmony_ci         if (fd_resource(pfb->zsbuf->texture)->valid) {
91bf215546Sopenharmony_ci            restore_buffers |= FD_BUFFER_STENCIL;
92bf215546Sopenharmony_ci            /* storing packed d/s stencil also stores depth, so we need
93bf215546Sopenharmony_ci             * the depth restored too to avoid invalidating it.
94bf215546Sopenharmony_ci             */
95bf215546Sopenharmony_ci            if (pfb->zsbuf->texture->format == PIPE_FORMAT_Z24_UNORM_S8_UINT)
96bf215546Sopenharmony_ci               restore_buffers |= FD_BUFFER_DEPTH;
97bf215546Sopenharmony_ci         } else {
98bf215546Sopenharmony_ci            batch->invalidated |= FD_BUFFER_STENCIL;
99bf215546Sopenharmony_ci         }
100bf215546Sopenharmony_ci         batch->gmem_reason |= FD_GMEM_STENCIL_ENABLED;
101bf215546Sopenharmony_ci         buffers |= FD_BUFFER_STENCIL;
102bf215546Sopenharmony_ci         resource_written(batch, pfb->zsbuf->texture);
103bf215546Sopenharmony_ci      }
104bf215546Sopenharmony_ci   }
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci   if (ctx->dirty & FD_DIRTY_FRAMEBUFFER) {
107bf215546Sopenharmony_ci      for (unsigned i = 0; i < pfb->nr_cbufs; i++) {
108bf215546Sopenharmony_ci         struct pipe_resource *surf;
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci         if (!pfb->cbufs[i])
111bf215546Sopenharmony_ci            continue;
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci         surf = pfb->cbufs[i]->texture;
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci         if (fd_resource(surf)->valid) {
116bf215546Sopenharmony_ci            restore_buffers |= PIPE_CLEAR_COLOR0 << i;
117bf215546Sopenharmony_ci         } else {
118bf215546Sopenharmony_ci            batch->invalidated |= PIPE_CLEAR_COLOR0 << i;
119bf215546Sopenharmony_ci         }
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci         buffers |= PIPE_CLEAR_COLOR0 << i;
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci         if (ctx->dirty & FD_DIRTY_FRAMEBUFFER)
124bf215546Sopenharmony_ci            resource_written(batch, pfb->cbufs[i]->texture);
125bf215546Sopenharmony_ci      }
126bf215546Sopenharmony_ci   }
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   if (ctx->dirty & FD_DIRTY_BLEND) {
129bf215546Sopenharmony_ci      if (ctx->blend->logicop_enable)
130bf215546Sopenharmony_ci         batch->gmem_reason |= FD_GMEM_LOGICOP_ENABLED;
131bf215546Sopenharmony_ci      for (unsigned i = 0; i < pfb->nr_cbufs; i++) {
132bf215546Sopenharmony_ci         if (ctx->blend->rt[i].blend_enable)
133bf215546Sopenharmony_ci            batch->gmem_reason |= FD_GMEM_BLEND_ENABLED;
134bf215546Sopenharmony_ci      }
135bf215546Sopenharmony_ci   }
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci   /* Mark SSBOs */
138bf215546Sopenharmony_ci   if (ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_SSBO) {
139bf215546Sopenharmony_ci      const struct fd_shaderbuf_stateobj *so =
140bf215546Sopenharmony_ci         &ctx->shaderbuf[PIPE_SHADER_FRAGMENT];
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci      u_foreach_bit (i, so->enabled_mask & so->writable_mask)
143bf215546Sopenharmony_ci         resource_written(batch, so->sb[i].buffer);
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci      u_foreach_bit (i, so->enabled_mask & ~so->writable_mask)
146bf215546Sopenharmony_ci         resource_read(batch, so->sb[i].buffer);
147bf215546Sopenharmony_ci   }
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   if (ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_IMAGE) {
150bf215546Sopenharmony_ci      u_foreach_bit (i, ctx->shaderimg[PIPE_SHADER_FRAGMENT].enabled_mask) {
151bf215546Sopenharmony_ci         struct pipe_image_view *img =
152bf215546Sopenharmony_ci            &ctx->shaderimg[PIPE_SHADER_FRAGMENT].si[i];
153bf215546Sopenharmony_ci         if (img->access & PIPE_IMAGE_ACCESS_WRITE)
154bf215546Sopenharmony_ci            resource_written(batch, img->resource);
155bf215546Sopenharmony_ci         else
156bf215546Sopenharmony_ci            resource_read(batch, img->resource);
157bf215546Sopenharmony_ci      }
158bf215546Sopenharmony_ci   }
159bf215546Sopenharmony_ci
160bf215546Sopenharmony_ci   u_foreach_bit (s, ctx->bound_shader_stages) {
161bf215546Sopenharmony_ci      /* Mark constbuf as being read: */
162bf215546Sopenharmony_ci      if (ctx->dirty_shader[s] & FD_DIRTY_SHADER_CONST) {
163bf215546Sopenharmony_ci         u_foreach_bit (i, ctx->constbuf[s].enabled_mask)
164bf215546Sopenharmony_ci            resource_read(batch, ctx->constbuf[s].cb[i].buffer);
165bf215546Sopenharmony_ci      }
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci      /* Mark textures as being read */
168bf215546Sopenharmony_ci      if (ctx->dirty_shader[s] & FD_DIRTY_SHADER_TEX) {
169bf215546Sopenharmony_ci         u_foreach_bit (i, ctx->tex[s].valid_textures)
170bf215546Sopenharmony_ci            resource_read(batch, ctx->tex[s].textures[i]->texture);
171bf215546Sopenharmony_ci      }
172bf215546Sopenharmony_ci   }
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci   /* Mark VBOs as being read */
175bf215546Sopenharmony_ci   if (ctx->dirty & FD_DIRTY_VTXBUF) {
176bf215546Sopenharmony_ci      u_foreach_bit (i, ctx->vtx.vertexbuf.enabled_mask) {
177bf215546Sopenharmony_ci         assert(!ctx->vtx.vertexbuf.vb[i].is_user_buffer);
178bf215546Sopenharmony_ci         resource_read(batch, ctx->vtx.vertexbuf.vb[i].buffer.resource);
179bf215546Sopenharmony_ci      }
180bf215546Sopenharmony_ci   }
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   /* Mark streamout buffers as being written.. */
183bf215546Sopenharmony_ci   if (ctx->dirty & FD_DIRTY_STREAMOUT) {
184bf215546Sopenharmony_ci      for (unsigned i = 0; i < ctx->streamout.num_targets; i++)
185bf215546Sopenharmony_ci         if (ctx->streamout.targets[i])
186bf215546Sopenharmony_ci            resource_written(batch, ctx->streamout.targets[i]->buffer);
187bf215546Sopenharmony_ci   }
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   /* any buffers that haven't been cleared yet, we need to restore: */
190bf215546Sopenharmony_ci   batch->restore |= restore_buffers & (FD_BUFFER_ALL & ~batch->invalidated);
191bf215546Sopenharmony_ci   /* and any buffers used, need to be resolved: */
192bf215546Sopenharmony_ci   batch->resolve |= buffers;
193bf215546Sopenharmony_ci}
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_cistatic void
196bf215546Sopenharmony_cibatch_draw_tracking(struct fd_batch *batch, const struct pipe_draw_info *info,
197bf215546Sopenharmony_ci                    const struct pipe_draw_indirect_info *indirect) assert_dt
198bf215546Sopenharmony_ci{
199bf215546Sopenharmony_ci   struct fd_context *ctx = batch->ctx;
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   /* NOTE: needs to be before resource_written(batch->query_buf), otherwise
202bf215546Sopenharmony_ci    * query_buf may not be created yet.
203bf215546Sopenharmony_ci    */
204bf215546Sopenharmony_ci   fd_batch_update_queries(batch);
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci   /*
207bf215546Sopenharmony_ci    * Figure out the buffers/features we need:
208bf215546Sopenharmony_ci    */
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci   fd_screen_lock(ctx->screen);
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci   if (ctx->dirty & FD_DIRTY_RESOURCE)
213bf215546Sopenharmony_ci      batch_draw_tracking_for_dirty_bits(batch);
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci   /* Mark index buffer as being read */
216bf215546Sopenharmony_ci   if (info->index_size)
217bf215546Sopenharmony_ci      resource_read(batch, info->index.resource);
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci   /* Mark indirect draw buffer as being read */
220bf215546Sopenharmony_ci   if (indirect) {
221bf215546Sopenharmony_ci      if (indirect->buffer)
222bf215546Sopenharmony_ci         resource_read(batch, indirect->buffer);
223bf215546Sopenharmony_ci      if (indirect->count_from_stream_output)
224bf215546Sopenharmony_ci         resource_read(
225bf215546Sopenharmony_ci            batch, fd_stream_output_target(indirect->count_from_stream_output)
226bf215546Sopenharmony_ci                      ->offset_buf);
227bf215546Sopenharmony_ci   }
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci   resource_written(batch, batch->query_buf);
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci   list_for_each_entry (struct fd_acc_query, aq, &ctx->acc_active_queries, node)
232bf215546Sopenharmony_ci      resource_written(batch, aq->prsc);
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci   fd_screen_unlock(ctx->screen);
235bf215546Sopenharmony_ci}
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_cistatic void
238bf215546Sopenharmony_ciupdate_draw_stats(struct fd_context *ctx, const struct pipe_draw_info *info,
239bf215546Sopenharmony_ci                  const struct pipe_draw_start_count_bias *draws,
240bf215546Sopenharmony_ci                  unsigned num_draws) assert_dt
241bf215546Sopenharmony_ci{
242bf215546Sopenharmony_ci   ctx->stats.draw_calls++;
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci   if (ctx->screen->gen < 6) {
245bf215546Sopenharmony_ci      /* Counting prims in sw doesn't work for GS and tesselation. For older
246bf215546Sopenharmony_ci       * gens we don't have those stages and don't have the hw counters enabled,
247bf215546Sopenharmony_ci       * so keep the count accurate for non-patch geometry.
248bf215546Sopenharmony_ci       */
249bf215546Sopenharmony_ci      unsigned prims = 0;
250bf215546Sopenharmony_ci      if ((info->mode != PIPE_PRIM_PATCHES) && (info->mode != PIPE_PRIM_MAX)) {
251bf215546Sopenharmony_ci         for (unsigned i = 0; i < num_draws; i++) {
252bf215546Sopenharmony_ci            prims += u_reduced_prims_for_vertices(info->mode, draws[i].count);
253bf215546Sopenharmony_ci         }
254bf215546Sopenharmony_ci      }
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci      ctx->stats.prims_generated += prims;
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci      if (ctx->streamout.num_targets > 0) {
259bf215546Sopenharmony_ci         /* Clip the prims we're writing to the size of the SO buffers. */
260bf215546Sopenharmony_ci         enum pipe_prim_type tf_prim = u_decomposed_prim(info->mode);
261bf215546Sopenharmony_ci         unsigned verts_written = u_vertices_for_prims(tf_prim, prims);
262bf215546Sopenharmony_ci         unsigned remaining_vert_space =
263bf215546Sopenharmony_ci            ctx->streamout.max_tf_vtx - ctx->streamout.verts_written;
264bf215546Sopenharmony_ci         if (verts_written > remaining_vert_space) {
265bf215546Sopenharmony_ci            verts_written = remaining_vert_space;
266bf215546Sopenharmony_ci            u_trim_pipe_prim(tf_prim, &remaining_vert_space);
267bf215546Sopenharmony_ci         }
268bf215546Sopenharmony_ci         ctx->streamout.verts_written += verts_written;
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci         ctx->stats.prims_emitted +=
271bf215546Sopenharmony_ci            u_reduced_prims_for_vertices(tf_prim, verts_written);
272bf215546Sopenharmony_ci      }
273bf215546Sopenharmony_ci   }
274bf215546Sopenharmony_ci}
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_cistatic void
277bf215546Sopenharmony_cifd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
278bf215546Sopenharmony_ci		unsigned drawid_offset,
279bf215546Sopenharmony_ci            const struct pipe_draw_indirect_info *indirect,
280bf215546Sopenharmony_ci            const struct pipe_draw_start_count_bias *draws, unsigned num_draws) in_dt
281bf215546Sopenharmony_ci{
282bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci   /* for debugging problems with indirect draw, it is convenient
285bf215546Sopenharmony_ci    * to be able to emulate it, to determine if game is feeding us
286bf215546Sopenharmony_ci    * bogus data:
287bf215546Sopenharmony_ci    */
288bf215546Sopenharmony_ci   if (indirect && indirect->buffer && FD_DBG(NOINDR)) {
289bf215546Sopenharmony_ci      /* num_draws is only applicable for direct draws: */
290bf215546Sopenharmony_ci      assert(num_draws == 1);
291bf215546Sopenharmony_ci      util_draw_indirect(pctx, info, indirect);
292bf215546Sopenharmony_ci      return;
293bf215546Sopenharmony_ci   }
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci   /* TODO: push down the region versions into the tiles */
296bf215546Sopenharmony_ci   if (!fd_render_condition_check(pctx))
297bf215546Sopenharmony_ci      return;
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_ci   /* Upload a user index buffer. */
300bf215546Sopenharmony_ci   struct pipe_resource *indexbuf = NULL;
301bf215546Sopenharmony_ci   unsigned index_offset = 0;
302bf215546Sopenharmony_ci   struct pipe_draw_info new_info;
303bf215546Sopenharmony_ci   if (info->index_size) {
304bf215546Sopenharmony_ci      if (info->has_user_indices) {
305bf215546Sopenharmony_ci         if (num_draws > 1) {
306bf215546Sopenharmony_ci            util_draw_multi(pctx, info, drawid_offset, indirect, draws, num_draws);
307bf215546Sopenharmony_ci            return;
308bf215546Sopenharmony_ci         }
309bf215546Sopenharmony_ci         if (!util_upload_index_buffer(pctx, info, &draws[0], &indexbuf,
310bf215546Sopenharmony_ci                                       &index_offset, 4))
311bf215546Sopenharmony_ci            return;
312bf215546Sopenharmony_ci         new_info = *info;
313bf215546Sopenharmony_ci         new_info.index.resource = indexbuf;
314bf215546Sopenharmony_ci         new_info.has_user_indices = false;
315bf215546Sopenharmony_ci         info = &new_info;
316bf215546Sopenharmony_ci      } else {
317bf215546Sopenharmony_ci         indexbuf = info->index.resource;
318bf215546Sopenharmony_ci      }
319bf215546Sopenharmony_ci   }
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   if ((ctx->streamout.num_targets > 0) && (num_draws > 1)) {
322bf215546Sopenharmony_ci      util_draw_multi(pctx, info, drawid_offset, indirect, draws, num_draws);
323bf215546Sopenharmony_ci      return;
324bf215546Sopenharmony_ci   }
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci   struct fd_batch *batch = fd_context_batch(ctx);
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci   batch_draw_tracking(batch, info, indirect);
329bf215546Sopenharmony_ci
330bf215546Sopenharmony_ci   while (unlikely(!fd_batch_lock_submit(batch))) {
331bf215546Sopenharmony_ci      /* The current batch was flushed in batch_draw_tracking()
332bf215546Sopenharmony_ci       * so start anew.  We know this won't happen a second time
333bf215546Sopenharmony_ci       * since we are dealing with a fresh batch:
334bf215546Sopenharmony_ci       */
335bf215546Sopenharmony_ci      fd_batch_reference(&batch, NULL);
336bf215546Sopenharmony_ci      batch = fd_context_batch(ctx);
337bf215546Sopenharmony_ci      batch_draw_tracking(batch, info, indirect);
338bf215546Sopenharmony_ci      assert(ctx->batch == batch);
339bf215546Sopenharmony_ci   }
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci   batch->num_draws++;
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci   /* Marking the batch as needing flush must come after the batch
344bf215546Sopenharmony_ci    * dependency tracking (resource_read()/resource_write()), as that
345bf215546Sopenharmony_ci    * can trigger a flush
346bf215546Sopenharmony_ci    */
347bf215546Sopenharmony_ci   fd_batch_needs_flush(batch);
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci   struct pipe_framebuffer_state *pfb = &batch->framebuffer;
350bf215546Sopenharmony_ci   DBG("%p: %ux%u num_draws=%u (%s/%s)", batch, pfb->width, pfb->height,
351bf215546Sopenharmony_ci       batch->num_draws,
352bf215546Sopenharmony_ci       util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
353bf215546Sopenharmony_ci       util_format_short_name(pipe_surface_format(pfb->zsbuf)));
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci   batch->cost += ctx->draw_cost;
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_draws; i++) {
358bf215546Sopenharmony_ci      ctx->draw_vbo(ctx, info, drawid_offset, indirect, &draws[i], index_offset);
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci      batch->num_vertices += draws[i].count * info->instance_count;
361bf215546Sopenharmony_ci   }
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci   if (unlikely(ctx->stats_users > 0))
364bf215546Sopenharmony_ci      update_draw_stats(ctx, info, draws, num_draws);
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_ci   for (unsigned i = 0; i < ctx->streamout.num_targets; i++) {
367bf215546Sopenharmony_ci      assert(num_draws == 1);
368bf215546Sopenharmony_ci      ctx->streamout.offsets[i] += draws[0].count;
369bf215546Sopenharmony_ci   }
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_ci   if (FD_DBG(DDRAW))
372bf215546Sopenharmony_ci      fd_context_all_dirty(ctx);
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci   assert(!batch->flushed);
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci   fd_batch_unlock_submit(batch);
377bf215546Sopenharmony_ci   fd_batch_check_size(batch);
378bf215546Sopenharmony_ci   fd_batch_reference(&batch, NULL);
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci   if (info == &new_info)
381bf215546Sopenharmony_ci      pipe_resource_reference(&indexbuf, NULL);
382bf215546Sopenharmony_ci}
383bf215546Sopenharmony_ci
384bf215546Sopenharmony_cistatic void
385bf215546Sopenharmony_cibatch_clear_tracking(struct fd_batch *batch, unsigned buffers) assert_dt
386bf215546Sopenharmony_ci{
387bf215546Sopenharmony_ci   struct fd_context *ctx = batch->ctx;
388bf215546Sopenharmony_ci   struct pipe_framebuffer_state *pfb = &batch->framebuffer;
389bf215546Sopenharmony_ci   unsigned cleared_buffers;
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci   /* pctx->clear() is only for full-surface clears, so scissor is
392bf215546Sopenharmony_ci    * equivalent to having GL_SCISSOR_TEST disabled:
393bf215546Sopenharmony_ci    */
394bf215546Sopenharmony_ci   batch->max_scissor.minx = 0;
395bf215546Sopenharmony_ci   batch->max_scissor.miny = 0;
396bf215546Sopenharmony_ci   batch->max_scissor.maxx = pfb->width;
397bf215546Sopenharmony_ci   batch->max_scissor.maxy = pfb->height;
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   /* for bookkeeping about which buffers have been cleared (and thus
400bf215546Sopenharmony_ci    * can fully or partially skip mem2gmem) we need to ignore buffers
401bf215546Sopenharmony_ci    * that have already had a draw, in case apps do silly things like
402bf215546Sopenharmony_ci    * clear after draw (ie. if you only clear the color buffer, but
403bf215546Sopenharmony_ci    * something like alpha-test causes side effects from the draw in
404bf215546Sopenharmony_ci    * the depth buffer, etc)
405bf215546Sopenharmony_ci    */
406bf215546Sopenharmony_ci   cleared_buffers = buffers & (FD_BUFFER_ALL & ~batch->restore);
407bf215546Sopenharmony_ci   batch->cleared |= buffers;
408bf215546Sopenharmony_ci   batch->invalidated |= cleared_buffers;
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci   batch->resolve |= buffers;
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci   fd_screen_lock(ctx->screen);
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_ci   if (buffers & PIPE_CLEAR_COLOR)
415bf215546Sopenharmony_ci      for (unsigned i = 0; i < pfb->nr_cbufs; i++)
416bf215546Sopenharmony_ci         if (buffers & (PIPE_CLEAR_COLOR0 << i))
417bf215546Sopenharmony_ci            resource_written(batch, pfb->cbufs[i]->texture);
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_ci   if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
420bf215546Sopenharmony_ci      resource_written(batch, pfb->zsbuf->texture);
421bf215546Sopenharmony_ci      batch->gmem_reason |= FD_GMEM_CLEARS_DEPTH_STENCIL;
422bf215546Sopenharmony_ci   }
423bf215546Sopenharmony_ci
424bf215546Sopenharmony_ci   resource_written(batch, batch->query_buf);
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci   list_for_each_entry (struct fd_acc_query, aq, &ctx->acc_active_queries, node)
427bf215546Sopenharmony_ci      resource_written(batch, aq->prsc);
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci   fd_screen_unlock(ctx->screen);
430bf215546Sopenharmony_ci}
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_cistatic void
433bf215546Sopenharmony_cifd_clear(struct pipe_context *pctx, unsigned buffers,
434bf215546Sopenharmony_ci         const struct pipe_scissor_state *scissor_state,
435bf215546Sopenharmony_ci         const union pipe_color_union *color, double depth,
436bf215546Sopenharmony_ci         unsigned stencil) in_dt
437bf215546Sopenharmony_ci{
438bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   /* TODO: push down the region versions into the tiles */
441bf215546Sopenharmony_ci   if (!fd_render_condition_check(pctx))
442bf215546Sopenharmony_ci      return;
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci   struct fd_batch *batch = fd_context_batch(ctx);
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_ci   batch_clear_tracking(batch, buffers);
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_ci   while (unlikely(!fd_batch_lock_submit(batch))) {
449bf215546Sopenharmony_ci      /* The current batch was flushed in batch_clear_tracking()
450bf215546Sopenharmony_ci       * so start anew.  We know this won't happen a second time
451bf215546Sopenharmony_ci       * since we are dealing with a fresh batch:
452bf215546Sopenharmony_ci       */
453bf215546Sopenharmony_ci      fd_batch_reference(&batch, NULL);
454bf215546Sopenharmony_ci      batch = fd_context_batch(ctx);
455bf215546Sopenharmony_ci      batch_clear_tracking(batch, buffers);
456bf215546Sopenharmony_ci      assert(ctx->batch == batch);
457bf215546Sopenharmony_ci   }
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci   /* Marking the batch as needing flush must come after the batch
460bf215546Sopenharmony_ci    * dependency tracking (resource_read()/resource_write()), as that
461bf215546Sopenharmony_ci    * can trigger a flush
462bf215546Sopenharmony_ci    */
463bf215546Sopenharmony_ci   fd_batch_needs_flush(batch);
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci   struct pipe_framebuffer_state *pfb = &batch->framebuffer;
466bf215546Sopenharmony_ci   DBG("%p: %x %ux%u depth=%f, stencil=%u (%s/%s)", batch, buffers, pfb->width,
467bf215546Sopenharmony_ci       pfb->height, depth, stencil,
468bf215546Sopenharmony_ci       util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
469bf215546Sopenharmony_ci       util_format_short_name(pipe_surface_format(pfb->zsbuf)));
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci   /* if per-gen backend doesn't implement ctx->clear() generic
472bf215546Sopenharmony_ci    * blitter clear:
473bf215546Sopenharmony_ci    */
474bf215546Sopenharmony_ci   bool fallback = true;
475bf215546Sopenharmony_ci
476bf215546Sopenharmony_ci   if (ctx->clear) {
477bf215546Sopenharmony_ci      fd_batch_update_queries(batch);
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci      if (ctx->clear(ctx, buffers, color, depth, stencil)) {
480bf215546Sopenharmony_ci         if (FD_DBG(DCLEAR))
481bf215546Sopenharmony_ci            fd_context_all_dirty(ctx);
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci         fallback = false;
484bf215546Sopenharmony_ci      }
485bf215546Sopenharmony_ci   }
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci   assert(!batch->flushed);
488bf215546Sopenharmony_ci
489bf215546Sopenharmony_ci   fd_batch_unlock_submit(batch);
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci   if (fallback) {
492bf215546Sopenharmony_ci      fd_blitter_clear(pctx, buffers, color, depth, stencil);
493bf215546Sopenharmony_ci   }
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_ci   fd_batch_check_size(batch);
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci   fd_batch_reference(&batch, NULL);
498bf215546Sopenharmony_ci}
499bf215546Sopenharmony_ci
500bf215546Sopenharmony_cistatic void
501bf215546Sopenharmony_cifd_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps,
502bf215546Sopenharmony_ci                       const union pipe_color_union *color, unsigned x,
503bf215546Sopenharmony_ci                       unsigned y, unsigned w, unsigned h,
504bf215546Sopenharmony_ci                       bool render_condition_enabled)
505bf215546Sopenharmony_ci{
506bf215546Sopenharmony_ci   DBG("TODO: x=%u, y=%u, w=%u, h=%u", x, y, w, h);
507bf215546Sopenharmony_ci}
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_cistatic void
510bf215546Sopenharmony_cifd_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps,
511bf215546Sopenharmony_ci                       unsigned buffers, double depth, unsigned stencil,
512bf215546Sopenharmony_ci                       unsigned x, unsigned y, unsigned w, unsigned h,
513bf215546Sopenharmony_ci                       bool render_condition_enabled)
514bf215546Sopenharmony_ci{
515bf215546Sopenharmony_ci   DBG("TODO: buffers=%u, depth=%f, stencil=%u, x=%u, y=%u, w=%u, h=%u",
516bf215546Sopenharmony_ci       buffers, depth, stencil, x, y, w, h);
517bf215546Sopenharmony_ci}
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_cistatic void
520bf215546Sopenharmony_cifd_launch_grid(struct pipe_context *pctx,
521bf215546Sopenharmony_ci               const struct pipe_grid_info *info) in_dt
522bf215546Sopenharmony_ci{
523bf215546Sopenharmony_ci   struct fd_context *ctx = fd_context(pctx);
524bf215546Sopenharmony_ci   const struct fd_shaderbuf_stateobj *so =
525bf215546Sopenharmony_ci      &ctx->shaderbuf[PIPE_SHADER_COMPUTE];
526bf215546Sopenharmony_ci   struct fd_batch *batch, *save_batch = NULL;
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci   batch = fd_bc_alloc_batch(ctx, true);
529bf215546Sopenharmony_ci   fd_batch_reference(&save_batch, ctx->batch);
530bf215546Sopenharmony_ci   fd_batch_reference(&ctx->batch, batch);
531bf215546Sopenharmony_ci   fd_context_all_dirty(ctx);
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci   fd_screen_lock(ctx->screen);
534bf215546Sopenharmony_ci
535bf215546Sopenharmony_ci   /* Mark SSBOs */
536bf215546Sopenharmony_ci   u_foreach_bit (i, so->enabled_mask & so->writable_mask)
537bf215546Sopenharmony_ci      resource_written(batch, so->sb[i].buffer);
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_ci   u_foreach_bit (i, so->enabled_mask & ~so->writable_mask)
540bf215546Sopenharmony_ci      resource_read(batch, so->sb[i].buffer);
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci   u_foreach_bit (i, ctx->shaderimg[PIPE_SHADER_COMPUTE].enabled_mask) {
543bf215546Sopenharmony_ci      struct pipe_image_view *img = &ctx->shaderimg[PIPE_SHADER_COMPUTE].si[i];
544bf215546Sopenharmony_ci      if (img->access & PIPE_IMAGE_ACCESS_WRITE)
545bf215546Sopenharmony_ci         resource_written(batch, img->resource);
546bf215546Sopenharmony_ci      else
547bf215546Sopenharmony_ci         resource_read(batch, img->resource);
548bf215546Sopenharmony_ci   }
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci   /* UBO's are read */
551bf215546Sopenharmony_ci   u_foreach_bit (i, ctx->constbuf[PIPE_SHADER_COMPUTE].enabled_mask)
552bf215546Sopenharmony_ci      resource_read(batch, ctx->constbuf[PIPE_SHADER_COMPUTE].cb[i].buffer);
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci   /* Mark textures as being read */
555bf215546Sopenharmony_ci   u_foreach_bit (i, ctx->tex[PIPE_SHADER_COMPUTE].valid_textures)
556bf215546Sopenharmony_ci      resource_read(batch, ctx->tex[PIPE_SHADER_COMPUTE].textures[i]->texture);
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci   /* For global buffers, we don't really know if read or written, so assume
559bf215546Sopenharmony_ci    * the worst:
560bf215546Sopenharmony_ci    */
561bf215546Sopenharmony_ci   u_foreach_bit (i, ctx->global_bindings.enabled_mask)
562bf215546Sopenharmony_ci      resource_written(batch, ctx->global_bindings.buf[i]);
563bf215546Sopenharmony_ci
564bf215546Sopenharmony_ci   if (info->indirect)
565bf215546Sopenharmony_ci      resource_read(batch, info->indirect);
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_ci   fd_screen_unlock(ctx->screen);
568bf215546Sopenharmony_ci
569bf215546Sopenharmony_ci   DBG("%p: work_dim=%u, block=%ux%ux%u, grid=%ux%ux%u",
570bf215546Sopenharmony_ci       batch, info->work_dim,
571bf215546Sopenharmony_ci       info->block[0], info->block[1], info->block[2],
572bf215546Sopenharmony_ci       info->grid[0], info->grid[1], info->grid[2]);
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci   fd_batch_needs_flush(batch);
575bf215546Sopenharmony_ci   ctx->launch_grid(ctx, info);
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ci   fd_batch_flush(batch);
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci   fd_batch_reference(&ctx->batch, save_batch);
580bf215546Sopenharmony_ci   fd_context_all_dirty(ctx);
581bf215546Sopenharmony_ci   fd_batch_reference(&save_batch, NULL);
582bf215546Sopenharmony_ci   fd_batch_reference(&batch, NULL);
583bf215546Sopenharmony_ci}
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_civoid
586bf215546Sopenharmony_cifd_draw_init(struct pipe_context *pctx)
587bf215546Sopenharmony_ci{
588bf215546Sopenharmony_ci   pctx->draw_vbo = fd_draw_vbo;
589bf215546Sopenharmony_ci   pctx->clear = fd_clear;
590bf215546Sopenharmony_ci   pctx->clear_render_target = fd_clear_render_target;
591bf215546Sopenharmony_ci   pctx->clear_depth_stencil = fd_clear_depth_stencil;
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci   if (has_compute(fd_screen(pctx->screen))) {
594bf215546Sopenharmony_ci      pctx->launch_grid = fd_launch_grid;
595bf215546Sopenharmony_ci   }
596bf215546Sopenharmony_ci}
597