19f464c52Smaya/* 27ec681f3Smrg * Copyright (C) 2019-2020 Collabora, Ltd. 39f464c52Smaya * © Copyright 2018 Alyssa Rosenzweig 47ec681f3Smrg * Copyright © 2014-2017 Broadcom 57ec681f3Smrg * Copyright (C) 2017 Intel Corporation 69f464c52Smaya * 79f464c52Smaya * Permission is hereby granted, free of charge, to any person obtaining a 89f464c52Smaya * copy of this software and associated documentation files (the "Software"), 99f464c52Smaya * to deal in the Software without restriction, including without limitation 109f464c52Smaya * the rights to use, copy, modify, merge, publish, distribute, sublicense, 119f464c52Smaya * and/or sell copies of the Software, and to permit persons to whom the 129f464c52Smaya * Software is furnished to do so, subject to the following conditions: 139f464c52Smaya * 149f464c52Smaya * The above copyright notice and this permission notice (including the next 159f464c52Smaya * paragraph) shall be included in all copies or substantial portions of the 169f464c52Smaya * Software. 179f464c52Smaya * 189f464c52Smaya * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 199f464c52Smaya * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 209f464c52Smaya * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 219f464c52Smaya * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 229f464c52Smaya * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 239f464c52Smaya * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 249f464c52Smaya * SOFTWARE. 259f464c52Smaya * 269f464c52Smaya */ 279f464c52Smaya 289f464c52Smaya#include <sys/poll.h> 299f464c52Smaya#include <errno.h> 309f464c52Smaya 317ec681f3Smrg#include "pan_bo.h" 329f464c52Smaya#include "pan_context.h" 337ec681f3Smrg#include "pan_minmax_cache.h" 347ec681f3Smrg#include "panfrost-quirks.h" 359f464c52Smaya 369f464c52Smaya#include "util/macros.h" 377ec681f3Smrg#include "util/format/u_format.h" 389f464c52Smaya#include "util/u_inlines.h" 399f464c52Smaya#include "util/u_upload_mgr.h" 409f464c52Smaya#include "util/u_memory.h" 419f464c52Smaya#include "util/u_vbuf.h" 429f464c52Smaya#include "util/half_float.h" 439f464c52Smaya#include "util/u_helpers.h" 447ec681f3Smrg#include "util/format/u_format.h" 457ec681f3Smrg#include "util/u_prim.h" 467ec681f3Smrg#include "util/u_prim_restart.h" 479f464c52Smaya#include "tgsi/tgsi_parse.h" 487ec681f3Smrg#include "tgsi/tgsi_from_mesa.h" 499f464c52Smaya#include "util/u_math.h" 509f464c52Smaya 519f464c52Smaya#include "pan_screen.h" 529f464c52Smaya#include "pan_util.h" 537ec681f3Smrg#include "decode.h" 547ec681f3Smrg#include "util/pan_lower_framebuffer.h" 559f464c52Smaya 569f464c52Smayastatic void 577ec681f3Smrgpanfrost_clear( 587ec681f3Smrg struct pipe_context *pipe, 597ec681f3Smrg unsigned buffers, 607ec681f3Smrg const struct pipe_scissor_state *scissor_state, 617ec681f3Smrg const union pipe_color_union *color, 627ec681f3Smrg double depth, unsigned stencil) 639f464c52Smaya{ 647ec681f3Smrg struct panfrost_context *ctx = pan_context(pipe); 659f464c52Smaya 667ec681f3Smrg if (!panfrost_render_condition_check(ctx)) 677ec681f3Smrg return; 689f464c52Smaya 697ec681f3Smrg /* TODO: panfrost_get_fresh_batch_for_fbo() instantiates a new batch if 707ec681f3Smrg * the existing batch targeting this FBO has draws. We could probably 717ec681f3Smrg * avoid that by replacing plain clears by quad-draws with a specific 727ec681f3Smrg * color/depth/stencil value, thus avoiding the generation of extra 737ec681f3Smrg * fragment jobs. 747ec681f3Smrg */ 757ec681f3Smrg struct panfrost_batch *batch = panfrost_get_fresh_batch_for_fbo(ctx, "Clear"); 767ec681f3Smrg panfrost_batch_clear(batch, buffers, color, depth, stencil); 779f464c52Smaya} 789f464c52Smaya 797ec681f3Smrgbool 807ec681f3Smrgpanfrost_writes_point_size(struct panfrost_context *ctx) 819f464c52Smaya{ 827ec681f3Smrg assert(ctx->shader[PIPE_SHADER_VERTEX]); 837ec681f3Smrg struct panfrost_shader_state *vs = panfrost_get_shader_state(ctx, PIPE_SHADER_VERTEX); 849f464c52Smaya 857ec681f3Smrg return vs->info.vs.writes_point_size && ctx->active_prim == PIPE_PRIM_POINTS; 869f464c52Smaya} 879f464c52Smaya 889f464c52Smaya/* The entire frame is in memory -- send it off to the kernel! */ 899f464c52Smaya 909f464c52Smayavoid 919f464c52Smayapanfrost_flush( 929f464c52Smaya struct pipe_context *pipe, 939f464c52Smaya struct pipe_fence_handle **fence, 949f464c52Smaya unsigned flags) 959f464c52Smaya{ 969f464c52Smaya struct panfrost_context *ctx = pan_context(pipe); 977ec681f3Smrg struct panfrost_device *dev = pan_device(pipe->screen); 989f464c52Smaya 999f464c52Smaya 1007ec681f3Smrg /* Submit all pending jobs */ 1017ec681f3Smrg panfrost_flush_all_batches(ctx, NULL); 1029f464c52Smaya 1037ec681f3Smrg if (fence) { 1047ec681f3Smrg struct pipe_fence_handle *f = panfrost_fence_create(ctx); 1057ec681f3Smrg pipe->screen->fence_reference(pipe->screen, fence, NULL); 1067ec681f3Smrg *fence = f; 1079f464c52Smaya } 1089f464c52Smaya 1097ec681f3Smrg if (dev->debug & PAN_DBG_TRACE) 1107ec681f3Smrg pandecode_next_frame(); 1119f464c52Smaya} 1129f464c52Smaya 1137ec681f3Smrgstatic void 1147ec681f3Smrgpanfrost_texture_barrier(struct pipe_context *pipe, unsigned flags) 1159f464c52Smaya{ 1167ec681f3Smrg struct panfrost_context *ctx = pan_context(pipe); 1177ec681f3Smrg panfrost_flush_all_batches(ctx, "Texture barrier"); 1189f464c52Smaya} 1199f464c52Smaya 1209f464c52Smayastatic void 1217ec681f3Smrgpanfrost_set_frontend_noop(struct pipe_context *pipe, bool enable) 1229f464c52Smaya{ 1239f464c52Smaya struct panfrost_context *ctx = pan_context(pipe); 1247ec681f3Smrg panfrost_flush_all_batches(ctx, "Frontend no-op change"); 1257ec681f3Smrg ctx->is_noop = enable; 1269f464c52Smaya} 1279f464c52Smaya 1289f464c52Smaya 1299f464c52Smayastatic void 1309f464c52Smayapanfrost_generic_cso_delete(struct pipe_context *pctx, void *hwcso) 1319f464c52Smaya{ 1329f464c52Smaya free(hwcso); 1339f464c52Smaya} 1349f464c52Smaya 1359f464c52Smayastatic void 1367ec681f3Smrgpanfrost_bind_blend_state(struct pipe_context *pipe, void *cso) 1379f464c52Smaya{ 1387ec681f3Smrg struct panfrost_context *ctx = pan_context(pipe); 1397ec681f3Smrg ctx->blend = cso; 1407ec681f3Smrg ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER; 1419f464c52Smaya} 1429f464c52Smaya 1439f464c52Smayastatic void 1447ec681f3Smrgpanfrost_set_blend_color(struct pipe_context *pipe, 1457ec681f3Smrg const struct pipe_blend_color *blend_color) 1469f464c52Smaya{ 1477ec681f3Smrg struct panfrost_context *ctx = pan_context(pipe); 1487ec681f3Smrg ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER; 1499f464c52Smaya 1507ec681f3Smrg if (blend_color) 1517ec681f3Smrg ctx->blend_color = *blend_color; 1529f464c52Smaya} 1539f464c52Smaya 1547ec681f3Smrg/* Create a final blend given the context */ 1559f464c52Smaya 1567ec681f3Smrgmali_ptr 1577ec681f3Smrgpanfrost_get_blend(struct panfrost_batch *batch, unsigned rti, struct panfrost_bo **bo, unsigned *shader_offset) 1589f464c52Smaya{ 1597ec681f3Smrg struct panfrost_context *ctx = batch->ctx; 1607ec681f3Smrg struct panfrost_device *dev = pan_device(ctx->base.screen); 1617ec681f3Smrg struct panfrost_blend_state *blend = ctx->blend; 1627ec681f3Smrg struct pan_blend_info info = blend->info[rti]; 1637ec681f3Smrg struct pipe_surface *surf = batch->key.cbufs[rti]; 1647ec681f3Smrg enum pipe_format fmt = surf->format; 1659f464c52Smaya 1667ec681f3Smrg /* Use fixed-function if the equation permits, the format is blendable, 1677ec681f3Smrg * and no more than one unique constant is accessed */ 1687ec681f3Smrg if (info.fixed_function && panfrost_blendable_formats_v7[fmt].internal && 1697ec681f3Smrg pan_blend_is_homogenous_constant(info.constant_mask, 1707ec681f3Smrg ctx->blend_color.color)) { 1717ec681f3Smrg return 0; 1729f464c52Smaya } 1739f464c52Smaya 1747ec681f3Smrg /* Otherwise, we need to grab a shader */ 1757ec681f3Smrg struct pan_blend_state pan_blend = blend->pan; 1767ec681f3Smrg unsigned nr_samples = surf->nr_samples ? : surf->texture->nr_samples; 1779f464c52Smaya 1787ec681f3Smrg pan_blend.rts[rti].format = fmt; 1797ec681f3Smrg pan_blend.rts[rti].nr_samples = nr_samples; 1807ec681f3Smrg memcpy(pan_blend.constants, ctx->blend_color.color, 1817ec681f3Smrg sizeof(pan_blend.constants)); 1829f464c52Smaya 1837ec681f3Smrg /* Upload the shader, sharing a BO */ 1847ec681f3Smrg if (!(*bo)) { 1857ec681f3Smrg *bo = panfrost_batch_create_bo(batch, 4096, PAN_BO_EXECUTE, 1867ec681f3Smrg PIPE_SHADER_FRAGMENT, "Blend shader"); 1879f464c52Smaya } 1889f464c52Smaya 1897ec681f3Smrg struct panfrost_shader_state *ss = panfrost_get_shader_state(ctx, PIPE_SHADER_FRAGMENT); 1909f464c52Smaya 1917ec681f3Smrg /* Default for Midgard */ 1927ec681f3Smrg nir_alu_type col0_type = nir_type_float32; 1937ec681f3Smrg nir_alu_type col1_type = nir_type_float32; 1949f464c52Smaya 1957ec681f3Smrg /* Bifrost has per-output types, respect them */ 1967ec681f3Smrg if (pan_is_bifrost(dev)) { 1977ec681f3Smrg col0_type = ss->info.bifrost.blend[rti].type; 1987ec681f3Smrg col1_type = ss->info.bifrost.blend_src1_type; 1999f464c52Smaya } 2009f464c52Smaya 2017ec681f3Smrg pthread_mutex_lock(&dev->blend_shaders.lock); 2027ec681f3Smrg struct pan_blend_shader_variant *shader = 2037ec681f3Smrg pan_screen(ctx->base.screen)->vtbl.get_blend_shader(dev, 2047ec681f3Smrg &pan_blend, 2057ec681f3Smrg col0_type, 2067ec681f3Smrg col1_type, 2077ec681f3Smrg rti); 2089f464c52Smaya 2097ec681f3Smrg /* Size check and upload */ 2107ec681f3Smrg unsigned offset = *shader_offset; 2117ec681f3Smrg assert((offset + shader->binary.size) < 4096); 2127ec681f3Smrg memcpy((*bo)->ptr.cpu + offset, shader->binary.data, shader->binary.size); 2137ec681f3Smrg *shader_offset += shader->binary.size; 2147ec681f3Smrg pthread_mutex_unlock(&dev->blend_shaders.lock); 2159f464c52Smaya 2167ec681f3Smrg return ((*bo)->ptr.gpu + offset) | shader->first_tag; 2179f464c52Smaya} 2189f464c52Smaya 2199f464c52Smayastatic void 2207ec681f3Smrgpanfrost_bind_rasterizer_state( 2219f464c52Smaya struct pipe_context *pctx, 2227ec681f3Smrg void *hwcso) 2239f464c52Smaya{ 2249f464c52Smaya struct panfrost_context *ctx = pan_context(pctx); 2257ec681f3Smrg ctx->rasterizer = hwcso; 2269f464c52Smaya 2277ec681f3Smrg /* We can assume the renderer state descriptor is always dirty, the 2287ec681f3Smrg * dependencies are too intricate to bother tracking in detail. However 2297ec681f3Smrg * we could probably diff the renderers for viewport dirty tracking, 2307ec681f3Smrg * that just cares about the scissor enable and the depth clips. */ 2317ec681f3Smrg ctx->dirty |= PAN_DIRTY_SCISSOR; 2327ec681f3Smrg ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER; 2339f464c52Smaya} 2349f464c52Smaya 2359f464c52Smayastatic void 2367ec681f3Smrgpanfrost_set_shader_images( 2379f464c52Smaya struct pipe_context *pctx, 2387ec681f3Smrg enum pipe_shader_type shader, 2397ec681f3Smrg unsigned start_slot, unsigned count, unsigned unbind_num_trailing_slots, 2407ec681f3Smrg const struct pipe_image_view *iviews) 2419f464c52Smaya{ 2429f464c52Smaya struct panfrost_context *ctx = pan_context(pctx); 2437ec681f3Smrg ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_IMAGE; 2449f464c52Smaya 2457ec681f3Smrg /* Unbind start_slot...start_slot+count */ 2467ec681f3Smrg if (!iviews) { 2477ec681f3Smrg for (int i = start_slot; i < start_slot + count + unbind_num_trailing_slots; i++) { 2487ec681f3Smrg pipe_resource_reference(&ctx->images[shader][i].resource, NULL); 2497ec681f3Smrg } 2509f464c52Smaya 2517ec681f3Smrg ctx->image_mask[shader] &= ~(((1ull << count) - 1) << start_slot); 2527ec681f3Smrg return; 2539f464c52Smaya } 2549f464c52Smaya 2557ec681f3Smrg /* Bind start_slot...start_slot+count */ 2567ec681f3Smrg for (int i = 0; i < count; i++) { 2577ec681f3Smrg const struct pipe_image_view *image = &iviews[i]; 2587ec681f3Smrg SET_BIT(ctx->image_mask[shader], 1 << (start_slot + i), image->resource); 2599f464c52Smaya 2607ec681f3Smrg if (!image->resource) { 2617ec681f3Smrg util_copy_image_view(&ctx->images[shader][start_slot+i], NULL); 2627ec681f3Smrg continue; 2637ec681f3Smrg } 2649f464c52Smaya 2657ec681f3Smrg struct panfrost_resource *rsrc = pan_resource(image->resource); 2669f464c52Smaya 2677ec681f3Smrg /* Images don't work with AFBC, since they require pixel-level granularity */ 2687ec681f3Smrg if (drm_is_afbc(rsrc->image.layout.modifier)) { 2697ec681f3Smrg pan_resource_modifier_convert(ctx, rsrc, 2707ec681f3Smrg DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, 2717ec681f3Smrg "Shader image"); 2727ec681f3Smrg } 2739f464c52Smaya 2747ec681f3Smrg util_copy_image_view(&ctx->images[shader][start_slot+i], image); 2759f464c52Smaya } 2769f464c52Smaya 2777ec681f3Smrg /* Unbind start_slot+count...start_slot+count+unbind_num_trailing_slots */ 2787ec681f3Smrg for (int i = 0; i < unbind_num_trailing_slots; i++) { 2797ec681f3Smrg SET_BIT(ctx->image_mask[shader], 1 << (start_slot + count + i), NULL); 2807ec681f3Smrg util_copy_image_view(&ctx->images[shader][start_slot+count+i], NULL); 2817ec681f3Smrg } 2829f464c52Smaya} 2839f464c52Smaya 2849f464c52Smayastatic void 2857ec681f3Smrgpanfrost_bind_vertex_elements_state( 2869f464c52Smaya struct pipe_context *pctx, 2877ec681f3Smrg void *hwcso) 2889f464c52Smaya{ 2899f464c52Smaya struct panfrost_context *ctx = pan_context(pctx); 2907ec681f3Smrg ctx->vertex = hwcso; 2919f464c52Smaya} 2929f464c52Smaya 2937ec681f3Smrgstatic void * 2947ec681f3Smrgpanfrost_create_shader_state( 2959f464c52Smaya struct pipe_context *pctx, 2967ec681f3Smrg const struct pipe_shader_state *cso, 2977ec681f3Smrg enum pipe_shader_type stage) 2989f464c52Smaya{ 2997ec681f3Smrg struct panfrost_shader_variants *so = CALLOC_STRUCT(panfrost_shader_variants); 3007ec681f3Smrg struct panfrost_device *dev = pan_device(pctx->screen); 3017ec681f3Smrg so->base = *cso; 3029f464c52Smaya 3037ec681f3Smrg simple_mtx_init(&so->lock, mtx_plain); 3049f464c52Smaya 3057ec681f3Smrg /* Token deep copy to prevent memory corruption */ 3069f464c52Smaya 3077ec681f3Smrg if (cso->type == PIPE_SHADER_IR_TGSI) 3087ec681f3Smrg so->base.tokens = tgsi_dup_tokens(so->base.tokens); 3099f464c52Smaya 3107ec681f3Smrg /* Precompile for shader-db if we need to */ 3117ec681f3Smrg if (unlikely((dev->debug & PAN_DBG_PRECOMPILE) && cso->type == PIPE_SHADER_IR_NIR)) { 3127ec681f3Smrg struct panfrost_context *ctx = pan_context(pctx); 3139f464c52Smaya 3147ec681f3Smrg struct panfrost_shader_state state = { 0 }; 3159f464c52Smaya 3167ec681f3Smrg panfrost_shader_compile(pctx->screen, 3177ec681f3Smrg &ctx->shaders, &ctx->descs, 3187ec681f3Smrg PIPE_SHADER_IR_NIR, 3197ec681f3Smrg so->base.ir.nir, 3207ec681f3Smrg tgsi_processor_to_shader_stage(stage), 3217ec681f3Smrg &state); 3227ec681f3Smrg } 3239f464c52Smaya 3247ec681f3Smrg return so; 3257ec681f3Smrg} 3269f464c52Smaya 3277ec681f3Smrgstatic void 3287ec681f3Smrgpanfrost_delete_shader_state( 3297ec681f3Smrg struct pipe_context *pctx, 3307ec681f3Smrg void *so) 3317ec681f3Smrg{ 3327ec681f3Smrg struct panfrost_shader_variants *cso = (struct panfrost_shader_variants *) so; 3339f464c52Smaya 3347ec681f3Smrg if (!cso->is_compute && cso->base.type == PIPE_SHADER_IR_NIR) 3357ec681f3Smrg ralloc_free(cso->base.ir.nir); 3369f464c52Smaya 3377ec681f3Smrg if (cso->base.type == PIPE_SHADER_IR_TGSI) 3387ec681f3Smrg tgsi_free_tokens(cso->base.tokens); 3399f464c52Smaya 3407ec681f3Smrg for (unsigned i = 0; i < cso->variant_count; ++i) { 3417ec681f3Smrg struct panfrost_shader_state *shader_state = &cso->variants[i]; 3427ec681f3Smrg panfrost_bo_unreference(shader_state->bin.bo); 3437ec681f3Smrg panfrost_bo_unreference(shader_state->state.bo); 3447ec681f3Smrg panfrost_bo_unreference(shader_state->linkage.bo); 3459f464c52Smaya } 3469f464c52Smaya 3477ec681f3Smrg simple_mtx_destroy(&cso->lock); 3487ec681f3Smrg 3497ec681f3Smrg free(cso->variants); 3507ec681f3Smrg free(so); 3517ec681f3Smrg} 3527ec681f3Smrg 3537ec681f3Smrgstatic void 3547ec681f3Smrgpanfrost_bind_sampler_states( 3557ec681f3Smrg struct pipe_context *pctx, 3567ec681f3Smrg enum pipe_shader_type shader, 3577ec681f3Smrg unsigned start_slot, unsigned num_sampler, 3587ec681f3Smrg void **sampler) 3597ec681f3Smrg{ 3607ec681f3Smrg assert(start_slot == 0); 3619f464c52Smaya 3627ec681f3Smrg struct panfrost_context *ctx = pan_context(pctx); 3637ec681f3Smrg ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_SAMPLER; 3649f464c52Smaya 3657ec681f3Smrg ctx->sampler_count[shader] = sampler ? num_sampler : 0; 3667ec681f3Smrg if (sampler) 3677ec681f3Smrg memcpy(ctx->samplers[shader], sampler, num_sampler * sizeof (void *)); 3687ec681f3Smrg} 3699f464c52Smaya 3707ec681f3Smrgstatic bool 3717ec681f3Smrgpanfrost_variant_matches( 3727ec681f3Smrg struct panfrost_context *ctx, 3737ec681f3Smrg struct panfrost_shader_state *variant, 3747ec681f3Smrg enum pipe_shader_type type) 3757ec681f3Smrg{ 3767ec681f3Smrg if (variant->info.stage == MESA_SHADER_FRAGMENT && 3777ec681f3Smrg variant->info.fs.outputs_read) { 3787ec681f3Smrg struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer; 3799f464c52Smaya 3807ec681f3Smrg unsigned i; 3817ec681f3Smrg BITSET_FOREACH_SET(i, &variant->info.fs.outputs_read, 8) { 3827ec681f3Smrg enum pipe_format fmt = PIPE_FORMAT_R8G8B8A8_UNORM; 3839f464c52Smaya 3847ec681f3Smrg if ((fb->nr_cbufs > i) && fb->cbufs[i]) 3857ec681f3Smrg fmt = fb->cbufs[i]->format; 3869f464c52Smaya 3877ec681f3Smrg if (panfrost_blendable_formats_v6[fmt].internal) 3887ec681f3Smrg fmt = PIPE_FORMAT_NONE; 3899f464c52Smaya 3907ec681f3Smrg if (variant->rt_formats[i] != fmt) 3917ec681f3Smrg return false; 3927ec681f3Smrg } 3937ec681f3Smrg } 3949f464c52Smaya 3957ec681f3Smrg if (variant->info.stage == MESA_SHADER_FRAGMENT && 3967ec681f3Smrg variant->nr_cbufs != ctx->pipe_framebuffer.nr_cbufs) 3977ec681f3Smrg return false; 3989f464c52Smaya 3997ec681f3Smrg /* Otherwise, we're good to go */ 4007ec681f3Smrg return true; 4019f464c52Smaya} 4029f464c52Smaya 4037ec681f3Smrg/** 4047ec681f3Smrg * Fix an uncompiled shader's stream output info, and produce a bitmask 4057ec681f3Smrg * of which VARYING_SLOT_* are captured for stream output. 4067ec681f3Smrg * 4077ec681f3Smrg * Core Gallium stores output->register_index as a "slot" number, where 4087ec681f3Smrg * slots are assigned consecutively to all outputs in info->outputs_written. 4097ec681f3Smrg * This naive packing of outputs doesn't work for us - we too have slots, 4107ec681f3Smrg * but the layout is defined by the VUE map, which we won't have until we 4117ec681f3Smrg * compile a specific shader variant. So, we remap these and simply store 4127ec681f3Smrg * VARYING_SLOT_* in our copy's output->register_index fields. 4137ec681f3Smrg * 4147ec681f3Smrg * We then produce a bitmask of outputs which are used for SO. 4157ec681f3Smrg * 4167ec681f3Smrg * Implementation from iris. 4177ec681f3Smrg */ 4189f464c52Smaya 4197ec681f3Smrgstatic uint64_t 4207ec681f3Smrgupdate_so_info(struct pipe_stream_output_info *so_info, 4217ec681f3Smrg uint64_t outputs_written) 4227ec681f3Smrg{ 4237ec681f3Smrg uint64_t so_outputs = 0; 4247ec681f3Smrg uint8_t reverse_map[64] = {0}; 4257ec681f3Smrg unsigned slot = 0; 4269f464c52Smaya 4277ec681f3Smrg while (outputs_written) 4287ec681f3Smrg reverse_map[slot++] = u_bit_scan64(&outputs_written); 4299f464c52Smaya 4307ec681f3Smrg for (unsigned i = 0; i < so_info->num_outputs; i++) { 4317ec681f3Smrg struct pipe_stream_output *output = &so_info->output[i]; 4329f464c52Smaya 4337ec681f3Smrg /* Map Gallium's condensed "slots" back to real VARYING_SLOT_* enums */ 4347ec681f3Smrg output->register_index = reverse_map[output->register_index]; 4359f464c52Smaya 4367ec681f3Smrg so_outputs |= 1ull << output->register_index; 4377ec681f3Smrg } 4389f464c52Smaya 4397ec681f3Smrg return so_outputs; 4409f464c52Smaya} 4419f464c52Smaya 4429f464c52Smayastatic void 4437ec681f3Smrgpanfrost_bind_shader_state( 4447ec681f3Smrg struct pipe_context *pctx, 4457ec681f3Smrg void *hwcso, 4467ec681f3Smrg enum pipe_shader_type type) 4479f464c52Smaya{ 4489f464c52Smaya struct panfrost_context *ctx = pan_context(pctx); 4497ec681f3Smrg ctx->shader[type] = hwcso; 4509f464c52Smaya 4517ec681f3Smrg ctx->dirty |= PAN_DIRTY_TLS_SIZE; 4527ec681f3Smrg ctx->dirty_shader[type] |= PAN_DIRTY_STAGE_RENDERER; 4539f464c52Smaya 4547ec681f3Smrg if (!hwcso) return; 4559f464c52Smaya 4567ec681f3Smrg /* Match the appropriate variant */ 4579f464c52Smaya 4587ec681f3Smrg signed variant = -1; 4597ec681f3Smrg struct panfrost_shader_variants *variants = (struct panfrost_shader_variants *) hwcso; 4609f464c52Smaya 4617ec681f3Smrg simple_mtx_lock(&variants->lock); 4629f464c52Smaya 4637ec681f3Smrg for (unsigned i = 0; i < variants->variant_count; ++i) { 4647ec681f3Smrg if (panfrost_variant_matches(ctx, &variants->variants[i], type)) { 4657ec681f3Smrg variant = i; 4667ec681f3Smrg break; 4679f464c52Smaya } 4687ec681f3Smrg } 4699f464c52Smaya 4707ec681f3Smrg if (variant == -1) { 4717ec681f3Smrg /* No variant matched, so create a new one */ 4727ec681f3Smrg variant = variants->variant_count++; 4739f464c52Smaya 4747ec681f3Smrg if (variants->variant_count > variants->variant_space) { 4757ec681f3Smrg unsigned old_space = variants->variant_space; 4769f464c52Smaya 4777ec681f3Smrg variants->variant_space *= 2; 4787ec681f3Smrg if (variants->variant_space == 0) 4797ec681f3Smrg variants->variant_space = 1; 4809f464c52Smaya 4817ec681f3Smrg /* Arbitrary limit to stop runaway programs from 4827ec681f3Smrg * creating an unbounded number of shader variants. */ 4837ec681f3Smrg assert(variants->variant_space < 1024); 4849f464c52Smaya 4857ec681f3Smrg unsigned msize = sizeof(struct panfrost_shader_state); 4867ec681f3Smrg variants->variants = realloc(variants->variants, 4877ec681f3Smrg variants->variant_space * msize); 4889f464c52Smaya 4897ec681f3Smrg memset(&variants->variants[old_space], 0, 4907ec681f3Smrg (variants->variant_space - old_space) * msize); 4919f464c52Smaya } 4929f464c52Smaya 4937ec681f3Smrg struct panfrost_shader_state *v = 4947ec681f3Smrg &variants->variants[variant]; 4959f464c52Smaya 4967ec681f3Smrg if (type == PIPE_SHADER_FRAGMENT) { 4977ec681f3Smrg struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer; 4987ec681f3Smrg v->nr_cbufs = fb->nr_cbufs; 4999f464c52Smaya 5007ec681f3Smrg for (unsigned i = 0; i < fb->nr_cbufs; ++i) { 5017ec681f3Smrg enum pipe_format fmt = PIPE_FORMAT_R8G8B8A8_UNORM; 5029f464c52Smaya 5037ec681f3Smrg if ((fb->nr_cbufs > i) && fb->cbufs[i]) 5047ec681f3Smrg fmt = fb->cbufs[i]->format; 5059f464c52Smaya 5067ec681f3Smrg if (panfrost_blendable_formats_v6[fmt].internal) 5077ec681f3Smrg fmt = PIPE_FORMAT_NONE; 5089f464c52Smaya 5097ec681f3Smrg v->rt_formats[i] = fmt; 5109f464c52Smaya } 5119f464c52Smaya } 5129f464c52Smaya } 5139f464c52Smaya 5147ec681f3Smrg /* Select this variant */ 5157ec681f3Smrg variants->active_variant = variant; 5169f464c52Smaya 5177ec681f3Smrg struct panfrost_shader_state *shader_state = &variants->variants[variant]; 5187ec681f3Smrg assert(panfrost_variant_matches(ctx, shader_state, type)); 5199f464c52Smaya 5207ec681f3Smrg /* We finally have a variant, so compile it */ 5219f464c52Smaya 5227ec681f3Smrg if (!shader_state->compiled) { 5237ec681f3Smrg panfrost_shader_compile(ctx->base.screen, 5247ec681f3Smrg &ctx->shaders, &ctx->descs, 5257ec681f3Smrg variants->base.type, 5267ec681f3Smrg variants->base.type == PIPE_SHADER_IR_NIR ? 5277ec681f3Smrg variants->base.ir.nir : 5287ec681f3Smrg variants->base.tokens, 5297ec681f3Smrg tgsi_processor_to_shader_stage(type), 5307ec681f3Smrg shader_state); 5319f464c52Smaya 5327ec681f3Smrg shader_state->compiled = true; 5339f464c52Smaya 5347ec681f3Smrg /* Fixup the stream out information */ 5357ec681f3Smrg shader_state->stream_output = variants->base.stream_output; 5367ec681f3Smrg shader_state->so_mask = 5377ec681f3Smrg update_so_info(&shader_state->stream_output, 5387ec681f3Smrg shader_state->info.outputs_written); 5397ec681f3Smrg } 5409f464c52Smaya 5417ec681f3Smrg /* TODO: it would be more efficient to release the lock before 5427ec681f3Smrg * compiling instead of after, but that can race if thread A compiles a 5437ec681f3Smrg * variant while thread B searches for that same variant */ 5447ec681f3Smrg simple_mtx_unlock(&variants->lock); 5459f464c52Smaya} 5469f464c52Smaya 5477ec681f3Smrgstatic void * 5487ec681f3Smrgpanfrost_create_vs_state(struct pipe_context *pctx, const struct pipe_shader_state *hwcso) 5499f464c52Smaya{ 5507ec681f3Smrg return panfrost_create_shader_state(pctx, hwcso, PIPE_SHADER_VERTEX); 5517ec681f3Smrg} 5529f464c52Smaya 5537ec681f3Smrgstatic void * 5547ec681f3Smrgpanfrost_create_fs_state(struct pipe_context *pctx, const struct pipe_shader_state *hwcso) 5557ec681f3Smrg{ 5567ec681f3Smrg return panfrost_create_shader_state(pctx, hwcso, PIPE_SHADER_FRAGMENT); 5577ec681f3Smrg} 5589f464c52Smaya 5597ec681f3Smrgstatic void 5607ec681f3Smrgpanfrost_bind_vs_state(struct pipe_context *pctx, void *hwcso) 5617ec681f3Smrg{ 5627ec681f3Smrg panfrost_bind_shader_state(pctx, hwcso, PIPE_SHADER_VERTEX); 5639f464c52Smaya} 5649f464c52Smaya 5659f464c52Smayastatic void 5667ec681f3Smrgpanfrost_bind_fs_state(struct pipe_context *pctx, void *hwcso) 5679f464c52Smaya{ 5687ec681f3Smrg panfrost_bind_shader_state(pctx, hwcso, PIPE_SHADER_FRAGMENT); 5697ec681f3Smrg} 5709f464c52Smaya 5717ec681f3Smrgstatic void 5727ec681f3Smrgpanfrost_set_vertex_buffers( 5737ec681f3Smrg struct pipe_context *pctx, 5747ec681f3Smrg unsigned start_slot, 5757ec681f3Smrg unsigned num_buffers, 5767ec681f3Smrg unsigned unbind_num_trailing_slots, 5777ec681f3Smrg bool take_ownership, 5787ec681f3Smrg const struct pipe_vertex_buffer *buffers) 5797ec681f3Smrg{ 5807ec681f3Smrg struct panfrost_context *ctx = pan_context(pctx); 5819f464c52Smaya 5827ec681f3Smrg util_set_vertex_buffers_mask(ctx->vertex_buffers, &ctx->vb_mask, buffers, 5837ec681f3Smrg start_slot, num_buffers, unbind_num_trailing_slots, 5847ec681f3Smrg take_ownership); 5859f464c52Smaya} 5869f464c52Smaya 5879f464c52Smayastatic void 5887ec681f3Smrgpanfrost_set_constant_buffer( 5897ec681f3Smrg struct pipe_context *pctx, 5907ec681f3Smrg enum pipe_shader_type shader, uint index, bool take_ownership, 5917ec681f3Smrg const struct pipe_constant_buffer *buf) 5929f464c52Smaya{ 5937ec681f3Smrg struct panfrost_context *ctx = pan_context(pctx); 5947ec681f3Smrg struct panfrost_constant_buffer *pbuf = &ctx->constant_buffer[shader]; 5959f464c52Smaya 5967ec681f3Smrg util_copy_constant_buffer(&pbuf->cb[index], buf, take_ownership); 5979f464c52Smaya 5987ec681f3Smrg unsigned mask = (1 << index); 5999f464c52Smaya 6007ec681f3Smrg if (unlikely(!buf)) { 6017ec681f3Smrg pbuf->enabled_mask &= ~mask; 6027ec681f3Smrg return; 6039f464c52Smaya } 6047ec681f3Smrg 6057ec681f3Smrg pbuf->enabled_mask |= mask; 6067ec681f3Smrg ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_CONST; 6079f464c52Smaya} 6089f464c52Smaya 6097ec681f3Smrgstatic void 6107ec681f3Smrgpanfrost_set_stencil_ref( 6117ec681f3Smrg struct pipe_context *pctx, 6127ec681f3Smrg const struct pipe_stencil_ref ref) 6139f464c52Smaya{ 6147ec681f3Smrg struct panfrost_context *ctx = pan_context(pctx); 6157ec681f3Smrg ctx->stencil_ref = ref; 6167ec681f3Smrg ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER; 6179f464c52Smaya} 6189f464c52Smaya 6199f464c52Smayastatic void 6207ec681f3Smrgpanfrost_set_sampler_views( 6217ec681f3Smrg struct pipe_context *pctx, 6227ec681f3Smrg enum pipe_shader_type shader, 6237ec681f3Smrg unsigned start_slot, unsigned num_views, 6247ec681f3Smrg unsigned unbind_num_trailing_slots, 6257ec681f3Smrg bool take_ownership, 6267ec681f3Smrg struct pipe_sampler_view **views) 6279f464c52Smaya{ 6287ec681f3Smrg struct panfrost_context *ctx = pan_context(pctx); 6297ec681f3Smrg ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_TEXTURE; 6309f464c52Smaya 6317ec681f3Smrg unsigned new_nr = 0; 6327ec681f3Smrg unsigned i; 6337ec681f3Smrg 6347ec681f3Smrg assert(start_slot == 0); 6357ec681f3Smrg 6367ec681f3Smrg if (!views) 6377ec681f3Smrg num_views = 0; 6389f464c52Smaya 6397ec681f3Smrg for (i = 0; i < num_views; ++i) { 6407ec681f3Smrg if (views[i]) 6417ec681f3Smrg new_nr = i + 1; 6427ec681f3Smrg if (take_ownership) { 6437ec681f3Smrg pipe_sampler_view_reference((struct pipe_sampler_view **)&ctx->sampler_views[shader][i], 6447ec681f3Smrg NULL); 6457ec681f3Smrg ctx->sampler_views[shader][i] = (struct panfrost_sampler_view *)views[i]; 6467ec681f3Smrg } else { 6477ec681f3Smrg pipe_sampler_view_reference((struct pipe_sampler_view **)&ctx->sampler_views[shader][i], 6487ec681f3Smrg views[i]); 6497ec681f3Smrg } 6507ec681f3Smrg } 6519f464c52Smaya 6527ec681f3Smrg for (; i < ctx->sampler_view_count[shader]; i++) { 6537ec681f3Smrg pipe_sampler_view_reference((struct pipe_sampler_view **)&ctx->sampler_views[shader][i], 6547ec681f3Smrg NULL); 6559f464c52Smaya } 6567ec681f3Smrg ctx->sampler_view_count[shader] = new_nr; 6577ec681f3Smrg} 6589f464c52Smaya 6597ec681f3Smrgstatic void 6607ec681f3Smrgpanfrost_set_shader_buffers( 6617ec681f3Smrg struct pipe_context *pctx, 6627ec681f3Smrg enum pipe_shader_type shader, 6637ec681f3Smrg unsigned start, unsigned count, 6647ec681f3Smrg const struct pipe_shader_buffer *buffers, 6657ec681f3Smrg unsigned writable_bitmask) 6667ec681f3Smrg{ 6677ec681f3Smrg struct panfrost_context *ctx = pan_context(pctx); 6689f464c52Smaya 6697ec681f3Smrg util_set_shader_buffers_mask(ctx->ssbo[shader], &ctx->ssbo_mask[shader], 6707ec681f3Smrg buffers, start, count); 6717ec681f3Smrg} 6729f464c52Smaya 6737ec681f3Smrgstatic void 6747ec681f3Smrgpanfrost_set_framebuffer_state(struct pipe_context *pctx, 6757ec681f3Smrg const struct pipe_framebuffer_state *fb) 6767ec681f3Smrg{ 6777ec681f3Smrg struct panfrost_context *ctx = pan_context(pctx); 6789f464c52Smaya 6797ec681f3Smrg util_copy_framebuffer_state(&ctx->pipe_framebuffer, fb); 6807ec681f3Smrg ctx->batch = NULL; 6819f464c52Smaya 6827ec681f3Smrg /* Hot draw call path needs the mask of active render targets */ 6837ec681f3Smrg ctx->fb_rt_mask = 0; 6849f464c52Smaya 6857ec681f3Smrg for (unsigned i = 0; i < ctx->pipe_framebuffer.nr_cbufs; ++i) { 6867ec681f3Smrg if (ctx->pipe_framebuffer.cbufs[i]) 6877ec681f3Smrg ctx->fb_rt_mask |= BITFIELD_BIT(i); 6887ec681f3Smrg } 6899f464c52Smaya 6907ec681f3Smrg /* We may need to generate a new variant if the fragment shader is 6917ec681f3Smrg * keyed to the framebuffer format or render target count */ 6927ec681f3Smrg struct panfrost_shader_variants *fs = ctx->shader[PIPE_SHADER_FRAGMENT]; 6939f464c52Smaya 6947ec681f3Smrg if (fs && fs->variant_count) 6957ec681f3Smrg ctx->base.bind_fs_state(&ctx->base, fs); 6969f464c52Smaya} 6979f464c52Smaya 6989f464c52Smayastatic void 6997ec681f3Smrgpanfrost_bind_depth_stencil_state(struct pipe_context *pipe, 7007ec681f3Smrg void *cso) 7019f464c52Smaya{ 7027ec681f3Smrg struct panfrost_context *ctx = pan_context(pipe); 7037ec681f3Smrg ctx->depth_stencil = cso; 7047ec681f3Smrg ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER; 7059f464c52Smaya} 7069f464c52Smaya 7079f464c52Smayastatic void 7089f464c52Smayapanfrost_set_sample_mask(struct pipe_context *pipe, 7099f464c52Smaya unsigned sample_mask) 7109f464c52Smaya{ 7117ec681f3Smrg struct panfrost_context *ctx = pan_context(pipe); 7127ec681f3Smrg ctx->sample_mask = sample_mask; 7137ec681f3Smrg ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER; 7147ec681f3Smrg} 7157ec681f3Smrg 7167ec681f3Smrgstatic void 7177ec681f3Smrgpanfrost_set_min_samples(struct pipe_context *pipe, 7187ec681f3Smrg unsigned min_samples) 7197ec681f3Smrg{ 7207ec681f3Smrg struct panfrost_context *ctx = pan_context(pipe); 7217ec681f3Smrg ctx->min_samples = min_samples; 7227ec681f3Smrg ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER; 7239f464c52Smaya} 7249f464c52Smaya 7259f464c52Smayastatic void 7269f464c52Smayapanfrost_set_clip_state(struct pipe_context *pipe, 7279f464c52Smaya const struct pipe_clip_state *clip) 7289f464c52Smaya{ 7299f464c52Smaya //struct panfrost_context *panfrost = pan_context(pipe); 7309f464c52Smaya} 7319f464c52Smaya 7329f464c52Smayastatic void 7339f464c52Smayapanfrost_set_viewport_states(struct pipe_context *pipe, 7349f464c52Smaya unsigned start_slot, 7359f464c52Smaya unsigned num_viewports, 7369f464c52Smaya const struct pipe_viewport_state *viewports) 7379f464c52Smaya{ 7389f464c52Smaya struct panfrost_context *ctx = pan_context(pipe); 7399f464c52Smaya 7409f464c52Smaya assert(start_slot == 0); 7419f464c52Smaya assert(num_viewports == 1); 7429f464c52Smaya 7439f464c52Smaya ctx->pipe_viewport = *viewports; 7447ec681f3Smrg ctx->dirty |= PAN_DIRTY_VIEWPORT; 7459f464c52Smaya} 7469f464c52Smaya 7479f464c52Smayastatic void 7489f464c52Smayapanfrost_set_scissor_states(struct pipe_context *pipe, 7499f464c52Smaya unsigned start_slot, 7509f464c52Smaya unsigned num_scissors, 7519f464c52Smaya const struct pipe_scissor_state *scissors) 7529f464c52Smaya{ 7539f464c52Smaya struct panfrost_context *ctx = pan_context(pipe); 7549f464c52Smaya 7559f464c52Smaya assert(start_slot == 0); 7569f464c52Smaya assert(num_scissors == 1); 7579f464c52Smaya 7589f464c52Smaya ctx->scissor = *scissors; 7597ec681f3Smrg ctx->dirty |= PAN_DIRTY_SCISSOR; 7609f464c52Smaya} 7619f464c52Smaya 7629f464c52Smayastatic void 7639f464c52Smayapanfrost_set_polygon_stipple(struct pipe_context *pipe, 7649f464c52Smaya const struct pipe_poly_stipple *stipple) 7659f464c52Smaya{ 7669f464c52Smaya //struct panfrost_context *panfrost = pan_context(pipe); 7679f464c52Smaya} 7689f464c52Smaya 7699f464c52Smayastatic void 7709f464c52Smayapanfrost_set_active_query_state(struct pipe_context *pipe, 7717ec681f3Smrg bool enable) 7729f464c52Smaya{ 7737ec681f3Smrg struct panfrost_context *ctx = pan_context(pipe); 7747ec681f3Smrg ctx->active_queries = enable; 7757ec681f3Smrg ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER; 7767ec681f3Smrg} 7777ec681f3Smrg 7787ec681f3Smrgstatic void 7797ec681f3Smrgpanfrost_render_condition(struct pipe_context *pipe, 7807ec681f3Smrg struct pipe_query *query, 7817ec681f3Smrg bool condition, 7827ec681f3Smrg enum pipe_render_cond_flag mode) 7837ec681f3Smrg{ 7847ec681f3Smrg struct panfrost_context *ctx = pan_context(pipe); 7857ec681f3Smrg 7867ec681f3Smrg ctx->cond_query = (struct panfrost_query *)query; 7877ec681f3Smrg ctx->cond_cond = condition; 7887ec681f3Smrg ctx->cond_mode = mode; 7899f464c52Smaya} 7909f464c52Smaya 7919f464c52Smayastatic void 7929f464c52Smayapanfrost_destroy(struct pipe_context *pipe) 7939f464c52Smaya{ 7949f464c52Smaya struct panfrost_context *panfrost = pan_context(pipe); 7957ec681f3Smrg 7967ec681f3Smrg _mesa_hash_table_destroy(panfrost->writers, NULL); 7979f464c52Smaya 7989f464c52Smaya if (panfrost->blitter) 7999f464c52Smaya util_blitter_destroy(panfrost->blitter); 8009f464c52Smaya 8017ec681f3Smrg util_unreference_framebuffer_state(&panfrost->pipe_framebuffer); 8027ec681f3Smrg u_upload_destroy(pipe->stream_uploader); 8037ec681f3Smrg 8047ec681f3Smrg panfrost_pool_cleanup(&panfrost->descs); 8057ec681f3Smrg panfrost_pool_cleanup(&panfrost->shaders); 8067ec681f3Smrg 8077ec681f3Smrg ralloc_free(pipe); 8089f464c52Smaya} 8099f464c52Smaya 8109f464c52Smayastatic struct pipe_query * 8117ec681f3Smrgpanfrost_create_query(struct pipe_context *pipe, 8127ec681f3Smrg unsigned type, 8137ec681f3Smrg unsigned index) 8149f464c52Smaya{ 8157ec681f3Smrg struct panfrost_query *q = rzalloc(pipe, struct panfrost_query); 8169f464c52Smaya 8179f464c52Smaya q->type = type; 8189f464c52Smaya q->index = index; 8199f464c52Smaya 8209f464c52Smaya return (struct pipe_query *) q; 8219f464c52Smaya} 8229f464c52Smaya 8239f464c52Smayastatic void 8249f464c52Smayapanfrost_destroy_query(struct pipe_context *pipe, struct pipe_query *q) 8259f464c52Smaya{ 8267ec681f3Smrg struct panfrost_query *query = (struct panfrost_query *) q; 8277ec681f3Smrg 8287ec681f3Smrg if (query->rsrc) 8297ec681f3Smrg pipe_resource_reference(&query->rsrc, NULL); 8307ec681f3Smrg 8317ec681f3Smrg ralloc_free(q); 8329f464c52Smaya} 8339f464c52Smaya 8347ec681f3Smrgstatic bool 8359f464c52Smayapanfrost_begin_query(struct pipe_context *pipe, struct pipe_query *q) 8369f464c52Smaya{ 8379f464c52Smaya struct panfrost_context *ctx = pan_context(pipe); 8387ec681f3Smrg struct panfrost_device *dev = pan_device(ctx->base.screen); 8399f464c52Smaya struct panfrost_query *query = (struct panfrost_query *) q; 8409f464c52Smaya 8419f464c52Smaya switch (query->type) { 8427ec681f3Smrg case PIPE_QUERY_OCCLUSION_COUNTER: 8437ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE: 8447ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: { 8457ec681f3Smrg unsigned size = sizeof(uint64_t) * dev->core_count; 8467ec681f3Smrg 8477ec681f3Smrg /* Allocate a resource for the query results to be stored */ 8487ec681f3Smrg if (!query->rsrc) { 8497ec681f3Smrg query->rsrc = pipe_buffer_create(ctx->base.screen, 8507ec681f3Smrg PIPE_BIND_QUERY_BUFFER, 0, size); 8517ec681f3Smrg } 8529f464c52Smaya 8537ec681f3Smrg /* Default to 0 if nothing at all drawn. */ 8547ec681f3Smrg uint8_t *zeroes = alloca(size); 8557ec681f3Smrg memset(zeroes, 0, size); 8567ec681f3Smrg pipe_buffer_write(pipe, query->rsrc, 0, size, zeroes); 8579f464c52Smaya 8587ec681f3Smrg query->msaa = (ctx->pipe_framebuffer.samples > 1); 8597ec681f3Smrg ctx->occlusion_query = query; 8607ec681f3Smrg ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER; 8617ec681f3Smrg break; 8627ec681f3Smrg } 8639f464c52Smaya 8647ec681f3Smrg /* Geometry statistics are computed in the driver. XXX: geom/tess 8657ec681f3Smrg * shaders.. */ 8667ec681f3Smrg 8677ec681f3Smrg case PIPE_QUERY_PRIMITIVES_GENERATED: 8687ec681f3Smrg query->start = ctx->prims_generated; 8697ec681f3Smrg break; 8707ec681f3Smrg case PIPE_QUERY_PRIMITIVES_EMITTED: 8717ec681f3Smrg query->start = ctx->tf_prims_generated; 8727ec681f3Smrg break; 8737ec681f3Smrg 8747ec681f3Smrg default: 8757ec681f3Smrg /* TODO: timestamp queries, etc? */ 8767ec681f3Smrg break; 8779f464c52Smaya } 8789f464c52Smaya 8799f464c52Smaya return true; 8809f464c52Smaya} 8819f464c52Smaya 8829f464c52Smayastatic bool 8839f464c52Smayapanfrost_end_query(struct pipe_context *pipe, struct pipe_query *q) 8849f464c52Smaya{ 8859f464c52Smaya struct panfrost_context *ctx = pan_context(pipe); 8867ec681f3Smrg struct panfrost_query *query = (struct panfrost_query *) q; 8877ec681f3Smrg 8887ec681f3Smrg switch (query->type) { 8897ec681f3Smrg case PIPE_QUERY_OCCLUSION_COUNTER: 8907ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE: 8917ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 8927ec681f3Smrg ctx->occlusion_query = NULL; 8937ec681f3Smrg ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= PAN_DIRTY_STAGE_RENDERER; 8947ec681f3Smrg break; 8957ec681f3Smrg case PIPE_QUERY_PRIMITIVES_GENERATED: 8967ec681f3Smrg query->end = ctx->prims_generated; 8977ec681f3Smrg break; 8987ec681f3Smrg case PIPE_QUERY_PRIMITIVES_EMITTED: 8997ec681f3Smrg query->end = ctx->tf_prims_generated; 9007ec681f3Smrg break; 9017ec681f3Smrg } 9027ec681f3Smrg 9039f464c52Smaya return true; 9049f464c52Smaya} 9059f464c52Smaya 9067ec681f3Smrgstatic bool 9077ec681f3Smrgpanfrost_get_query_result(struct pipe_context *pipe, 9089f464c52Smaya struct pipe_query *q, 9097ec681f3Smrg bool wait, 9109f464c52Smaya union pipe_query_result *vresult) 9119f464c52Smaya{ 9129f464c52Smaya struct panfrost_query *query = (struct panfrost_query *) q; 9137ec681f3Smrg struct panfrost_context *ctx = pan_context(pipe); 9147ec681f3Smrg struct panfrost_device *dev = pan_device(ctx->base.screen); 9157ec681f3Smrg struct panfrost_resource *rsrc = pan_resource(query->rsrc); 9169f464c52Smaya 9177ec681f3Smrg switch (query->type) { 9187ec681f3Smrg case PIPE_QUERY_OCCLUSION_COUNTER: 9197ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE: 9207ec681f3Smrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 9217ec681f3Smrg panfrost_flush_writer(ctx, rsrc, "Occlusion query"); 9227ec681f3Smrg panfrost_bo_wait(rsrc->image.data.bo, INT64_MAX, false); 9239f464c52Smaya 9247ec681f3Smrg /* Read back the query results */ 9257ec681f3Smrg uint64_t *result = (uint64_t *) rsrc->image.data.bo->ptr.cpu; 9269f464c52Smaya 9277ec681f3Smrg if (query->type == PIPE_QUERY_OCCLUSION_COUNTER) { 9287ec681f3Smrg uint64_t passed = 0; 9297ec681f3Smrg for (int i = 0; i < dev->core_count; ++i) 9307ec681f3Smrg passed += result[i]; 9319f464c52Smaya 9327ec681f3Smrg if (!pan_is_bifrost(dev) && !query->msaa) 9337ec681f3Smrg passed /= 4; 9347ec681f3Smrg 9357ec681f3Smrg vresult->u64 = passed; 9367ec681f3Smrg } else { 9377ec681f3Smrg vresult->b = !!result[0]; 9389f464c52Smaya } 9397ec681f3Smrg 9407ec681f3Smrg break; 9417ec681f3Smrg 9427ec681f3Smrg case PIPE_QUERY_PRIMITIVES_GENERATED: 9437ec681f3Smrg case PIPE_QUERY_PRIMITIVES_EMITTED: 9447ec681f3Smrg panfrost_flush_all_batches(ctx, "Primitive count query"); 9457ec681f3Smrg vresult->u64 = query->end - query->start; 9467ec681f3Smrg break; 9477ec681f3Smrg 9487ec681f3Smrg default: 9497ec681f3Smrg /* TODO: more queries */ 9507ec681f3Smrg break; 9519f464c52Smaya } 9529f464c52Smaya 9539f464c52Smaya return true; 9549f464c52Smaya} 9559f464c52Smaya 9567ec681f3Smrgbool 9577ec681f3Smrgpanfrost_render_condition_check(struct panfrost_context *ctx) 9587ec681f3Smrg{ 9597ec681f3Smrg if (!ctx->cond_query) 9607ec681f3Smrg return true; 9617ec681f3Smrg 9627ec681f3Smrg perf_debug_ctx(ctx, "Implementing conditional rendering on the CPU"); 9637ec681f3Smrg 9647ec681f3Smrg union pipe_query_result res = { 0 }; 9657ec681f3Smrg bool wait = 9667ec681f3Smrg ctx->cond_mode != PIPE_RENDER_COND_NO_WAIT && 9677ec681f3Smrg ctx->cond_mode != PIPE_RENDER_COND_BY_REGION_NO_WAIT; 9687ec681f3Smrg 9697ec681f3Smrg struct pipe_query *pq = (struct pipe_query *)ctx->cond_query; 9707ec681f3Smrg 9717ec681f3Smrg if (panfrost_get_query_result(&ctx->base, pq, wait, &res)) 9727ec681f3Smrg return res.u64 != ctx->cond_cond; 9737ec681f3Smrg 9747ec681f3Smrg return true; 9757ec681f3Smrg} 9767ec681f3Smrg 9779f464c52Smayastatic struct pipe_stream_output_target * 9789f464c52Smayapanfrost_create_stream_output_target(struct pipe_context *pctx, 9797ec681f3Smrg struct pipe_resource *prsc, 9807ec681f3Smrg unsigned buffer_offset, 9817ec681f3Smrg unsigned buffer_size) 9829f464c52Smaya{ 9839f464c52Smaya struct pipe_stream_output_target *target; 9849f464c52Smaya 9857ec681f3Smrg target = &rzalloc(pctx, struct panfrost_streamout_target)->base; 9869f464c52Smaya 9879f464c52Smaya if (!target) 9889f464c52Smaya return NULL; 9899f464c52Smaya 9909f464c52Smaya pipe_reference_init(&target->reference, 1); 9919f464c52Smaya pipe_resource_reference(&target->buffer, prsc); 9929f464c52Smaya 9939f464c52Smaya target->context = pctx; 9949f464c52Smaya target->buffer_offset = buffer_offset; 9959f464c52Smaya target->buffer_size = buffer_size; 9969f464c52Smaya 9979f464c52Smaya return target; 9989f464c52Smaya} 9999f464c52Smaya 10009f464c52Smayastatic void 10019f464c52Smayapanfrost_stream_output_target_destroy(struct pipe_context *pctx, 10027ec681f3Smrg struct pipe_stream_output_target *target) 10039f464c52Smaya{ 10049f464c52Smaya pipe_resource_reference(&target->buffer, NULL); 10057ec681f3Smrg ralloc_free(target); 10069f464c52Smaya} 10079f464c52Smaya 10089f464c52Smayastatic void 10099f464c52Smayapanfrost_set_stream_output_targets(struct pipe_context *pctx, 10107ec681f3Smrg unsigned num_targets, 10117ec681f3Smrg struct pipe_stream_output_target **targets, 10127ec681f3Smrg const unsigned *offsets) 10139f464c52Smaya{ 10147ec681f3Smrg struct panfrost_context *ctx = pan_context(pctx); 10157ec681f3Smrg struct panfrost_streamout *so = &ctx->streamout; 10169f464c52Smaya 10177ec681f3Smrg assert(num_targets <= ARRAY_SIZE(so->targets)); 10189f464c52Smaya 10197ec681f3Smrg for (unsigned i = 0; i < num_targets; i++) { 10207ec681f3Smrg if (offsets[i] != -1) 10217ec681f3Smrg pan_so_target(targets[i])->offset = offsets[i]; 10229f464c52Smaya 10237ec681f3Smrg pipe_so_target_reference(&so->targets[i], targets[i]); 10249f464c52Smaya } 10259f464c52Smaya 10267ec681f3Smrg for (unsigned i = 0; i < so->num_targets; i++) 10277ec681f3Smrg pipe_so_target_reference(&so->targets[i], NULL); 10289f464c52Smaya 10297ec681f3Smrg so->num_targets = num_targets; 10309f464c52Smaya} 10319f464c52Smaya 10329f464c52Smayastruct pipe_context * 10339f464c52Smayapanfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags) 10349f464c52Smaya{ 10357ec681f3Smrg struct panfrost_context *ctx = rzalloc(screen, struct panfrost_context); 10369f464c52Smaya struct pipe_context *gallium = (struct pipe_context *) ctx; 10377ec681f3Smrg struct panfrost_device *dev = pan_device(screen); 10389f464c52Smaya 10399f464c52Smaya gallium->screen = screen; 10409f464c52Smaya 10419f464c52Smaya gallium->destroy = panfrost_destroy; 10429f464c52Smaya 10439f464c52Smaya gallium->set_framebuffer_state = panfrost_set_framebuffer_state; 10449f464c52Smaya 10459f464c52Smaya gallium->flush = panfrost_flush; 10469f464c52Smaya gallium->clear = panfrost_clear; 10477ec681f3Smrg gallium->texture_barrier = panfrost_texture_barrier; 10487ec681f3Smrg gallium->set_frontend_noop = panfrost_set_frontend_noop; 10499f464c52Smaya 10509f464c52Smaya gallium->set_vertex_buffers = panfrost_set_vertex_buffers; 10519f464c52Smaya gallium->set_constant_buffer = panfrost_set_constant_buffer; 10527ec681f3Smrg gallium->set_shader_buffers = panfrost_set_shader_buffers; 10537ec681f3Smrg gallium->set_shader_images = panfrost_set_shader_images; 10549f464c52Smaya 10559f464c52Smaya gallium->set_stencil_ref = panfrost_set_stencil_ref; 10569f464c52Smaya 10579f464c52Smaya gallium->set_sampler_views = panfrost_set_sampler_views; 10589f464c52Smaya 10599f464c52Smaya gallium->bind_rasterizer_state = panfrost_bind_rasterizer_state; 10609f464c52Smaya gallium->delete_rasterizer_state = panfrost_generic_cso_delete; 10619f464c52Smaya 10629f464c52Smaya gallium->bind_vertex_elements_state = panfrost_bind_vertex_elements_state; 10637ec681f3Smrg gallium->delete_vertex_elements_state = panfrost_generic_cso_delete; 10649f464c52Smaya 10657ec681f3Smrg gallium->create_fs_state = panfrost_create_fs_state; 10669f464c52Smaya gallium->delete_fs_state = panfrost_delete_shader_state; 10679f464c52Smaya gallium->bind_fs_state = panfrost_bind_fs_state; 10689f464c52Smaya 10697ec681f3Smrg gallium->create_vs_state = panfrost_create_vs_state; 10709f464c52Smaya gallium->delete_vs_state = panfrost_delete_shader_state; 10719f464c52Smaya gallium->bind_vs_state = panfrost_bind_vs_state; 10729f464c52Smaya 10739f464c52Smaya gallium->delete_sampler_state = panfrost_generic_cso_delete; 10749f464c52Smaya gallium->bind_sampler_states = panfrost_bind_sampler_states; 10759f464c52Smaya 10769f464c52Smaya gallium->bind_depth_stencil_alpha_state = panfrost_bind_depth_stencil_state; 10777ec681f3Smrg gallium->delete_depth_stencil_alpha_state = panfrost_generic_cso_delete; 10789f464c52Smaya 10799f464c52Smaya gallium->set_sample_mask = panfrost_set_sample_mask; 10807ec681f3Smrg gallium->set_min_samples = panfrost_set_min_samples; 10819f464c52Smaya 10829f464c52Smaya gallium->set_clip_state = panfrost_set_clip_state; 10839f464c52Smaya gallium->set_viewport_states = panfrost_set_viewport_states; 10849f464c52Smaya gallium->set_scissor_states = panfrost_set_scissor_states; 10859f464c52Smaya gallium->set_polygon_stipple = panfrost_set_polygon_stipple; 10869f464c52Smaya gallium->set_active_query_state = panfrost_set_active_query_state; 10877ec681f3Smrg gallium->render_condition = panfrost_render_condition; 10889f464c52Smaya 10899f464c52Smaya gallium->create_query = panfrost_create_query; 10909f464c52Smaya gallium->destroy_query = panfrost_destroy_query; 10919f464c52Smaya gallium->begin_query = panfrost_begin_query; 10929f464c52Smaya gallium->end_query = panfrost_end_query; 10939f464c52Smaya gallium->get_query_result = panfrost_get_query_result; 10949f464c52Smaya 10959f464c52Smaya gallium->create_stream_output_target = panfrost_create_stream_output_target; 10969f464c52Smaya gallium->stream_output_target_destroy = panfrost_stream_output_target_destroy; 10979f464c52Smaya gallium->set_stream_output_targets = panfrost_set_stream_output_targets; 10989f464c52Smaya 10997ec681f3Smrg gallium->bind_blend_state = panfrost_bind_blend_state; 11007ec681f3Smrg gallium->delete_blend_state = panfrost_generic_cso_delete; 11019f464c52Smaya 11027ec681f3Smrg gallium->set_blend_color = panfrost_set_blend_color; 11037ec681f3Smrg 11047ec681f3Smrg pan_screen(screen)->vtbl.context_init(gallium); 11059f464c52Smaya 11067ec681f3Smrg panfrost_resource_context_init(gallium); 11077ec681f3Smrg panfrost_compute_context_init(gallium); 11089f464c52Smaya 11099f464c52Smaya gallium->stream_uploader = u_upload_create_default(gallium); 11109f464c52Smaya gallium->const_uploader = gallium->stream_uploader; 11119f464c52Smaya 11127ec681f3Smrg panfrost_pool_init(&ctx->descs, ctx, dev, 11137ec681f3Smrg 0, 4096, "Descriptors", true, false); 11149f464c52Smaya 11157ec681f3Smrg panfrost_pool_init(&ctx->shaders, ctx, dev, 11167ec681f3Smrg PAN_BO_EXECUTE, 4096, "Shaders", true, false); 11179f464c52Smaya 11189f464c52Smaya ctx->blitter = util_blitter_create(gallium); 11197ec681f3Smrg 11207ec681f3Smrg ctx->writers = _mesa_hash_table_create(gallium, _mesa_hash_pointer, 11217ec681f3Smrg _mesa_key_pointer_equal); 11227ec681f3Smrg 11239f464c52Smaya assert(ctx->blitter); 11249f464c52Smaya 11259f464c52Smaya /* Prepare for render! */ 11269f464c52Smaya 11277ec681f3Smrg /* By default mask everything on */ 11287ec681f3Smrg ctx->sample_mask = ~0; 11297ec681f3Smrg ctx->active_queries = true; 11307ec681f3Smrg 11317ec681f3Smrg int ASSERTED ret; 11327ec681f3Smrg 11337ec681f3Smrg /* Create a syncobj in a signaled state. Will be updated to point to the 11347ec681f3Smrg * last queued job out_sync every time we submit a new job. 11357ec681f3Smrg */ 11367ec681f3Smrg ret = drmSyncobjCreate(dev->fd, DRM_SYNCOBJ_CREATE_SIGNALED, &ctx->syncobj); 11377ec681f3Smrg assert(!ret && ctx->syncobj); 11389f464c52Smaya 11399f464c52Smaya return gallium; 11409f464c52Smaya} 1141