1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2016 Rob Clark <robclark@freedesktop.org>
3bf215546Sopenharmony_ci * Copyright © 2018 Google, Inc.
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci * Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22bf215546Sopenharmony_ci * SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci * Authors:
25bf215546Sopenharmony_ci *    Rob Clark <robclark@freedesktop.org>
26bf215546Sopenharmony_ci */
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#ifndef FD6_EMIT_H
29bf215546Sopenharmony_ci#define FD6_EMIT_H
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include "pipe/p_context.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "fd6_context.h"
34bf215546Sopenharmony_ci#include "fd6_program.h"
35bf215546Sopenharmony_ci#include "fdl/fd6_format_table.h"
36bf215546Sopenharmony_ci#include "freedreno_context.h"
37bf215546Sopenharmony_ci#include "ir3_gallium.h"
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_cistruct fd_ringbuffer;
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci/* To collect all the state objects to emit in a single CP_SET_DRAW_STATE
42bf215546Sopenharmony_ci * packet, the emit tracks a collection of however many state_group's that
43bf215546Sopenharmony_ci * need to be emit'd.
44bf215546Sopenharmony_ci */
45bf215546Sopenharmony_cienum fd6_state_id {
46bf215546Sopenharmony_ci   FD6_GROUP_PROG_CONFIG,
47bf215546Sopenharmony_ci   FD6_GROUP_PROG,
48bf215546Sopenharmony_ci   FD6_GROUP_PROG_BINNING,
49bf215546Sopenharmony_ci   FD6_GROUP_PROG_INTERP,
50bf215546Sopenharmony_ci   FD6_GROUP_PROG_FB_RAST,
51bf215546Sopenharmony_ci   FD6_GROUP_LRZ,
52bf215546Sopenharmony_ci   FD6_GROUP_LRZ_BINNING,
53bf215546Sopenharmony_ci   FD6_GROUP_VTXSTATE,
54bf215546Sopenharmony_ci   FD6_GROUP_VBO,
55bf215546Sopenharmony_ci   FD6_GROUP_CONST,
56bf215546Sopenharmony_ci   FD6_GROUP_DRIVER_PARAMS,
57bf215546Sopenharmony_ci   FD6_GROUP_PRIMITIVE_PARAMS,
58bf215546Sopenharmony_ci   FD6_GROUP_VS_TEX,
59bf215546Sopenharmony_ci   FD6_GROUP_HS_TEX,
60bf215546Sopenharmony_ci   FD6_GROUP_DS_TEX,
61bf215546Sopenharmony_ci   FD6_GROUP_GS_TEX,
62bf215546Sopenharmony_ci   FD6_GROUP_FS_TEX,
63bf215546Sopenharmony_ci   FD6_GROUP_RASTERIZER,
64bf215546Sopenharmony_ci   FD6_GROUP_ZSA,
65bf215546Sopenharmony_ci   FD6_GROUP_BLEND,
66bf215546Sopenharmony_ci   FD6_GROUP_SCISSOR,
67bf215546Sopenharmony_ci   FD6_GROUP_BLEND_COLOR,
68bf215546Sopenharmony_ci   FD6_GROUP_SO,
69bf215546Sopenharmony_ci   FD6_GROUP_IBO,
70bf215546Sopenharmony_ci   FD6_GROUP_NON_GROUP, /* placeholder group for state emit in IB2, keep last */
71bf215546Sopenharmony_ci};
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci#define ENABLE_ALL                                                             \
74bf215546Sopenharmony_ci   (CP_SET_DRAW_STATE__0_BINNING | CP_SET_DRAW_STATE__0_GMEM |                 \
75bf215546Sopenharmony_ci    CP_SET_DRAW_STATE__0_SYSMEM)
76bf215546Sopenharmony_ci#define ENABLE_DRAW (CP_SET_DRAW_STATE__0_GMEM | CP_SET_DRAW_STATE__0_SYSMEM)
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_cistruct fd6_state_group {
79bf215546Sopenharmony_ci   struct fd_ringbuffer *stateobj;
80bf215546Sopenharmony_ci   enum fd6_state_id group_id;
81bf215546Sopenharmony_ci   /* enable_mask controls which states the stateobj is evaluated in,
82bf215546Sopenharmony_ci    * b0 is binning pass b1 and/or b2 is draw pass
83bf215546Sopenharmony_ci    */
84bf215546Sopenharmony_ci   uint32_t enable_mask;
85bf215546Sopenharmony_ci};
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci/* grouped together emit-state for prog/vertex/state emit: */
88bf215546Sopenharmony_cistruct fd6_emit {
89bf215546Sopenharmony_ci   struct fd_context *ctx;
90bf215546Sopenharmony_ci   const struct fd_vertex_state *vtx;
91bf215546Sopenharmony_ci   const struct pipe_draw_info *info;
92bf215546Sopenharmony_ci	unsigned drawid_offset;
93bf215546Sopenharmony_ci   const struct pipe_draw_indirect_info *indirect;
94bf215546Sopenharmony_ci	const struct pipe_draw_start_count_bias *draw;
95bf215546Sopenharmony_ci   struct ir3_cache_key key;
96bf215546Sopenharmony_ci   enum fd_dirty_3d_state dirty;
97bf215546Sopenharmony_ci   uint32_t dirty_groups;
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci   uint32_t sprite_coord_enable; /* bitmask */
100bf215546Sopenharmony_ci   bool sprite_coord_mode;
101bf215546Sopenharmony_ci   bool rasterflat;
102bf215546Sopenharmony_ci   bool primitive_restart;
103bf215546Sopenharmony_ci   uint8_t patch_vertices;
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   /* cached to avoid repeated lookups: */
106bf215546Sopenharmony_ci   const struct fd6_program_state *prog;
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci   struct ir3_shader_variant *bs;
109bf215546Sopenharmony_ci   struct ir3_shader_variant *vs;
110bf215546Sopenharmony_ci   struct ir3_shader_variant *hs;
111bf215546Sopenharmony_ci   struct ir3_shader_variant *ds;
112bf215546Sopenharmony_ci   struct ir3_shader_variant *gs;
113bf215546Sopenharmony_ci   struct ir3_shader_variant *fs;
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci   unsigned streamout_mask;
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   struct fd6_state_group groups[32];
118bf215546Sopenharmony_ci   unsigned num_groups;
119bf215546Sopenharmony_ci};
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_cistatic inline const struct fd6_program_state *
122bf215546Sopenharmony_cifd6_emit_get_prog(struct fd6_emit *emit)
123bf215546Sopenharmony_ci{
124bf215546Sopenharmony_ci   if (!emit->prog) {
125bf215546Sopenharmony_ci      struct ir3_program_state *s = ir3_cache_lookup(
126bf215546Sopenharmony_ci         emit->ctx->shader_cache, &emit->key, &emit->ctx->debug);
127bf215546Sopenharmony_ci      emit->prog = fd6_program_state(s);
128bf215546Sopenharmony_ci   }
129bf215546Sopenharmony_ci   return emit->prog;
130bf215546Sopenharmony_ci}
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_cistatic inline void
133bf215546Sopenharmony_cifd6_emit_take_group(struct fd6_emit *emit, struct fd_ringbuffer *stateobj,
134bf215546Sopenharmony_ci                    enum fd6_state_id group_id, unsigned enable_mask)
135bf215546Sopenharmony_ci{
136bf215546Sopenharmony_ci   assert(emit->num_groups < ARRAY_SIZE(emit->groups));
137bf215546Sopenharmony_ci   struct fd6_state_group *g = &emit->groups[emit->num_groups++];
138bf215546Sopenharmony_ci   g->stateobj = stateobj;
139bf215546Sopenharmony_ci   g->group_id = group_id;
140bf215546Sopenharmony_ci   g->enable_mask = enable_mask;
141bf215546Sopenharmony_ci}
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_cistatic inline void
144bf215546Sopenharmony_cifd6_emit_add_group(struct fd6_emit *emit, struct fd_ringbuffer *stateobj,
145bf215546Sopenharmony_ci                   enum fd6_state_id group_id, unsigned enable_mask)
146bf215546Sopenharmony_ci{
147bf215546Sopenharmony_ci   fd6_emit_take_group(emit, fd_ringbuffer_ref(stateobj), group_id,
148bf215546Sopenharmony_ci                       enable_mask);
149bf215546Sopenharmony_ci}
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_cistatic inline unsigned
152bf215546Sopenharmony_cifd6_event_write(struct fd_batch *batch, struct fd_ringbuffer *ring,
153bf215546Sopenharmony_ci                enum vgt_event_type evt, bool timestamp)
154bf215546Sopenharmony_ci{
155bf215546Sopenharmony_ci   unsigned seqno = 0;
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   fd_reset_wfi(batch);
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   OUT_PKT7(ring, CP_EVENT_WRITE, timestamp ? 4 : 1);
160bf215546Sopenharmony_ci   OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(evt));
161bf215546Sopenharmony_ci   if (timestamp) {
162bf215546Sopenharmony_ci      struct fd6_context *fd6_ctx = fd6_context(batch->ctx);
163bf215546Sopenharmony_ci      seqno = ++fd6_ctx->seqno;
164bf215546Sopenharmony_ci      OUT_RELOC(ring, control_ptr(fd6_ctx, seqno)); /* ADDR_LO/HI */
165bf215546Sopenharmony_ci      OUT_RING(ring, seqno);
166bf215546Sopenharmony_ci   }
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   return seqno;
169bf215546Sopenharmony_ci}
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_cistatic inline void
172bf215546Sopenharmony_cifd6_cache_inv(struct fd_batch *batch, struct fd_ringbuffer *ring)
173bf215546Sopenharmony_ci{
174bf215546Sopenharmony_ci   fd6_event_write(batch, ring, PC_CCU_INVALIDATE_COLOR, false);
175bf215546Sopenharmony_ci   fd6_event_write(batch, ring, PC_CCU_INVALIDATE_DEPTH, false);
176bf215546Sopenharmony_ci   fd6_event_write(batch, ring, CACHE_INVALIDATE, false);
177bf215546Sopenharmony_ci}
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_cistatic inline void
180bf215546Sopenharmony_cifd6_cache_flush(struct fd_batch *batch, struct fd_ringbuffer *ring)
181bf215546Sopenharmony_ci{
182bf215546Sopenharmony_ci   struct fd6_context *fd6_ctx = fd6_context(batch->ctx);
183bf215546Sopenharmony_ci   unsigned seqno;
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci   seqno = fd6_event_write(batch, ring, RB_DONE_TS, true);
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci   OUT_PKT7(ring, CP_WAIT_REG_MEM, 6);
188bf215546Sopenharmony_ci   OUT_RING(ring, CP_WAIT_REG_MEM_0_FUNCTION(WRITE_EQ) |
189bf215546Sopenharmony_ci                     CP_WAIT_REG_MEM_0_POLL_MEMORY);
190bf215546Sopenharmony_ci   OUT_RELOC(ring, control_ptr(fd6_ctx, seqno));
191bf215546Sopenharmony_ci   OUT_RING(ring, CP_WAIT_REG_MEM_3_REF(seqno));
192bf215546Sopenharmony_ci   OUT_RING(ring, CP_WAIT_REG_MEM_4_MASK(~0));
193bf215546Sopenharmony_ci   OUT_RING(ring, CP_WAIT_REG_MEM_5_DELAY_LOOP_CYCLES(16));
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci   seqno = fd6_event_write(batch, ring, CACHE_FLUSH_TS, true);
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   OUT_PKT7(ring, CP_WAIT_MEM_GTE, 4);
198bf215546Sopenharmony_ci   OUT_RING(ring, CP_WAIT_MEM_GTE_0_RESERVED(0));
199bf215546Sopenharmony_ci   OUT_RELOC(ring, control_ptr(fd6_ctx, seqno));
200bf215546Sopenharmony_ci   OUT_RING(ring, CP_WAIT_MEM_GTE_3_REF(seqno));
201bf215546Sopenharmony_ci}
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_cistatic inline void
204bf215546Sopenharmony_cifd6_emit_blit(struct fd_batch *batch, struct fd_ringbuffer *ring)
205bf215546Sopenharmony_ci{
206bf215546Sopenharmony_ci   emit_marker6(ring, 7);
207bf215546Sopenharmony_ci   fd6_event_write(batch, ring, BLIT, false);
208bf215546Sopenharmony_ci   emit_marker6(ring, 7);
209bf215546Sopenharmony_ci}
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_cistatic inline void
212bf215546Sopenharmony_cifd6_emit_lrz_flush(struct fd_ringbuffer *ring)
213bf215546Sopenharmony_ci{
214bf215546Sopenharmony_ci   OUT_PKT7(ring, CP_EVENT_WRITE, 1);
215bf215546Sopenharmony_ci   OUT_RING(ring, LRZ_FLUSH);
216bf215546Sopenharmony_ci}
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_cistatic inline bool
219bf215546Sopenharmony_cifd6_geom_stage(gl_shader_stage type)
220bf215546Sopenharmony_ci{
221bf215546Sopenharmony_ci   switch (type) {
222bf215546Sopenharmony_ci   case MESA_SHADER_VERTEX:
223bf215546Sopenharmony_ci   case MESA_SHADER_TESS_CTRL:
224bf215546Sopenharmony_ci   case MESA_SHADER_TESS_EVAL:
225bf215546Sopenharmony_ci   case MESA_SHADER_GEOMETRY:
226bf215546Sopenharmony_ci      return true;
227bf215546Sopenharmony_ci   case MESA_SHADER_FRAGMENT:
228bf215546Sopenharmony_ci   case MESA_SHADER_COMPUTE:
229bf215546Sopenharmony_ci   case MESA_SHADER_KERNEL:
230bf215546Sopenharmony_ci      return false;
231bf215546Sopenharmony_ci   default:
232bf215546Sopenharmony_ci      unreachable("bad shader type");
233bf215546Sopenharmony_ci   }
234bf215546Sopenharmony_ci}
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_cistatic inline uint32_t
237bf215546Sopenharmony_cifd6_stage2opcode(gl_shader_stage type)
238bf215546Sopenharmony_ci{
239bf215546Sopenharmony_ci   return fd6_geom_stage(type) ? CP_LOAD_STATE6_GEOM : CP_LOAD_STATE6_FRAG;
240bf215546Sopenharmony_ci}
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_cistatic inline enum a6xx_state_block
243bf215546Sopenharmony_cifd6_stage2shadersb(gl_shader_stage type)
244bf215546Sopenharmony_ci{
245bf215546Sopenharmony_ci   switch (type) {
246bf215546Sopenharmony_ci   case MESA_SHADER_VERTEX:
247bf215546Sopenharmony_ci      return SB6_VS_SHADER;
248bf215546Sopenharmony_ci   case MESA_SHADER_TESS_CTRL:
249bf215546Sopenharmony_ci      return SB6_HS_SHADER;
250bf215546Sopenharmony_ci   case MESA_SHADER_TESS_EVAL:
251bf215546Sopenharmony_ci      return SB6_DS_SHADER;
252bf215546Sopenharmony_ci   case MESA_SHADER_GEOMETRY:
253bf215546Sopenharmony_ci      return SB6_GS_SHADER;
254bf215546Sopenharmony_ci   case MESA_SHADER_FRAGMENT:
255bf215546Sopenharmony_ci      return SB6_FS_SHADER;
256bf215546Sopenharmony_ci   case MESA_SHADER_COMPUTE:
257bf215546Sopenharmony_ci   case MESA_SHADER_KERNEL:
258bf215546Sopenharmony_ci      return SB6_CS_SHADER;
259bf215546Sopenharmony_ci   default:
260bf215546Sopenharmony_ci      unreachable("bad shader type");
261bf215546Sopenharmony_ci      return ~0;
262bf215546Sopenharmony_ci   }
263bf215546Sopenharmony_ci}
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_cistatic inline enum a6xx_tess_spacing
266bf215546Sopenharmony_cifd6_gl2spacing(enum gl_tess_spacing spacing)
267bf215546Sopenharmony_ci{
268bf215546Sopenharmony_ci   switch (spacing) {
269bf215546Sopenharmony_ci   case TESS_SPACING_EQUAL:
270bf215546Sopenharmony_ci      return TESS_EQUAL;
271bf215546Sopenharmony_ci   case TESS_SPACING_FRACTIONAL_ODD:
272bf215546Sopenharmony_ci      return TESS_FRACTIONAL_ODD;
273bf215546Sopenharmony_ci   case TESS_SPACING_FRACTIONAL_EVEN:
274bf215546Sopenharmony_ci      return TESS_FRACTIONAL_EVEN;
275bf215546Sopenharmony_ci   case TESS_SPACING_UNSPECIFIED:
276bf215546Sopenharmony_ci   default:
277bf215546Sopenharmony_ci      unreachable("spacing must be specified");
278bf215546Sopenharmony_ci   }
279bf215546Sopenharmony_ci}
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_cibool fd6_emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring,
282bf215546Sopenharmony_ci                       enum pipe_shader_type type,
283bf215546Sopenharmony_ci                       struct fd_texture_stateobj *tex, unsigned bcolor_offset,
284bf215546Sopenharmony_ci                       const struct ir3_shader_variant *v) assert_dt;
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_civoid fd6_emit_state(struct fd_ringbuffer *ring,
287bf215546Sopenharmony_ci                    struct fd6_emit *emit) assert_dt;
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_civoid fd6_emit_cs_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
290bf215546Sopenharmony_ci                       struct ir3_shader_variant *cp) assert_dt;
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_civoid fd6_emit_restore(struct fd_batch *batch, struct fd_ringbuffer *ring);
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_civoid fd6_emit_init_screen(struct pipe_screen *pscreen);
295bf215546Sopenharmony_civoid fd6_emit_init(struct pipe_context *pctx);
296bf215546Sopenharmony_ci
297bf215546Sopenharmony_cistatic inline void
298bf215546Sopenharmony_cifd6_emit_ib(struct fd_ringbuffer *ring, struct fd_ringbuffer *target)
299bf215546Sopenharmony_ci{
300bf215546Sopenharmony_ci   emit_marker6(ring, 6);
301bf215546Sopenharmony_ci   __OUT_IB5(ring, target);
302bf215546Sopenharmony_ci   emit_marker6(ring, 6);
303bf215546Sopenharmony_ci}
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci#define WRITE(reg, val)                                                        \
306bf215546Sopenharmony_ci   do {                                                                        \
307bf215546Sopenharmony_ci      OUT_PKT4(ring, reg, 1);                                                  \
308bf215546Sopenharmony_ci      OUT_RING(ring, val);                                                     \
309bf215546Sopenharmony_ci   } while (0)
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci#endif /* FD6_EMIT_H */
312