17ec681f3Smrg/*
27ec681f3Smrg * Copyright (C) 2019 Collabora, Ltd.
37ec681f3Smrg * Copyright (C) 2019 Red Hat Inc.
47ec681f3Smrg *
57ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
67ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
77ec681f3Smrg * to deal in the Software without restriction, including without limitation
87ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
97ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
107ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
117ec681f3Smrg *
127ec681f3Smrg * The above copyright notice and this permission notice (including the next
137ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
147ec681f3Smrg * Software.
157ec681f3Smrg *
167ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
177ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
197ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
207ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
217ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
227ec681f3Smrg * SOFTWARE.
237ec681f3Smrg *
247ec681f3Smrg * Authors (Collabora):
257ec681f3Smrg *   Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
267ec681f3Smrg *
277ec681f3Smrg */
287ec681f3Smrg
297ec681f3Smrg#include "pan_context.h"
307ec681f3Smrg#include "panfrost-quirks.h"
317ec681f3Smrg#include "pan_bo.h"
327ec681f3Smrg#include "pan_shader.h"
337ec681f3Smrg#include "util/u_memory.h"
347ec681f3Smrg#include "nir_serialize.h"
357ec681f3Smrg
367ec681f3Smrg/* Compute CSOs are tracked like graphics shader CSOs, but are
377ec681f3Smrg * considerably simpler. We do not implement multiple
387ec681f3Smrg * variants/keying. So the CSO create function just goes ahead and
397ec681f3Smrg * compiles the thing. */
407ec681f3Smrg
417ec681f3Smrgstatic void *
427ec681f3Smrgpanfrost_create_compute_state(
437ec681f3Smrg        struct pipe_context *pctx,
447ec681f3Smrg        const struct pipe_compute_state *cso)
457ec681f3Smrg{
467ec681f3Smrg        struct panfrost_context *ctx = pan_context(pctx);
477ec681f3Smrg        struct panfrost_screen *screen = pan_screen(pctx->screen);
487ec681f3Smrg
497ec681f3Smrg        struct panfrost_shader_variants *so = CALLOC_STRUCT(panfrost_shader_variants);
507ec681f3Smrg        so->cbase = *cso;
517ec681f3Smrg        so->is_compute = true;
527ec681f3Smrg
537ec681f3Smrg        struct panfrost_shader_state *v = calloc(1, sizeof(*v));
547ec681f3Smrg        so->variants = v;
557ec681f3Smrg
567ec681f3Smrg        so->variant_count = 1;
577ec681f3Smrg        so->active_variant = 0;
587ec681f3Smrg
597ec681f3Smrg        if (cso->ir_type == PIPE_SHADER_IR_NIR_SERIALIZED) {
607ec681f3Smrg                struct blob_reader reader;
617ec681f3Smrg                const struct pipe_binary_program_header *hdr = cso->prog;
627ec681f3Smrg
637ec681f3Smrg                blob_reader_init(&reader, hdr->blob, hdr->num_bytes);
647ec681f3Smrg
657ec681f3Smrg                const struct nir_shader_compiler_options *options =
667ec681f3Smrg                        screen->vtbl.get_compiler_options();
677ec681f3Smrg
687ec681f3Smrg                so->cbase.prog = nir_deserialize(NULL, options, &reader);
697ec681f3Smrg                so->cbase.ir_type = PIPE_SHADER_IR_NIR;
707ec681f3Smrg        }
717ec681f3Smrg
727ec681f3Smrg        panfrost_shader_compile(pctx->screen, &ctx->shaders, &ctx->descs,
737ec681f3Smrg                        so->cbase.ir_type, so->cbase.prog, MESA_SHADER_COMPUTE,
747ec681f3Smrg                        v);
757ec681f3Smrg
767ec681f3Smrg        /* There are no variants so we won't need the NIR again */
777ec681f3Smrg        ralloc_free((void *)so->cbase.prog);
787ec681f3Smrg        so->cbase.prog = NULL;
797ec681f3Smrg
807ec681f3Smrg        return so;
817ec681f3Smrg}
827ec681f3Smrg
837ec681f3Smrgstatic void
847ec681f3Smrgpanfrost_bind_compute_state(struct pipe_context *pipe, void *cso)
857ec681f3Smrg{
867ec681f3Smrg        struct panfrost_context *ctx = pan_context(pipe);
877ec681f3Smrg        ctx->shader[PIPE_SHADER_COMPUTE] = cso;
887ec681f3Smrg}
897ec681f3Smrg
907ec681f3Smrgstatic void
917ec681f3Smrgpanfrost_delete_compute_state(struct pipe_context *pipe, void *cso)
927ec681f3Smrg{
937ec681f3Smrg        struct panfrost_shader_variants *so =
947ec681f3Smrg                (struct panfrost_shader_variants *)cso;
957ec681f3Smrg
967ec681f3Smrg        free(so->variants);
977ec681f3Smrg        free(cso);
987ec681f3Smrg}
997ec681f3Smrg
1007ec681f3Smrgstatic void
1017ec681f3Smrgpanfrost_set_compute_resources(struct pipe_context *pctx,
1027ec681f3Smrg                         unsigned start, unsigned count,
1037ec681f3Smrg                         struct pipe_surface **resources)
1047ec681f3Smrg{
1057ec681f3Smrg        /* TODO */
1067ec681f3Smrg}
1077ec681f3Smrg
1087ec681f3Smrgstatic void
1097ec681f3Smrgpanfrost_set_global_binding(struct pipe_context *pctx,
1107ec681f3Smrg                      unsigned first, unsigned count,
1117ec681f3Smrg                      struct pipe_resource **resources,
1127ec681f3Smrg                      uint32_t **handles)
1137ec681f3Smrg{
1147ec681f3Smrg        if (!resources)
1157ec681f3Smrg                return;
1167ec681f3Smrg
1177ec681f3Smrg        struct panfrost_context *ctx = pan_context(pctx);
1187ec681f3Smrg        struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
1197ec681f3Smrg
1207ec681f3Smrg        for (unsigned i = first; i < first + count; ++i) {
1217ec681f3Smrg                struct panfrost_resource *rsrc = pan_resource(resources[i]);
1227ec681f3Smrg                panfrost_batch_write_rsrc(batch, rsrc, PIPE_SHADER_COMPUTE);
1237ec681f3Smrg
1247ec681f3Smrg                util_range_add(&rsrc->base, &rsrc->valid_buffer_range,
1257ec681f3Smrg                                0, rsrc->base.width0);
1267ec681f3Smrg
1277ec681f3Smrg                /* The handle points to uint32_t, but space is allocated for 64 bits */
1287ec681f3Smrg                memcpy(handles[i], &rsrc->image.data.bo->ptr.gpu, sizeof(mali_ptr));
1297ec681f3Smrg        }
1307ec681f3Smrg}
1317ec681f3Smrg
1327ec681f3Smrgstatic void
1337ec681f3Smrgpanfrost_memory_barrier(struct pipe_context *pctx, unsigned flags)
1347ec681f3Smrg{
1357ec681f3Smrg        /* TODO: Be smart and only flush the minimum needed, maybe emitting a
1367ec681f3Smrg         * cache flush job if that would help */
1377ec681f3Smrg        panfrost_flush_all_batches(pan_context(pctx), "Memory barrier");
1387ec681f3Smrg}
1397ec681f3Smrg
1407ec681f3Smrgvoid
1417ec681f3Smrgpanfrost_compute_context_init(struct pipe_context *pctx)
1427ec681f3Smrg{
1437ec681f3Smrg        pctx->create_compute_state = panfrost_create_compute_state;
1447ec681f3Smrg        pctx->bind_compute_state = panfrost_bind_compute_state;
1457ec681f3Smrg        pctx->delete_compute_state = panfrost_delete_compute_state;
1467ec681f3Smrg
1477ec681f3Smrg        pctx->set_compute_resources = panfrost_set_compute_resources;
1487ec681f3Smrg        pctx->set_global_binding = panfrost_set_global_binding;
1497ec681f3Smrg
1507ec681f3Smrg        pctx->memory_barrier = panfrost_memory_barrier;
1517ec681f3Smrg}
152