1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2019-2020 Collabora, Ltd.
3bf215546Sopenharmony_ci * © Copyright 2018 Alyssa Rosenzweig
4bf215546Sopenharmony_ci * Copyright © 2014-2017 Broadcom
5bf215546Sopenharmony_ci * Copyright (C) 2017 Intel Corporation
6bf215546Sopenharmony_ci *
7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
9bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
10bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
12bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
15bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
16bf215546Sopenharmony_ci * Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24bf215546Sopenharmony_ci * SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci */
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include <sys/poll.h>
29bf215546Sopenharmony_ci#include <errno.h>
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include "pan_bo.h"
32bf215546Sopenharmony_ci#include "pan_context.h"
33bf215546Sopenharmony_ci#include "pan_minmax_cache.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci#include "util/macros.h"
36bf215546Sopenharmony_ci#include "util/format/u_format.h"
37bf215546Sopenharmony_ci#include "util/u_inlines.h"
38bf215546Sopenharmony_ci#include "util/u_upload_mgr.h"
39bf215546Sopenharmony_ci#include "util/u_memory.h"
40bf215546Sopenharmony_ci#include "util/u_vbuf.h"
41bf215546Sopenharmony_ci#include "util/half_float.h"
42bf215546Sopenharmony_ci#include "util/u_helpers.h"
43bf215546Sopenharmony_ci#include "util/format/u_format.h"
44bf215546Sopenharmony_ci#include "util/u_prim.h"
45bf215546Sopenharmony_ci#include "util/u_prim_restart.h"
46bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h"
47bf215546Sopenharmony_ci#include "tgsi/tgsi_from_mesa.h"
48bf215546Sopenharmony_ci#include "nir/tgsi_to_nir.h"
49bf215546Sopenharmony_ci#include "util/u_math.h"
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci#include "pan_screen.h"
52bf215546Sopenharmony_ci#include "pan_util.h"
53bf215546Sopenharmony_ci#include "decode.h"
54bf215546Sopenharmony_ci#include "util/pan_lower_framebuffer.h"
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_cistatic void
57bf215546Sopenharmony_cipanfrost_clear(
58bf215546Sopenharmony_ci        struct pipe_context *pipe,
59bf215546Sopenharmony_ci        unsigned buffers,
60bf215546Sopenharmony_ci        const struct pipe_scissor_state *scissor_state,
61bf215546Sopenharmony_ci        const union pipe_color_union *color,
62bf215546Sopenharmony_ci        double depth, unsigned stencil)
63bf215546Sopenharmony_ci{
64bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
65bf215546Sopenharmony_ci        struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci        if (!panfrost_render_condition_check(ctx))
68bf215546Sopenharmony_ci                return;
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci        /* At the start of the batch, we can clear for free */
71bf215546Sopenharmony_ci        if (!batch->scoreboard.first_job) {
72bf215546Sopenharmony_ci                panfrost_batch_clear(batch, buffers, color, depth, stencil);
73bf215546Sopenharmony_ci                return;
74bf215546Sopenharmony_ci        }
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci        /* Once there is content, clear with a fullscreen quad */
77bf215546Sopenharmony_ci        panfrost_blitter_save(ctx, false /* render condition */);
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci        util_blitter_clear(ctx->blitter,
80bf215546Sopenharmony_ci                           ctx->pipe_framebuffer.width,
81bf215546Sopenharmony_ci                           ctx->pipe_framebuffer.height,
82bf215546Sopenharmony_ci                           util_framebuffer_get_num_layers(&ctx->pipe_framebuffer),
83bf215546Sopenharmony_ci                           buffers, color, depth, stencil,
84bf215546Sopenharmony_ci                           util_framebuffer_get_num_samples(&ctx->pipe_framebuffer) > 1);
85bf215546Sopenharmony_ci}
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_cibool
88bf215546Sopenharmony_cipanfrost_writes_point_size(struct panfrost_context *ctx)
89bf215546Sopenharmony_ci{
90bf215546Sopenharmony_ci        assert(ctx->shader[PIPE_SHADER_VERTEX]);
91bf215546Sopenharmony_ci        struct panfrost_shader_state *vs = panfrost_get_shader_state(ctx, PIPE_SHADER_VERTEX);
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci        return vs->info.vs.writes_point_size && ctx->active_prim == PIPE_PRIM_POINTS;
94bf215546Sopenharmony_ci}
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci/* The entire frame is in memory -- send it off to the kernel! */
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_civoid
99bf215546Sopenharmony_cipanfrost_flush(
100bf215546Sopenharmony_ci        struct pipe_context *pipe,
101bf215546Sopenharmony_ci        struct pipe_fence_handle **fence,
102bf215546Sopenharmony_ci        unsigned flags)
103bf215546Sopenharmony_ci{
104bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
105bf215546Sopenharmony_ci        struct panfrost_device *dev = pan_device(pipe->screen);
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci        /* Submit all pending jobs */
109bf215546Sopenharmony_ci        panfrost_flush_all_batches(ctx, NULL);
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci        if (fence) {
112bf215546Sopenharmony_ci                struct pipe_fence_handle *f = panfrost_fence_create(ctx);
113bf215546Sopenharmony_ci                pipe->screen->fence_reference(pipe->screen, fence, NULL);
114bf215546Sopenharmony_ci                *fence = f;
115bf215546Sopenharmony_ci        }
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci        if (dev->debug & PAN_DBG_TRACE)
118bf215546Sopenharmony_ci                pandecode_next_frame();
119bf215546Sopenharmony_ci}
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_cistatic void
122bf215546Sopenharmony_cipanfrost_texture_barrier(struct pipe_context *pipe, unsigned flags)
123bf215546Sopenharmony_ci{
124bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
125bf215546Sopenharmony_ci        panfrost_flush_all_batches(ctx, "Texture barrier");
126bf215546Sopenharmony_ci}
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_cistatic void
129bf215546Sopenharmony_cipanfrost_set_frontend_noop(struct pipe_context *pipe, bool enable)
130bf215546Sopenharmony_ci{
131bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
132bf215546Sopenharmony_ci        panfrost_flush_all_batches(ctx, "Frontend no-op change");
133bf215546Sopenharmony_ci        ctx->is_noop = enable;
134bf215546Sopenharmony_ci}
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_cistatic void
138bf215546Sopenharmony_cipanfrost_generic_cso_delete(struct pipe_context *pctx, void *hwcso)
139bf215546Sopenharmony_ci{
140bf215546Sopenharmony_ci        free(hwcso);
141bf215546Sopenharmony_ci}
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_cistatic void
144bf215546Sopenharmony_cipanfrost_bind_blend_state(struct pipe_context *pipe, void *cso)
145bf215546Sopenharmony_ci{
146bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
147bf215546Sopenharmony_ci        ctx->blend = cso;
148bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_BLEND;
149bf215546Sopenharmony_ci}
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_cistatic void
152bf215546Sopenharmony_cipanfrost_set_blend_color(struct pipe_context *pipe,
153bf215546Sopenharmony_ci                         const struct pipe_blend_color *blend_color)
154bf215546Sopenharmony_ci{
155bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
156bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_BLEND;
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci        if (blend_color)
159bf215546Sopenharmony_ci                ctx->blend_color = *blend_color;
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci/* Create a final blend given the context */
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_cimali_ptr
165bf215546Sopenharmony_cipanfrost_get_blend(struct panfrost_batch *batch, unsigned rti, struct panfrost_bo **bo, unsigned *shader_offset)
166bf215546Sopenharmony_ci{
167bf215546Sopenharmony_ci        struct panfrost_context *ctx = batch->ctx;
168bf215546Sopenharmony_ci        struct panfrost_device *dev = pan_device(ctx->base.screen);
169bf215546Sopenharmony_ci        struct panfrost_blend_state *blend = ctx->blend;
170bf215546Sopenharmony_ci        struct pan_blend_info info = blend->info[rti];
171bf215546Sopenharmony_ci        struct pipe_surface *surf = batch->key.cbufs[rti];
172bf215546Sopenharmony_ci        enum pipe_format fmt = surf->format;
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci        /* Use fixed-function if the equation permits, the format is blendable,
175bf215546Sopenharmony_ci         * and no more than one unique constant is accessed */
176bf215546Sopenharmony_ci        if (info.fixed_function && panfrost_blendable_formats_v7[fmt].internal &&
177bf215546Sopenharmony_ci                        pan_blend_is_homogenous_constant(info.constant_mask,
178bf215546Sopenharmony_ci                                ctx->blend_color.color)) {
179bf215546Sopenharmony_ci                return 0;
180bf215546Sopenharmony_ci        }
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci        /* Otherwise, we need to grab a shader */
183bf215546Sopenharmony_ci        struct pan_blend_state pan_blend = blend->pan;
184bf215546Sopenharmony_ci        unsigned nr_samples = surf->nr_samples ? : surf->texture->nr_samples;
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci        pan_blend.rts[rti].format = fmt;
187bf215546Sopenharmony_ci        pan_blend.rts[rti].nr_samples = nr_samples;
188bf215546Sopenharmony_ci        memcpy(pan_blend.constants, ctx->blend_color.color,
189bf215546Sopenharmony_ci               sizeof(pan_blend.constants));
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci        /* Upload the shader, sharing a BO */
192bf215546Sopenharmony_ci        if (!(*bo)) {
193bf215546Sopenharmony_ci                *bo = panfrost_batch_create_bo(batch, 4096, PAN_BO_EXECUTE,
194bf215546Sopenharmony_ci                                PIPE_SHADER_FRAGMENT, "Blend shader");
195bf215546Sopenharmony_ci        }
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci        struct panfrost_shader_state *ss = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT);
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci        /* Default for Midgard */
200bf215546Sopenharmony_ci        nir_alu_type col0_type = nir_type_float32;
201bf215546Sopenharmony_ci        nir_alu_type col1_type = nir_type_float32;
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci        /* Bifrost has per-output types, respect them */
204bf215546Sopenharmony_ci        if (dev->arch >= 6) {
205bf215546Sopenharmony_ci                col0_type = ss->info.bifrost.blend[rti].type;
206bf215546Sopenharmony_ci                col1_type = ss->info.bifrost.blend_src1_type;
207bf215546Sopenharmony_ci        }
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci        pthread_mutex_lock(&dev->blend_shaders.lock);
210bf215546Sopenharmony_ci        struct pan_blend_shader_variant *shader =
211bf215546Sopenharmony_ci                pan_screen(ctx->base.screen)->vtbl.get_blend_shader(dev,
212bf215546Sopenharmony_ci                                                                    &pan_blend,
213bf215546Sopenharmony_ci                                                                    col0_type,
214bf215546Sopenharmony_ci                                                                    col1_type,
215bf215546Sopenharmony_ci                                                                    rti);
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci        /* Size check and upload */
218bf215546Sopenharmony_ci        unsigned offset = *shader_offset;
219bf215546Sopenharmony_ci        assert((offset + shader->binary.size) < 4096);
220bf215546Sopenharmony_ci        memcpy((*bo)->ptr.cpu + offset, shader->binary.data, shader->binary.size);
221bf215546Sopenharmony_ci        *shader_offset += shader->binary.size;
222bf215546Sopenharmony_ci        pthread_mutex_unlock(&dev->blend_shaders.lock);
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci        return ((*bo)->ptr.gpu + offset) | shader->first_tag;
225bf215546Sopenharmony_ci}
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_cistatic void
228bf215546Sopenharmony_cipanfrost_bind_rasterizer_state(
229bf215546Sopenharmony_ci        struct pipe_context *pctx,
230bf215546Sopenharmony_ci        void *hwcso)
231bf215546Sopenharmony_ci{
232bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
233bf215546Sopenharmony_ci        ctx->rasterizer = hwcso;
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci        /* We can assume rasterizer is always dirty, the dependencies are
236bf215546Sopenharmony_ci         * too intricate to bother tracking in detail. However we could
237bf215546Sopenharmony_ci         * probably diff the renderers for viewport dirty tracking, that
238bf215546Sopenharmony_ci         * just cares about the scissor enable and the depth clips. */
239bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_SCISSOR | PAN_DIRTY_RASTERIZER;
240bf215546Sopenharmony_ci}
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_cistatic void
243bf215546Sopenharmony_cipanfrost_set_shader_images(
244bf215546Sopenharmony_ci        struct pipe_context *pctx,
245bf215546Sopenharmony_ci        enum pipe_shader_type shader,
246bf215546Sopenharmony_ci        unsigned start_slot, unsigned count, unsigned unbind_num_trailing_slots,
247bf215546Sopenharmony_ci        const struct pipe_image_view *iviews)
248bf215546Sopenharmony_ci{
249bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
250bf215546Sopenharmony_ci        ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_IMAGE;
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci        /* Unbind start_slot...start_slot+count */
253bf215546Sopenharmony_ci        if (!iviews) {
254bf215546Sopenharmony_ci                for (int i = start_slot; i < start_slot + count + unbind_num_trailing_slots; i++) {
255bf215546Sopenharmony_ci                        pipe_resource_reference(&ctx->images[shader][i].resource, NULL);
256bf215546Sopenharmony_ci                }
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci                ctx->image_mask[shader] &= ~(((1ull << count) - 1) << start_slot);
259bf215546Sopenharmony_ci                return;
260bf215546Sopenharmony_ci        }
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci        /* Bind start_slot...start_slot+count */
263bf215546Sopenharmony_ci        for (int i = 0; i < count; i++) {
264bf215546Sopenharmony_ci                const struct pipe_image_view *image = &iviews[i];
265bf215546Sopenharmony_ci                SET_BIT(ctx->image_mask[shader], 1 << (start_slot + i), image->resource);
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci                if (!image->resource) {
268bf215546Sopenharmony_ci                        util_copy_image_view(&ctx->images[shader][start_slot+i], NULL);
269bf215546Sopenharmony_ci                        continue;
270bf215546Sopenharmony_ci                }
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci                struct panfrost_resource *rsrc = pan_resource(image->resource);
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci                /* Images don't work with AFBC, since they require pixel-level granularity */
275bf215546Sopenharmony_ci                if (drm_is_afbc(rsrc->image.layout.modifier)) {
276bf215546Sopenharmony_ci                        pan_resource_modifier_convert(ctx, rsrc,
277bf215546Sopenharmony_ci                                        DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED,
278bf215546Sopenharmony_ci                                        "Shader image");
279bf215546Sopenharmony_ci                }
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci                util_copy_image_view(&ctx->images[shader][start_slot+i], image);
282bf215546Sopenharmony_ci        }
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci        /* Unbind start_slot+count...start_slot+count+unbind_num_trailing_slots */
285bf215546Sopenharmony_ci        for (int i = 0; i < unbind_num_trailing_slots; i++) {
286bf215546Sopenharmony_ci                SET_BIT(ctx->image_mask[shader], 1 << (start_slot + count + i), NULL);
287bf215546Sopenharmony_ci                util_copy_image_view(&ctx->images[shader][start_slot+count+i], NULL);
288bf215546Sopenharmony_ci        }
289bf215546Sopenharmony_ci}
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_cistatic void
292bf215546Sopenharmony_cipanfrost_bind_vertex_elements_state(
293bf215546Sopenharmony_ci        struct pipe_context *pctx,
294bf215546Sopenharmony_ci        void *hwcso)
295bf215546Sopenharmony_ci{
296bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
297bf215546Sopenharmony_ci        ctx->vertex = hwcso;
298bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_VERTEX;
299bf215546Sopenharmony_ci}
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_cistatic void *
302bf215546Sopenharmony_cipanfrost_create_shader_state(
303bf215546Sopenharmony_ci        struct pipe_context *pctx,
304bf215546Sopenharmony_ci        const struct pipe_shader_state *cso)
305bf215546Sopenharmony_ci{
306bf215546Sopenharmony_ci        struct panfrost_shader_variants *so = CALLOC_STRUCT(panfrost_shader_variants);
307bf215546Sopenharmony_ci        struct panfrost_device *dev = pan_device(pctx->screen);
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci        simple_mtx_init(&so->lock, mtx_plain);
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci        so->stream_output = cso->stream_output;
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci        if (cso->type == PIPE_SHADER_IR_TGSI)
314bf215546Sopenharmony_ci                so->nir = tgsi_to_nir(cso->tokens, pctx->screen, false);
315bf215546Sopenharmony_ci        else
316bf215546Sopenharmony_ci                so->nir = cso->ir.nir;
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci        /* Fix linkage early */
319bf215546Sopenharmony_ci        if (so->nir->info.stage == MESA_SHADER_VERTEX) {
320bf215546Sopenharmony_ci                so->fixed_varying_mask =
321bf215546Sopenharmony_ci                        (so->nir->info.outputs_written & BITFIELD_MASK(VARYING_SLOT_VAR0)) &
322bf215546Sopenharmony_ci                        ~VARYING_BIT_POS & ~VARYING_BIT_PSIZ;
323bf215546Sopenharmony_ci        }
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci        /* Precompile for shader-db if we need to */
326bf215546Sopenharmony_ci        if (unlikely(dev->debug & PAN_DBG_PRECOMPILE)) {
327bf215546Sopenharmony_ci                struct panfrost_context *ctx = pan_context(pctx);
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci                struct panfrost_shader_state state = { 0 };
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci                panfrost_shader_compile(pctx->screen,
332bf215546Sopenharmony_ci                                        &ctx->shaders, &ctx->descs,
333bf215546Sopenharmony_ci                                        so->nir, &state);
334bf215546Sopenharmony_ci        }
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci        return so;
337bf215546Sopenharmony_ci}
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_cistatic void
340bf215546Sopenharmony_cipanfrost_delete_shader_state(
341bf215546Sopenharmony_ci        struct pipe_context *pctx,
342bf215546Sopenharmony_ci        void *so)
343bf215546Sopenharmony_ci{
344bf215546Sopenharmony_ci        struct panfrost_shader_variants *cso = (struct panfrost_shader_variants *) so;
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci        ralloc_free(cso->nir);
347bf215546Sopenharmony_ci
348bf215546Sopenharmony_ci        for (unsigned i = 0; i < cso->variant_count; ++i) {
349bf215546Sopenharmony_ci                struct panfrost_shader_state *shader_state = &cso->variants[i];
350bf215546Sopenharmony_ci                panfrost_bo_unreference(shader_state->bin.bo);
351bf215546Sopenharmony_ci                panfrost_bo_unreference(shader_state->state.bo);
352bf215546Sopenharmony_ci                panfrost_bo_unreference(shader_state->linkage.bo);
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci                if (shader_state->xfb) {
355bf215546Sopenharmony_ci                        panfrost_bo_unreference(shader_state->xfb->bin.bo);
356bf215546Sopenharmony_ci                        panfrost_bo_unreference(shader_state->xfb->state.bo);
357bf215546Sopenharmony_ci                        panfrost_bo_unreference(shader_state->xfb->linkage.bo);
358bf215546Sopenharmony_ci                        free(shader_state->xfb);
359bf215546Sopenharmony_ci                }
360bf215546Sopenharmony_ci        }
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci        simple_mtx_destroy(&cso->lock);
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci        free(cso->variants);
365bf215546Sopenharmony_ci        free(so);
366bf215546Sopenharmony_ci}
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_cistatic void
369bf215546Sopenharmony_cipanfrost_bind_sampler_states(
370bf215546Sopenharmony_ci        struct pipe_context *pctx,
371bf215546Sopenharmony_ci        enum pipe_shader_type shader,
372bf215546Sopenharmony_ci        unsigned start_slot, unsigned num_sampler,
373bf215546Sopenharmony_ci        void **sampler)
374bf215546Sopenharmony_ci{
375bf215546Sopenharmony_ci        assert(start_slot == 0);
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
378bf215546Sopenharmony_ci        ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_SAMPLER;
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci        ctx->sampler_count[shader] = sampler ? num_sampler : 0;
381bf215546Sopenharmony_ci        if (sampler)
382bf215546Sopenharmony_ci                memcpy(ctx->samplers[shader], sampler, num_sampler * sizeof (void *));
383bf215546Sopenharmony_ci}
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_cistatic void
386bf215546Sopenharmony_cipanfrost_build_key(struct panfrost_context *ctx,
387bf215546Sopenharmony_ci                   struct panfrost_shader_key *key,
388bf215546Sopenharmony_ci                   nir_shader *nir)
389bf215546Sopenharmony_ci{
390bf215546Sopenharmony_ci        /* We don't currently have vertex shader variants */
391bf215546Sopenharmony_ci        if (nir->info.stage != MESA_SHADER_FRAGMENT)
392bf215546Sopenharmony_ci               return;
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci        struct panfrost_device *dev = pan_device(ctx->base.screen);
395bf215546Sopenharmony_ci        struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer;
396bf215546Sopenharmony_ci        struct pipe_rasterizer_state *rast = (void *) ctx->rasterizer;
397bf215546Sopenharmony_ci        struct panfrost_shader_variants *vs = ctx->shader[MESA_SHADER_VERTEX];
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci        key->fs.nr_cbufs = fb->nr_cbufs;
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci        /* Point sprite lowering needed on Bifrost and newer */
402bf215546Sopenharmony_ci        if (dev->arch >= 6 && rast && ctx->active_prim == PIPE_PRIM_POINTS) {
403bf215546Sopenharmony_ci                key->fs.sprite_coord_enable = rast->sprite_coord_enable;
404bf215546Sopenharmony_ci        }
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ci        /* User clip plane lowering needed everywhere */
407bf215546Sopenharmony_ci        if (rast) {
408bf215546Sopenharmony_ci                key->fs.clip_plane_enable = rast->clip_plane_enable;
409bf215546Sopenharmony_ci        }
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_ci        if (dev->arch <= 5) {
412bf215546Sopenharmony_ci                u_foreach_bit(i, (nir->info.outputs_read >> FRAG_RESULT_DATA0)) {
413bf215546Sopenharmony_ci                        enum pipe_format fmt = PIPE_FORMAT_R8G8B8A8_UNORM;
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci                        if ((fb->nr_cbufs > i) && fb->cbufs[i])
416bf215546Sopenharmony_ci                                fmt = fb->cbufs[i]->format;
417bf215546Sopenharmony_ci
418bf215546Sopenharmony_ci                        if (panfrost_blendable_formats_v6[fmt].internal)
419bf215546Sopenharmony_ci                                fmt = PIPE_FORMAT_NONE;
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci                        key->fs.rt_formats[i] = fmt;
422bf215546Sopenharmony_ci                }
423bf215546Sopenharmony_ci        }
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_ci        /* Funny desktop GL varying lowering on Valhall */
426bf215546Sopenharmony_ci        if (dev->arch >= 9) {
427bf215546Sopenharmony_ci                assert(vs != NULL && "too early");
428bf215546Sopenharmony_ci                key->fixed_varying_mask = vs->fixed_varying_mask;
429bf215546Sopenharmony_ci        }
430bf215546Sopenharmony_ci}
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci/**
433bf215546Sopenharmony_ci * Fix an uncompiled shader's stream output info, and produce a bitmask
434bf215546Sopenharmony_ci * of which VARYING_SLOT_* are captured for stream output.
435bf215546Sopenharmony_ci *
436bf215546Sopenharmony_ci * Core Gallium stores output->register_index as a "slot" number, where
437bf215546Sopenharmony_ci * slots are assigned consecutively to all outputs in info->outputs_written.
438bf215546Sopenharmony_ci * This naive packing of outputs doesn't work for us - we too have slots,
439bf215546Sopenharmony_ci * but the layout is defined by the VUE map, which we won't have until we
440bf215546Sopenharmony_ci * compile a specific shader variant.  So, we remap these and simply store
441bf215546Sopenharmony_ci * VARYING_SLOT_* in our copy's output->register_index fields.
442bf215546Sopenharmony_ci *
443bf215546Sopenharmony_ci * We then produce a bitmask of outputs which are used for SO.
444bf215546Sopenharmony_ci *
445bf215546Sopenharmony_ci * Implementation from iris.
446bf215546Sopenharmony_ci */
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_cistatic uint64_t
449bf215546Sopenharmony_ciupdate_so_info(struct pipe_stream_output_info *so_info,
450bf215546Sopenharmony_ci               uint64_t outputs_written)
451bf215546Sopenharmony_ci{
452bf215546Sopenharmony_ci	uint64_t so_outputs = 0;
453bf215546Sopenharmony_ci	uint8_t reverse_map[64] = {0};
454bf215546Sopenharmony_ci	unsigned slot = 0;
455bf215546Sopenharmony_ci
456bf215546Sopenharmony_ci	while (outputs_written)
457bf215546Sopenharmony_ci		reverse_map[slot++] = u_bit_scan64(&outputs_written);
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci	for (unsigned i = 0; i < so_info->num_outputs; i++) {
460bf215546Sopenharmony_ci		struct pipe_stream_output *output = &so_info->output[i];
461bf215546Sopenharmony_ci
462bf215546Sopenharmony_ci		/* Map Gallium's condensed "slots" back to real VARYING_SLOT_* enums */
463bf215546Sopenharmony_ci		output->register_index = reverse_map[output->register_index];
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci		so_outputs |= 1ull << output->register_index;
466bf215546Sopenharmony_ci	}
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci	return so_outputs;
469bf215546Sopenharmony_ci}
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_cistatic unsigned
472bf215546Sopenharmony_cipanfrost_new_variant_locked(
473bf215546Sopenharmony_ci        struct panfrost_context *ctx,
474bf215546Sopenharmony_ci        struct panfrost_shader_variants *variants,
475bf215546Sopenharmony_ci        struct panfrost_shader_key *key)
476bf215546Sopenharmony_ci{
477bf215546Sopenharmony_ci        unsigned variant = variants->variant_count++;
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci        if (variants->variant_count > variants->variant_space) {
480bf215546Sopenharmony_ci                unsigned old_space = variants->variant_space;
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci                variants->variant_space *= 2;
483bf215546Sopenharmony_ci                if (variants->variant_space == 0)
484bf215546Sopenharmony_ci                        variants->variant_space = 1;
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci                /* Arbitrary limit to stop runaway programs from
487bf215546Sopenharmony_ci                 * creating an unbounded number of shader variants. */
488bf215546Sopenharmony_ci                assert(variants->variant_space < 1024);
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_ci                unsigned msize = sizeof(struct panfrost_shader_state);
491bf215546Sopenharmony_ci                variants->variants = realloc(variants->variants,
492bf215546Sopenharmony_ci                                             variants->variant_space * msize);
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_ci                memset(&variants->variants[old_space], 0,
495bf215546Sopenharmony_ci                       (variants->variant_space - old_space) * msize);
496bf215546Sopenharmony_ci        }
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci        variants->variants[variant].key = *key;
499bf215546Sopenharmony_ci
500bf215546Sopenharmony_ci        struct panfrost_shader_state *shader_state = &variants->variants[variant];
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci        /* We finally have a variant, so compile it */
503bf215546Sopenharmony_ci        panfrost_shader_compile(ctx->base.screen,
504bf215546Sopenharmony_ci                                &ctx->shaders, &ctx->descs,
505bf215546Sopenharmony_ci                                variants->nir, shader_state);
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci        /* Fixup the stream out information */
508bf215546Sopenharmony_ci        shader_state->stream_output = variants->stream_output;
509bf215546Sopenharmony_ci        shader_state->so_mask =
510bf215546Sopenharmony_ci                update_so_info(&shader_state->stream_output,
511bf215546Sopenharmony_ci                               shader_state->info.outputs_written);
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_ci        shader_state->earlyzs = pan_earlyzs_analyze(&shader_state->info);
514bf215546Sopenharmony_ci
515bf215546Sopenharmony_ci        return variant;
516bf215546Sopenharmony_ci}
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_cistatic void
519bf215546Sopenharmony_cipanfrost_bind_shader_state(
520bf215546Sopenharmony_ci        struct pipe_context *pctx,
521bf215546Sopenharmony_ci        void *hwcso,
522bf215546Sopenharmony_ci        enum pipe_shader_type type)
523bf215546Sopenharmony_ci{
524bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
525bf215546Sopenharmony_ci        ctx->shader[type] = hwcso;
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_TLS_SIZE;
528bf215546Sopenharmony_ci        ctx->dirty_shader[type] |= PAN_DIRTY_STAGE_SHADER;
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_ci        if (hwcso)
531bf215546Sopenharmony_ci                panfrost_update_shader_variant(ctx, type);
532bf215546Sopenharmony_ci}
533bf215546Sopenharmony_ci
534bf215546Sopenharmony_civoid
535bf215546Sopenharmony_cipanfrost_update_shader_variant(struct panfrost_context *ctx,
536bf215546Sopenharmony_ci                               enum pipe_shader_type type)
537bf215546Sopenharmony_ci{
538bf215546Sopenharmony_ci        /* No shader variants for compute */
539bf215546Sopenharmony_ci        if (type == PIPE_SHADER_COMPUTE)
540bf215546Sopenharmony_ci                return;
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci        /* We need linking information, defer this */
543bf215546Sopenharmony_ci        if (type == PIPE_SHADER_FRAGMENT && !ctx->shader[PIPE_SHADER_VERTEX])
544bf215546Sopenharmony_ci                return;
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci        /* Also defer, happens with GALLIUM_HUD */
547bf215546Sopenharmony_ci        if (!ctx->shader[type])
548bf215546Sopenharmony_ci                return;
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci        /* Match the appropriate variant */
551bf215546Sopenharmony_ci        signed variant = -1;
552bf215546Sopenharmony_ci        struct panfrost_shader_variants *variants = ctx->shader[type];
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci        simple_mtx_lock(&variants->lock);
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci        struct panfrost_shader_key key = {
557bf215546Sopenharmony_ci                .fixed_varying_mask = variants->fixed_varying_mask
558bf215546Sopenharmony_ci        };
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_ci        panfrost_build_key(ctx, &key, variants->nir);
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_ci        for (unsigned i = 0; i < variants->variant_count; ++i) {
563bf215546Sopenharmony_ci                if (memcmp(&key, &variants->variants[i].key, sizeof(key)) == 0) {
564bf215546Sopenharmony_ci                        variant = i;
565bf215546Sopenharmony_ci                        break;
566bf215546Sopenharmony_ci                }
567bf215546Sopenharmony_ci        }
568bf215546Sopenharmony_ci
569bf215546Sopenharmony_ci        if (variant == -1)
570bf215546Sopenharmony_ci                variant = panfrost_new_variant_locked(ctx, variants, &key);
571bf215546Sopenharmony_ci
572bf215546Sopenharmony_ci        variants->active_variant = variant;
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci        /* TODO: it would be more efficient to release the lock before
575bf215546Sopenharmony_ci         * compiling instead of after, but that can race if thread A compiles a
576bf215546Sopenharmony_ci         * variant while thread B searches for that same variant */
577bf215546Sopenharmony_ci        simple_mtx_unlock(&variants->lock);
578bf215546Sopenharmony_ci}
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_cistatic void
581bf215546Sopenharmony_cipanfrost_bind_vs_state(struct pipe_context *pctx, void *hwcso)
582bf215546Sopenharmony_ci{
583bf215546Sopenharmony_ci        panfrost_bind_shader_state(pctx, hwcso, PIPE_SHADER_VERTEX);
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci        /* Fragment shaders are linked with vertex shaders */
586bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
587bf215546Sopenharmony_ci        panfrost_update_shader_variant(ctx, PIPE_SHADER_FRAGMENT);
588bf215546Sopenharmony_ci}
589bf215546Sopenharmony_ci
590bf215546Sopenharmony_cistatic void
591bf215546Sopenharmony_cipanfrost_bind_fs_state(struct pipe_context *pctx, void *hwcso)
592bf215546Sopenharmony_ci{
593bf215546Sopenharmony_ci        panfrost_bind_shader_state(pctx, hwcso, PIPE_SHADER_FRAGMENT);
594bf215546Sopenharmony_ci}
595bf215546Sopenharmony_ci
596bf215546Sopenharmony_cistatic void
597bf215546Sopenharmony_cipanfrost_set_vertex_buffers(
598bf215546Sopenharmony_ci        struct pipe_context *pctx,
599bf215546Sopenharmony_ci        unsigned start_slot,
600bf215546Sopenharmony_ci        unsigned num_buffers,
601bf215546Sopenharmony_ci        unsigned unbind_num_trailing_slots,
602bf215546Sopenharmony_ci        bool take_ownership,
603bf215546Sopenharmony_ci        const struct pipe_vertex_buffer *buffers)
604bf215546Sopenharmony_ci{
605bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
606bf215546Sopenharmony_ci
607bf215546Sopenharmony_ci        util_set_vertex_buffers_mask(ctx->vertex_buffers, &ctx->vb_mask, buffers,
608bf215546Sopenharmony_ci                                     start_slot, num_buffers, unbind_num_trailing_slots,
609bf215546Sopenharmony_ci                                     take_ownership);
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_VERTEX;
612bf215546Sopenharmony_ci}
613bf215546Sopenharmony_ci
614bf215546Sopenharmony_cistatic void
615bf215546Sopenharmony_cipanfrost_set_constant_buffer(
616bf215546Sopenharmony_ci        struct pipe_context *pctx,
617bf215546Sopenharmony_ci        enum pipe_shader_type shader, uint index, bool take_ownership,
618bf215546Sopenharmony_ci        const struct pipe_constant_buffer *buf)
619bf215546Sopenharmony_ci{
620bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
621bf215546Sopenharmony_ci        struct panfrost_constant_buffer *pbuf = &ctx->constant_buffer[shader];
622bf215546Sopenharmony_ci
623bf215546Sopenharmony_ci        util_copy_constant_buffer(&pbuf->cb[index], buf, take_ownership);
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci        unsigned mask = (1 << index);
626bf215546Sopenharmony_ci
627bf215546Sopenharmony_ci        if (unlikely(!buf)) {
628bf215546Sopenharmony_ci                pbuf->enabled_mask &= ~mask;
629bf215546Sopenharmony_ci                return;
630bf215546Sopenharmony_ci        }
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_ci        pbuf->enabled_mask |= mask;
633bf215546Sopenharmony_ci        ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_CONST;
634bf215546Sopenharmony_ci}
635bf215546Sopenharmony_ci
636bf215546Sopenharmony_cistatic void
637bf215546Sopenharmony_cipanfrost_set_stencil_ref(
638bf215546Sopenharmony_ci        struct pipe_context *pctx,
639bf215546Sopenharmony_ci        const struct pipe_stencil_ref ref)
640bf215546Sopenharmony_ci{
641bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
642bf215546Sopenharmony_ci        ctx->stencil_ref = ref;
643bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_ZS;
644bf215546Sopenharmony_ci}
645bf215546Sopenharmony_ci
646bf215546Sopenharmony_cistatic void
647bf215546Sopenharmony_cipanfrost_set_sampler_views(
648bf215546Sopenharmony_ci        struct pipe_context *pctx,
649bf215546Sopenharmony_ci        enum pipe_shader_type shader,
650bf215546Sopenharmony_ci        unsigned start_slot, unsigned num_views,
651bf215546Sopenharmony_ci        unsigned unbind_num_trailing_slots,
652bf215546Sopenharmony_ci        bool take_ownership,
653bf215546Sopenharmony_ci        struct pipe_sampler_view **views)
654bf215546Sopenharmony_ci{
655bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
656bf215546Sopenharmony_ci        ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_TEXTURE;
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_ci        unsigned new_nr = 0;
659bf215546Sopenharmony_ci        unsigned i;
660bf215546Sopenharmony_ci
661bf215546Sopenharmony_ci        for (i = 0; i < num_views; ++i) {
662bf215546Sopenharmony_ci                struct pipe_sampler_view *view = views ? views[i] : NULL;
663bf215546Sopenharmony_ci                unsigned p = i + start_slot;
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci                if (view)
666bf215546Sopenharmony_ci                        new_nr = p + 1;
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_ci                if (take_ownership) {
669bf215546Sopenharmony_ci                        pipe_sampler_view_reference((struct pipe_sampler_view **)&ctx->sampler_views[shader][p],
670bf215546Sopenharmony_ci                                                    NULL);
671bf215546Sopenharmony_ci                        ctx->sampler_views[shader][i] = (struct panfrost_sampler_view *)view;
672bf215546Sopenharmony_ci                } else {
673bf215546Sopenharmony_ci                        pipe_sampler_view_reference((struct pipe_sampler_view **)&ctx->sampler_views[shader][p],
674bf215546Sopenharmony_ci                                                    view);
675bf215546Sopenharmony_ci                }
676bf215546Sopenharmony_ci        }
677bf215546Sopenharmony_ci
678bf215546Sopenharmony_ci        for (; i < num_views + unbind_num_trailing_slots; i++) {
679bf215546Sopenharmony_ci                unsigned p = i + start_slot;
680bf215546Sopenharmony_ci		pipe_sampler_view_reference((struct pipe_sampler_view **)&ctx->sampler_views[shader][p],
681bf215546Sopenharmony_ci		                            NULL);
682bf215546Sopenharmony_ci        }
683bf215546Sopenharmony_ci
684bf215546Sopenharmony_ci        /* If the sampler view count is higher than the greatest sampler view
685bf215546Sopenharmony_ci         * we touch, it can't change */
686bf215546Sopenharmony_ci        if (ctx->sampler_view_count[shader] > start_slot + num_views + unbind_num_trailing_slots)
687bf215546Sopenharmony_ci                return;
688bf215546Sopenharmony_ci
689bf215546Sopenharmony_ci        /* If we haven't set any sampler views here, search lower numbers for
690bf215546Sopenharmony_ci         * set sampler views */
691bf215546Sopenharmony_ci        if (new_nr == 0) {
692bf215546Sopenharmony_ci                for (i = 0; i < start_slot; ++i) {
693bf215546Sopenharmony_ci                        if (ctx->sampler_views[shader][i])
694bf215546Sopenharmony_ci                                new_nr = i + 1;
695bf215546Sopenharmony_ci                }
696bf215546Sopenharmony_ci        }
697bf215546Sopenharmony_ci
698bf215546Sopenharmony_ci        ctx->sampler_view_count[shader] = new_nr;
699bf215546Sopenharmony_ci}
700bf215546Sopenharmony_ci
701bf215546Sopenharmony_cistatic void
702bf215546Sopenharmony_cipanfrost_set_shader_buffers(
703bf215546Sopenharmony_ci        struct pipe_context *pctx,
704bf215546Sopenharmony_ci        enum pipe_shader_type shader,
705bf215546Sopenharmony_ci        unsigned start, unsigned count,
706bf215546Sopenharmony_ci        const struct pipe_shader_buffer *buffers,
707bf215546Sopenharmony_ci        unsigned writable_bitmask)
708bf215546Sopenharmony_ci{
709bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
710bf215546Sopenharmony_ci
711bf215546Sopenharmony_ci        util_set_shader_buffers_mask(ctx->ssbo[shader], &ctx->ssbo_mask[shader],
712bf215546Sopenharmony_ci                        buffers, start, count);
713bf215546Sopenharmony_ci
714bf215546Sopenharmony_ci        ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_SSBO;
715bf215546Sopenharmony_ci}
716bf215546Sopenharmony_ci
717bf215546Sopenharmony_cistatic void
718bf215546Sopenharmony_cipanfrost_set_framebuffer_state(struct pipe_context *pctx,
719bf215546Sopenharmony_ci                               const struct pipe_framebuffer_state *fb)
720bf215546Sopenharmony_ci{
721bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
722bf215546Sopenharmony_ci
723bf215546Sopenharmony_ci        util_copy_framebuffer_state(&ctx->pipe_framebuffer, fb);
724bf215546Sopenharmony_ci        ctx->batch = NULL;
725bf215546Sopenharmony_ci
726bf215546Sopenharmony_ci        /* Hot draw call path needs the mask of active render targets */
727bf215546Sopenharmony_ci        ctx->fb_rt_mask = 0;
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_ci        for (unsigned i = 0; i < ctx->pipe_framebuffer.nr_cbufs; ++i) {
730bf215546Sopenharmony_ci                if (ctx->pipe_framebuffer.cbufs[i])
731bf215546Sopenharmony_ci                        ctx->fb_rt_mask |= BITFIELD_BIT(i);
732bf215546Sopenharmony_ci        }
733bf215546Sopenharmony_ci}
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_cistatic void
736bf215546Sopenharmony_cipanfrost_bind_depth_stencil_state(struct pipe_context *pipe,
737bf215546Sopenharmony_ci                                  void *cso)
738bf215546Sopenharmony_ci{
739bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
740bf215546Sopenharmony_ci        ctx->depth_stencil = cso;
741bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_ZS;
742bf215546Sopenharmony_ci}
743bf215546Sopenharmony_ci
744bf215546Sopenharmony_cistatic void
745bf215546Sopenharmony_cipanfrost_set_sample_mask(struct pipe_context *pipe,
746bf215546Sopenharmony_ci                         unsigned sample_mask)
747bf215546Sopenharmony_ci{
748bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
749bf215546Sopenharmony_ci        ctx->sample_mask = sample_mask;
750bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_MSAA;
751bf215546Sopenharmony_ci}
752bf215546Sopenharmony_ci
753bf215546Sopenharmony_cistatic void
754bf215546Sopenharmony_cipanfrost_set_min_samples(struct pipe_context *pipe,
755bf215546Sopenharmony_ci                         unsigned min_samples)
756bf215546Sopenharmony_ci{
757bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
758bf215546Sopenharmony_ci        ctx->min_samples = min_samples;
759bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_MSAA;
760bf215546Sopenharmony_ci}
761bf215546Sopenharmony_ci
762bf215546Sopenharmony_cistatic void
763bf215546Sopenharmony_cipanfrost_set_clip_state(struct pipe_context *pipe,
764bf215546Sopenharmony_ci                        const struct pipe_clip_state *clip)
765bf215546Sopenharmony_ci{
766bf215546Sopenharmony_ci        //struct panfrost_context *panfrost = pan_context(pipe);
767bf215546Sopenharmony_ci}
768bf215546Sopenharmony_ci
769bf215546Sopenharmony_cistatic void
770bf215546Sopenharmony_cipanfrost_set_viewport_states(struct pipe_context *pipe,
771bf215546Sopenharmony_ci                             unsigned start_slot,
772bf215546Sopenharmony_ci                             unsigned num_viewports,
773bf215546Sopenharmony_ci                             const struct pipe_viewport_state *viewports)
774bf215546Sopenharmony_ci{
775bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
776bf215546Sopenharmony_ci
777bf215546Sopenharmony_ci        assert(start_slot == 0);
778bf215546Sopenharmony_ci        assert(num_viewports == 1);
779bf215546Sopenharmony_ci
780bf215546Sopenharmony_ci        ctx->pipe_viewport = *viewports;
781bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_VIEWPORT;
782bf215546Sopenharmony_ci}
783bf215546Sopenharmony_ci
784bf215546Sopenharmony_cistatic void
785bf215546Sopenharmony_cipanfrost_set_scissor_states(struct pipe_context *pipe,
786bf215546Sopenharmony_ci                            unsigned start_slot,
787bf215546Sopenharmony_ci                            unsigned num_scissors,
788bf215546Sopenharmony_ci                            const struct pipe_scissor_state *scissors)
789bf215546Sopenharmony_ci{
790bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
791bf215546Sopenharmony_ci
792bf215546Sopenharmony_ci        assert(start_slot == 0);
793bf215546Sopenharmony_ci        assert(num_scissors == 1);
794bf215546Sopenharmony_ci
795bf215546Sopenharmony_ci        ctx->scissor = *scissors;
796bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_SCISSOR;
797bf215546Sopenharmony_ci}
798bf215546Sopenharmony_ci
799bf215546Sopenharmony_cistatic void
800bf215546Sopenharmony_cipanfrost_set_polygon_stipple(struct pipe_context *pipe,
801bf215546Sopenharmony_ci                             const struct pipe_poly_stipple *stipple)
802bf215546Sopenharmony_ci{
803bf215546Sopenharmony_ci        //struct panfrost_context *panfrost = pan_context(pipe);
804bf215546Sopenharmony_ci}
805bf215546Sopenharmony_ci
806bf215546Sopenharmony_cistatic void
807bf215546Sopenharmony_cipanfrost_set_active_query_state(struct pipe_context *pipe,
808bf215546Sopenharmony_ci                                bool enable)
809bf215546Sopenharmony_ci{
810bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
811bf215546Sopenharmony_ci        ctx->active_queries = enable;
812bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_OQ;
813bf215546Sopenharmony_ci}
814bf215546Sopenharmony_ci
815bf215546Sopenharmony_cistatic void
816bf215546Sopenharmony_cipanfrost_render_condition(struct pipe_context *pipe,
817bf215546Sopenharmony_ci                          struct pipe_query *query,
818bf215546Sopenharmony_ci                          bool condition,
819bf215546Sopenharmony_ci                          enum pipe_render_cond_flag mode)
820bf215546Sopenharmony_ci{
821bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
822bf215546Sopenharmony_ci
823bf215546Sopenharmony_ci        ctx->cond_query = (struct panfrost_query *)query;
824bf215546Sopenharmony_ci        ctx->cond_cond = condition;
825bf215546Sopenharmony_ci        ctx->cond_mode = mode;
826bf215546Sopenharmony_ci}
827bf215546Sopenharmony_ci
828bf215546Sopenharmony_cistatic void
829bf215546Sopenharmony_cipanfrost_destroy(struct pipe_context *pipe)
830bf215546Sopenharmony_ci{
831bf215546Sopenharmony_ci        struct panfrost_context *panfrost = pan_context(pipe);
832bf215546Sopenharmony_ci
833bf215546Sopenharmony_ci        _mesa_hash_table_destroy(panfrost->writers, NULL);
834bf215546Sopenharmony_ci
835bf215546Sopenharmony_ci        if (panfrost->blitter)
836bf215546Sopenharmony_ci                util_blitter_destroy(panfrost->blitter);
837bf215546Sopenharmony_ci
838bf215546Sopenharmony_ci        util_unreference_framebuffer_state(&panfrost->pipe_framebuffer);
839bf215546Sopenharmony_ci        u_upload_destroy(pipe->stream_uploader);
840bf215546Sopenharmony_ci
841bf215546Sopenharmony_ci        panfrost_pool_cleanup(&panfrost->descs);
842bf215546Sopenharmony_ci        panfrost_pool_cleanup(&panfrost->shaders);
843bf215546Sopenharmony_ci
844bf215546Sopenharmony_ci        ralloc_free(pipe);
845bf215546Sopenharmony_ci}
846bf215546Sopenharmony_ci
847bf215546Sopenharmony_cistatic struct pipe_query *
848bf215546Sopenharmony_cipanfrost_create_query(struct pipe_context *pipe,
849bf215546Sopenharmony_ci                      unsigned type,
850bf215546Sopenharmony_ci                      unsigned index)
851bf215546Sopenharmony_ci{
852bf215546Sopenharmony_ci        struct panfrost_query *q = rzalloc(pipe, struct panfrost_query);
853bf215546Sopenharmony_ci
854bf215546Sopenharmony_ci        q->type = type;
855bf215546Sopenharmony_ci        q->index = index;
856bf215546Sopenharmony_ci
857bf215546Sopenharmony_ci        return (struct pipe_query *) q;
858bf215546Sopenharmony_ci}
859bf215546Sopenharmony_ci
860bf215546Sopenharmony_cistatic void
861bf215546Sopenharmony_cipanfrost_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
862bf215546Sopenharmony_ci{
863bf215546Sopenharmony_ci        struct panfrost_query *query = (struct panfrost_query *) q;
864bf215546Sopenharmony_ci
865bf215546Sopenharmony_ci        if (query->rsrc)
866bf215546Sopenharmony_ci                pipe_resource_reference(&query->rsrc, NULL);
867bf215546Sopenharmony_ci
868bf215546Sopenharmony_ci        ralloc_free(q);
869bf215546Sopenharmony_ci}
870bf215546Sopenharmony_ci
871bf215546Sopenharmony_cistatic bool
872bf215546Sopenharmony_cipanfrost_begin_query(struct pipe_context *pipe, struct pipe_query *q)
873bf215546Sopenharmony_ci{
874bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
875bf215546Sopenharmony_ci        struct panfrost_device *dev = pan_device(ctx->base.screen);
876bf215546Sopenharmony_ci        struct panfrost_query *query = (struct panfrost_query *) q;
877bf215546Sopenharmony_ci
878bf215546Sopenharmony_ci        switch (query->type) {
879bf215546Sopenharmony_ci        case PIPE_QUERY_OCCLUSION_COUNTER:
880bf215546Sopenharmony_ci        case PIPE_QUERY_OCCLUSION_PREDICATE:
881bf215546Sopenharmony_ci        case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: {
882bf215546Sopenharmony_ci                unsigned size = sizeof(uint64_t) * dev->core_id_range;
883bf215546Sopenharmony_ci
884bf215546Sopenharmony_ci                /* Allocate a resource for the query results to be stored */
885bf215546Sopenharmony_ci                if (!query->rsrc) {
886bf215546Sopenharmony_ci                        query->rsrc = pipe_buffer_create(ctx->base.screen,
887bf215546Sopenharmony_ci                                        PIPE_BIND_QUERY_BUFFER, 0, size);
888bf215546Sopenharmony_ci                }
889bf215546Sopenharmony_ci
890bf215546Sopenharmony_ci                /* Default to 0 if nothing at all drawn. */
891bf215546Sopenharmony_ci                uint8_t *zeroes = alloca(size);
892bf215546Sopenharmony_ci                memset(zeroes, 0, size);
893bf215546Sopenharmony_ci                pipe_buffer_write(pipe, query->rsrc, 0, size, zeroes);
894bf215546Sopenharmony_ci
895bf215546Sopenharmony_ci                query->msaa = (ctx->pipe_framebuffer.samples > 1);
896bf215546Sopenharmony_ci                ctx->occlusion_query = query;
897bf215546Sopenharmony_ci                ctx->dirty |= PAN_DIRTY_OQ;
898bf215546Sopenharmony_ci                break;
899bf215546Sopenharmony_ci        }
900bf215546Sopenharmony_ci
901bf215546Sopenharmony_ci        /* Geometry statistics are computed in the driver. XXX: geom/tess
902bf215546Sopenharmony_ci         * shaders.. */
903bf215546Sopenharmony_ci
904bf215546Sopenharmony_ci        case PIPE_QUERY_PRIMITIVES_GENERATED:
905bf215546Sopenharmony_ci                query->start = ctx->prims_generated;
906bf215546Sopenharmony_ci                break;
907bf215546Sopenharmony_ci        case PIPE_QUERY_PRIMITIVES_EMITTED:
908bf215546Sopenharmony_ci                query->start = ctx->tf_prims_generated;
909bf215546Sopenharmony_ci                break;
910bf215546Sopenharmony_ci
911bf215546Sopenharmony_ci        default:
912bf215546Sopenharmony_ci                /* TODO: timestamp queries, etc? */
913bf215546Sopenharmony_ci                break;
914bf215546Sopenharmony_ci        }
915bf215546Sopenharmony_ci
916bf215546Sopenharmony_ci        return true;
917bf215546Sopenharmony_ci}
918bf215546Sopenharmony_ci
919bf215546Sopenharmony_cistatic bool
920bf215546Sopenharmony_cipanfrost_end_query(struct pipe_context *pipe, struct pipe_query *q)
921bf215546Sopenharmony_ci{
922bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
923bf215546Sopenharmony_ci        struct panfrost_query *query = (struct panfrost_query *) q;
924bf215546Sopenharmony_ci
925bf215546Sopenharmony_ci        switch (query->type) {
926bf215546Sopenharmony_ci        case PIPE_QUERY_OCCLUSION_COUNTER:
927bf215546Sopenharmony_ci        case PIPE_QUERY_OCCLUSION_PREDICATE:
928bf215546Sopenharmony_ci        case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
929bf215546Sopenharmony_ci                ctx->occlusion_query = NULL;
930bf215546Sopenharmony_ci                ctx->dirty |= PAN_DIRTY_OQ;
931bf215546Sopenharmony_ci                break;
932bf215546Sopenharmony_ci        case PIPE_QUERY_PRIMITIVES_GENERATED:
933bf215546Sopenharmony_ci                query->end = ctx->prims_generated;
934bf215546Sopenharmony_ci                break;
935bf215546Sopenharmony_ci        case PIPE_QUERY_PRIMITIVES_EMITTED:
936bf215546Sopenharmony_ci                query->end = ctx->tf_prims_generated;
937bf215546Sopenharmony_ci                break;
938bf215546Sopenharmony_ci        }
939bf215546Sopenharmony_ci
940bf215546Sopenharmony_ci        return true;
941bf215546Sopenharmony_ci}
942bf215546Sopenharmony_ci
943bf215546Sopenharmony_cistatic bool
944bf215546Sopenharmony_cipanfrost_get_query_result(struct pipe_context *pipe,
945bf215546Sopenharmony_ci                          struct pipe_query *q,
946bf215546Sopenharmony_ci                          bool wait,
947bf215546Sopenharmony_ci                          union pipe_query_result *vresult)
948bf215546Sopenharmony_ci{
949bf215546Sopenharmony_ci        struct panfrost_query *query = (struct panfrost_query *) q;
950bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pipe);
951bf215546Sopenharmony_ci        struct panfrost_device *dev = pan_device(ctx->base.screen);
952bf215546Sopenharmony_ci        struct panfrost_resource *rsrc = pan_resource(query->rsrc);
953bf215546Sopenharmony_ci
954bf215546Sopenharmony_ci        switch (query->type) {
955bf215546Sopenharmony_ci        case PIPE_QUERY_OCCLUSION_COUNTER:
956bf215546Sopenharmony_ci        case PIPE_QUERY_OCCLUSION_PREDICATE:
957bf215546Sopenharmony_ci        case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
958bf215546Sopenharmony_ci                panfrost_flush_writer(ctx, rsrc, "Occlusion query");
959bf215546Sopenharmony_ci                panfrost_bo_wait(rsrc->image.data.bo, INT64_MAX, false);
960bf215546Sopenharmony_ci
961bf215546Sopenharmony_ci                /* Read back the query results */
962bf215546Sopenharmony_ci                uint64_t *result = (uint64_t *) rsrc->image.data.bo->ptr.cpu;
963bf215546Sopenharmony_ci
964bf215546Sopenharmony_ci                if (query->type == PIPE_QUERY_OCCLUSION_COUNTER) {
965bf215546Sopenharmony_ci                        uint64_t passed = 0;
966bf215546Sopenharmony_ci                        for (int i = 0; i < dev->core_id_range; ++i)
967bf215546Sopenharmony_ci                                passed += result[i];
968bf215546Sopenharmony_ci
969bf215546Sopenharmony_ci                        if (dev->arch <= 5 && !query->msaa)
970bf215546Sopenharmony_ci                                passed /= 4;
971bf215546Sopenharmony_ci
972bf215546Sopenharmony_ci                        vresult->u64 = passed;
973bf215546Sopenharmony_ci                } else {
974bf215546Sopenharmony_ci                        vresult->b = !!result[0];
975bf215546Sopenharmony_ci                }
976bf215546Sopenharmony_ci
977bf215546Sopenharmony_ci                break;
978bf215546Sopenharmony_ci
979bf215546Sopenharmony_ci        case PIPE_QUERY_PRIMITIVES_GENERATED:
980bf215546Sopenharmony_ci        case PIPE_QUERY_PRIMITIVES_EMITTED:
981bf215546Sopenharmony_ci                panfrost_flush_all_batches(ctx, "Primitive count query");
982bf215546Sopenharmony_ci                vresult->u64 = query->end - query->start;
983bf215546Sopenharmony_ci                break;
984bf215546Sopenharmony_ci
985bf215546Sopenharmony_ci        default:
986bf215546Sopenharmony_ci                /* TODO: more queries */
987bf215546Sopenharmony_ci                break;
988bf215546Sopenharmony_ci        }
989bf215546Sopenharmony_ci
990bf215546Sopenharmony_ci        return true;
991bf215546Sopenharmony_ci}
992bf215546Sopenharmony_ci
993bf215546Sopenharmony_cibool
994bf215546Sopenharmony_cipanfrost_render_condition_check(struct panfrost_context *ctx)
995bf215546Sopenharmony_ci{
996bf215546Sopenharmony_ci	if (!ctx->cond_query)
997bf215546Sopenharmony_ci		return true;
998bf215546Sopenharmony_ci
999bf215546Sopenharmony_ci        perf_debug_ctx(ctx, "Implementing conditional rendering on the CPU");
1000bf215546Sopenharmony_ci
1001bf215546Sopenharmony_ci	union pipe_query_result res = { 0 };
1002bf215546Sopenharmony_ci	bool wait =
1003bf215546Sopenharmony_ci		ctx->cond_mode != PIPE_RENDER_COND_NO_WAIT &&
1004bf215546Sopenharmony_ci		ctx->cond_mode != PIPE_RENDER_COND_BY_REGION_NO_WAIT;
1005bf215546Sopenharmony_ci
1006bf215546Sopenharmony_ci        struct pipe_query *pq = (struct pipe_query *)ctx->cond_query;
1007bf215546Sopenharmony_ci
1008bf215546Sopenharmony_ci        if (panfrost_get_query_result(&ctx->base, pq, wait, &res))
1009bf215546Sopenharmony_ci                return res.u64 != ctx->cond_cond;
1010bf215546Sopenharmony_ci
1011bf215546Sopenharmony_ci	return true;
1012bf215546Sopenharmony_ci}
1013bf215546Sopenharmony_ci
1014bf215546Sopenharmony_cistatic struct pipe_stream_output_target *
1015bf215546Sopenharmony_cipanfrost_create_stream_output_target(struct pipe_context *pctx,
1016bf215546Sopenharmony_ci                                     struct pipe_resource *prsc,
1017bf215546Sopenharmony_ci                                     unsigned buffer_offset,
1018bf215546Sopenharmony_ci                                     unsigned buffer_size)
1019bf215546Sopenharmony_ci{
1020bf215546Sopenharmony_ci        struct pipe_stream_output_target *target;
1021bf215546Sopenharmony_ci
1022bf215546Sopenharmony_ci        target = &rzalloc(pctx, struct panfrost_streamout_target)->base;
1023bf215546Sopenharmony_ci
1024bf215546Sopenharmony_ci        if (!target)
1025bf215546Sopenharmony_ci                return NULL;
1026bf215546Sopenharmony_ci
1027bf215546Sopenharmony_ci        pipe_reference_init(&target->reference, 1);
1028bf215546Sopenharmony_ci        pipe_resource_reference(&target->buffer, prsc);
1029bf215546Sopenharmony_ci
1030bf215546Sopenharmony_ci        target->context = pctx;
1031bf215546Sopenharmony_ci        target->buffer_offset = buffer_offset;
1032bf215546Sopenharmony_ci        target->buffer_size = buffer_size;
1033bf215546Sopenharmony_ci
1034bf215546Sopenharmony_ci        return target;
1035bf215546Sopenharmony_ci}
1036bf215546Sopenharmony_ci
1037bf215546Sopenharmony_cistatic void
1038bf215546Sopenharmony_cipanfrost_stream_output_target_destroy(struct pipe_context *pctx,
1039bf215546Sopenharmony_ci                                      struct pipe_stream_output_target *target)
1040bf215546Sopenharmony_ci{
1041bf215546Sopenharmony_ci        pipe_resource_reference(&target->buffer, NULL);
1042bf215546Sopenharmony_ci        ralloc_free(target);
1043bf215546Sopenharmony_ci}
1044bf215546Sopenharmony_ci
1045bf215546Sopenharmony_cistatic void
1046bf215546Sopenharmony_cipanfrost_set_stream_output_targets(struct pipe_context *pctx,
1047bf215546Sopenharmony_ci                                   unsigned num_targets,
1048bf215546Sopenharmony_ci                                   struct pipe_stream_output_target **targets,
1049bf215546Sopenharmony_ci                                   const unsigned *offsets)
1050bf215546Sopenharmony_ci{
1051bf215546Sopenharmony_ci        struct panfrost_context *ctx = pan_context(pctx);
1052bf215546Sopenharmony_ci        struct panfrost_streamout *so = &ctx->streamout;
1053bf215546Sopenharmony_ci
1054bf215546Sopenharmony_ci        assert(num_targets <= ARRAY_SIZE(so->targets));
1055bf215546Sopenharmony_ci
1056bf215546Sopenharmony_ci        for (unsigned i = 0; i < num_targets; i++) {
1057bf215546Sopenharmony_ci                if (targets[i] && offsets[i] != -1)
1058bf215546Sopenharmony_ci                        pan_so_target(targets[i])->offset = offsets[i];
1059bf215546Sopenharmony_ci
1060bf215546Sopenharmony_ci                pipe_so_target_reference(&so->targets[i], targets[i]);
1061bf215546Sopenharmony_ci        }
1062bf215546Sopenharmony_ci
1063bf215546Sopenharmony_ci        for (unsigned i = num_targets; i < so->num_targets; i++)
1064bf215546Sopenharmony_ci                pipe_so_target_reference(&so->targets[i], NULL);
1065bf215546Sopenharmony_ci
1066bf215546Sopenharmony_ci        so->num_targets = num_targets;
1067bf215546Sopenharmony_ci        ctx->dirty |= PAN_DIRTY_SO;
1068bf215546Sopenharmony_ci}
1069bf215546Sopenharmony_ci
1070bf215546Sopenharmony_cistruct pipe_context *
1071bf215546Sopenharmony_cipanfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
1072bf215546Sopenharmony_ci{
1073bf215546Sopenharmony_ci        struct panfrost_context *ctx = rzalloc(NULL, struct panfrost_context);
1074bf215546Sopenharmony_ci        struct pipe_context *gallium = (struct pipe_context *) ctx;
1075bf215546Sopenharmony_ci        struct panfrost_device *dev = pan_device(screen);
1076bf215546Sopenharmony_ci
1077bf215546Sopenharmony_ci        gallium->screen = screen;
1078bf215546Sopenharmony_ci
1079bf215546Sopenharmony_ci        gallium->destroy = panfrost_destroy;
1080bf215546Sopenharmony_ci
1081bf215546Sopenharmony_ci        gallium->set_framebuffer_state = panfrost_set_framebuffer_state;
1082bf215546Sopenharmony_ci
1083bf215546Sopenharmony_ci        gallium->flush = panfrost_flush;
1084bf215546Sopenharmony_ci        gallium->clear = panfrost_clear;
1085bf215546Sopenharmony_ci        gallium->texture_barrier = panfrost_texture_barrier;
1086bf215546Sopenharmony_ci        gallium->set_frontend_noop = panfrost_set_frontend_noop;
1087bf215546Sopenharmony_ci
1088bf215546Sopenharmony_ci        gallium->set_vertex_buffers = panfrost_set_vertex_buffers;
1089bf215546Sopenharmony_ci        gallium->set_constant_buffer = panfrost_set_constant_buffer;
1090bf215546Sopenharmony_ci        gallium->set_shader_buffers = panfrost_set_shader_buffers;
1091bf215546Sopenharmony_ci        gallium->set_shader_images = panfrost_set_shader_images;
1092bf215546Sopenharmony_ci
1093bf215546Sopenharmony_ci        gallium->set_stencil_ref = panfrost_set_stencil_ref;
1094bf215546Sopenharmony_ci
1095bf215546Sopenharmony_ci        gallium->set_sampler_views = panfrost_set_sampler_views;
1096bf215546Sopenharmony_ci
1097bf215546Sopenharmony_ci        gallium->bind_rasterizer_state = panfrost_bind_rasterizer_state;
1098bf215546Sopenharmony_ci        gallium->delete_rasterizer_state = panfrost_generic_cso_delete;
1099bf215546Sopenharmony_ci
1100bf215546Sopenharmony_ci        gallium->bind_vertex_elements_state = panfrost_bind_vertex_elements_state;
1101bf215546Sopenharmony_ci        gallium->delete_vertex_elements_state = panfrost_generic_cso_delete;
1102bf215546Sopenharmony_ci
1103bf215546Sopenharmony_ci        gallium->create_fs_state = panfrost_create_shader_state;
1104bf215546Sopenharmony_ci        gallium->delete_fs_state = panfrost_delete_shader_state;
1105bf215546Sopenharmony_ci        gallium->bind_fs_state = panfrost_bind_fs_state;
1106bf215546Sopenharmony_ci
1107bf215546Sopenharmony_ci        gallium->create_vs_state = panfrost_create_shader_state;
1108bf215546Sopenharmony_ci        gallium->delete_vs_state = panfrost_delete_shader_state;
1109bf215546Sopenharmony_ci        gallium->bind_vs_state = panfrost_bind_vs_state;
1110bf215546Sopenharmony_ci
1111bf215546Sopenharmony_ci        gallium->delete_sampler_state = panfrost_generic_cso_delete;
1112bf215546Sopenharmony_ci        gallium->bind_sampler_states = panfrost_bind_sampler_states;
1113bf215546Sopenharmony_ci
1114bf215546Sopenharmony_ci        gallium->bind_depth_stencil_alpha_state   = panfrost_bind_depth_stencil_state;
1115bf215546Sopenharmony_ci        gallium->delete_depth_stencil_alpha_state = panfrost_generic_cso_delete;
1116bf215546Sopenharmony_ci
1117bf215546Sopenharmony_ci        gallium->set_sample_mask = panfrost_set_sample_mask;
1118bf215546Sopenharmony_ci        gallium->set_min_samples = panfrost_set_min_samples;
1119bf215546Sopenharmony_ci
1120bf215546Sopenharmony_ci        gallium->set_clip_state = panfrost_set_clip_state;
1121bf215546Sopenharmony_ci        gallium->set_viewport_states = panfrost_set_viewport_states;
1122bf215546Sopenharmony_ci        gallium->set_scissor_states = panfrost_set_scissor_states;
1123bf215546Sopenharmony_ci        gallium->set_polygon_stipple = panfrost_set_polygon_stipple;
1124bf215546Sopenharmony_ci        gallium->set_active_query_state = panfrost_set_active_query_state;
1125bf215546Sopenharmony_ci        gallium->render_condition = panfrost_render_condition;
1126bf215546Sopenharmony_ci
1127bf215546Sopenharmony_ci        gallium->create_query = panfrost_create_query;
1128bf215546Sopenharmony_ci        gallium->destroy_query = panfrost_destroy_query;
1129bf215546Sopenharmony_ci        gallium->begin_query = panfrost_begin_query;
1130bf215546Sopenharmony_ci        gallium->end_query = panfrost_end_query;
1131bf215546Sopenharmony_ci        gallium->get_query_result = panfrost_get_query_result;
1132bf215546Sopenharmony_ci
1133bf215546Sopenharmony_ci        gallium->create_stream_output_target = panfrost_create_stream_output_target;
1134bf215546Sopenharmony_ci        gallium->stream_output_target_destroy = panfrost_stream_output_target_destroy;
1135bf215546Sopenharmony_ci        gallium->set_stream_output_targets = panfrost_set_stream_output_targets;
1136bf215546Sopenharmony_ci
1137bf215546Sopenharmony_ci        gallium->bind_blend_state   = panfrost_bind_blend_state;
1138bf215546Sopenharmony_ci        gallium->delete_blend_state = panfrost_generic_cso_delete;
1139bf215546Sopenharmony_ci
1140bf215546Sopenharmony_ci        gallium->set_blend_color = panfrost_set_blend_color;
1141bf215546Sopenharmony_ci
1142bf215546Sopenharmony_ci        pan_screen(screen)->vtbl.context_init(gallium);
1143bf215546Sopenharmony_ci
1144bf215546Sopenharmony_ci        panfrost_resource_context_init(gallium);
1145bf215546Sopenharmony_ci        panfrost_compute_context_init(gallium);
1146bf215546Sopenharmony_ci
1147bf215546Sopenharmony_ci        gallium->stream_uploader = u_upload_create_default(gallium);
1148bf215546Sopenharmony_ci        gallium->const_uploader = gallium->stream_uploader;
1149bf215546Sopenharmony_ci
1150bf215546Sopenharmony_ci        panfrost_pool_init(&ctx->descs, ctx, dev,
1151bf215546Sopenharmony_ci                        0, 4096, "Descriptors", true, false);
1152bf215546Sopenharmony_ci
1153bf215546Sopenharmony_ci        panfrost_pool_init(&ctx->shaders, ctx, dev,
1154bf215546Sopenharmony_ci                        PAN_BO_EXECUTE, 4096, "Shaders", true, false);
1155bf215546Sopenharmony_ci
1156bf215546Sopenharmony_ci        ctx->blitter = util_blitter_create(gallium);
1157bf215546Sopenharmony_ci
1158bf215546Sopenharmony_ci        ctx->writers = _mesa_hash_table_create(gallium, _mesa_hash_pointer,
1159bf215546Sopenharmony_ci                                                        _mesa_key_pointer_equal);
1160bf215546Sopenharmony_ci
1161bf215546Sopenharmony_ci        assert(ctx->blitter);
1162bf215546Sopenharmony_ci
1163bf215546Sopenharmony_ci        /* Prepare for render! */
1164bf215546Sopenharmony_ci
1165bf215546Sopenharmony_ci        /* By default mask everything on */
1166bf215546Sopenharmony_ci        ctx->sample_mask = ~0;
1167bf215546Sopenharmony_ci        ctx->active_queries = true;
1168bf215546Sopenharmony_ci
1169bf215546Sopenharmony_ci        int ASSERTED ret;
1170bf215546Sopenharmony_ci
1171bf215546Sopenharmony_ci        /* Create a syncobj in a signaled state. Will be updated to point to the
1172bf215546Sopenharmony_ci         * last queued job out_sync every time we submit a new job.
1173bf215546Sopenharmony_ci         */
1174bf215546Sopenharmony_ci        ret = drmSyncobjCreate(dev->fd, DRM_SYNCOBJ_CREATE_SIGNALED, &ctx->syncobj);
1175bf215546Sopenharmony_ci        assert(!ret && ctx->syncobj);
1176bf215546Sopenharmony_ci
1177bf215546Sopenharmony_ci        return gallium;
1178bf215546Sopenharmony_ci}
1179