1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2013 Rob Clark <robclark@freedesktop.org> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "pipe/p_state.h" 28bf215546Sopenharmony_ci#include "util/format/u_format.h" 29bf215546Sopenharmony_ci#include "util/u_memory.h" 30bf215546Sopenharmony_ci#include "util/u_prim.h" 31bf215546Sopenharmony_ci#include "util/u_string.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "freedreno_resource.h" 34bf215546Sopenharmony_ci#include "freedreno_state.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include "fd3_context.h" 37bf215546Sopenharmony_ci#include "fd3_draw.h" 38bf215546Sopenharmony_ci#include "fd3_emit.h" 39bf215546Sopenharmony_ci#include "fd3_format.h" 40bf215546Sopenharmony_ci#include "fd3_program.h" 41bf215546Sopenharmony_ci#include "fd3_zsa.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistatic inline uint32_t 44bf215546Sopenharmony_ciadd_sat(uint32_t a, int32_t b) 45bf215546Sopenharmony_ci{ 46bf215546Sopenharmony_ci int64_t ret = (uint64_t)a + (int64_t)b; 47bf215546Sopenharmony_ci if (ret > ~0U) 48bf215546Sopenharmony_ci return ~0U; 49bf215546Sopenharmony_ci if (ret < 0) 50bf215546Sopenharmony_ci return 0; 51bf215546Sopenharmony_ci return (uint32_t)ret; 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_cistatic void 55bf215546Sopenharmony_cidraw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, 56bf215546Sopenharmony_ci struct fd3_emit *emit, unsigned index_offset) assert_dt 57bf215546Sopenharmony_ci{ 58bf215546Sopenharmony_ci const struct pipe_draw_info *info = emit->info; 59bf215546Sopenharmony_ci enum pc_di_primtype primtype = ctx->screen->primtypes[info->mode]; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci fd3_emit_state(ctx, ring, emit); 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci if (emit->dirty & (FD_DIRTY_VTXBUF | FD_DIRTY_VTXSTATE)) 64bf215546Sopenharmony_ci fd3_emit_vertex_bufs(ring, emit); 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci OUT_PKT0(ring, REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL, 1); 67bf215546Sopenharmony_ci OUT_RING(ring, 0x0000000b); /* PC_VERTEX_REUSE_BLOCK_CNTL */ 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4); 70bf215546Sopenharmony_ci OUT_RING(ring, info->index_bounds_valid 71bf215546Sopenharmony_ci ? add_sat(info->min_index, 72bf215546Sopenharmony_ci info->index_size ? emit->draw->index_bias : 0) 73bf215546Sopenharmony_ci : 0); /* VFD_INDEX_MIN */ 74bf215546Sopenharmony_ci OUT_RING(ring, info->index_bounds_valid 75bf215546Sopenharmony_ci ? add_sat(info->max_index, 76bf215546Sopenharmony_ci info->index_size ? emit->draw->index_bias : 0) 77bf215546Sopenharmony_ci : ~0); /* VFD_INDEX_MAX */ 78bf215546Sopenharmony_ci OUT_RING(ring, info->start_instance); /* VFD_INSTANCEID_OFFSET */ 79bf215546Sopenharmony_ci OUT_RING(ring, info->index_size ? emit->draw->index_bias 80bf215546Sopenharmony_ci : emit->draw->start); /* VFD_INDEX_OFFSET */ 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci OUT_PKT0(ring, REG_A3XX_PC_RESTART_INDEX, 1); 83bf215546Sopenharmony_ci OUT_RING(ring, info->primitive_restart ? /* PC_RESTART_INDEX */ 84bf215546Sopenharmony_ci info->restart_index 85bf215546Sopenharmony_ci : 0xffffffff); 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci /* points + psize -> spritelist: */ 88bf215546Sopenharmony_ci if (ctx->rasterizer->point_size_per_vertex && 89bf215546Sopenharmony_ci fd3_emit_get_vp(emit)->writes_psize && (info->mode == PIPE_PRIM_POINTS)) 90bf215546Sopenharmony_ci primtype = DI_PT_POINTLIST_PSIZE; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci fd_draw_emit(ctx->batch, ring, primtype, 93bf215546Sopenharmony_ci emit->binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY, info, 94bf215546Sopenharmony_ci emit->draw, index_offset); 95bf215546Sopenharmony_ci} 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_cistatic bool 98bf215546Sopenharmony_cifd3_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, 99bf215546Sopenharmony_ci unsigned drawid_offset, 100bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 101bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw, 102bf215546Sopenharmony_ci unsigned index_offset) in_dt 103bf215546Sopenharmony_ci{ 104bf215546Sopenharmony_ci struct fd3_emit emit = { 105bf215546Sopenharmony_ci .debug = &ctx->debug, 106bf215546Sopenharmony_ci .vtx = &ctx->vtx, 107bf215546Sopenharmony_ci .info = info, 108bf215546Sopenharmony_ci .drawid_offset = drawid_offset, 109bf215546Sopenharmony_ci .indirect = indirect, 110bf215546Sopenharmony_ci .draw = draw, 111bf215546Sopenharmony_ci .key = { 112bf215546Sopenharmony_ci .vs = ctx->prog.vs, 113bf215546Sopenharmony_ci .fs = ctx->prog.fs, 114bf215546Sopenharmony_ci }, 115bf215546Sopenharmony_ci .rasterflat = ctx->rasterizer->flatshade, 116bf215546Sopenharmony_ci .sprite_coord_enable = ctx->rasterizer->sprite_coord_enable, 117bf215546Sopenharmony_ci .sprite_coord_mode = ctx->rasterizer->sprite_coord_mode, 118bf215546Sopenharmony_ci }; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci if (info->mode != PIPE_PRIM_MAX && !indirect && !info->primitive_restart && 121bf215546Sopenharmony_ci !u_trim_pipe_prim(info->mode, (unsigned *)&draw->count)) 122bf215546Sopenharmony_ci return false; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci if (fd3_needs_manual_clipping(ir3_get_shader(ctx->prog.vs), ctx->rasterizer)) 125bf215546Sopenharmony_ci emit.key.key.ucp_enables = ctx->rasterizer->clip_plane_enable; 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci ir3_fixup_shader_state(&ctx->base, &emit.key.key); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci unsigned dirty = ctx->dirty; 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci emit.prog = fd3_program_state( 132bf215546Sopenharmony_ci ir3_cache_lookup(ctx->shader_cache, &emit.key, &ctx->debug)); 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci /* bail if compile failed: */ 135bf215546Sopenharmony_ci if (!emit.prog) 136bf215546Sopenharmony_ci return false; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci const struct ir3_shader_variant *vp = fd3_emit_get_vp(&emit); 139bf215546Sopenharmony_ci const struct ir3_shader_variant *fp = fd3_emit_get_fp(&emit); 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci ir3_update_max_tf_vtx(ctx, vp); 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci /* do regular pass first: */ 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci if (unlikely(ctx->stats_users > 0)) { 146bf215546Sopenharmony_ci ctx->stats.vs_regs += ir3_shader_halfregs(vp); 147bf215546Sopenharmony_ci ctx->stats.fs_regs += ir3_shader_halfregs(fp); 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci emit.binning_pass = false; 151bf215546Sopenharmony_ci emit.dirty = dirty; 152bf215546Sopenharmony_ci draw_impl(ctx, ctx->batch->draw, &emit, index_offset); 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci /* and now binning pass: */ 155bf215546Sopenharmony_ci emit.binning_pass = true; 156bf215546Sopenharmony_ci emit.dirty = dirty & ~(FD_DIRTY_BLEND); 157bf215546Sopenharmony_ci emit.vs = NULL; /* we changed key so need to refetch vs */ 158bf215546Sopenharmony_ci emit.fs = NULL; 159bf215546Sopenharmony_ci draw_impl(ctx, ctx->batch->binning, &emit, index_offset); 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci fd_context_all_clean(ctx); 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci return true; 164bf215546Sopenharmony_ci} 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_civoid 167bf215546Sopenharmony_cifd3_draw_init(struct pipe_context *pctx) disable_thread_safety_analysis 168bf215546Sopenharmony_ci{ 169bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 170bf215546Sopenharmony_ci ctx->draw_vbo = fd3_draw_vbo; 171bf215546Sopenharmony_ci} 172