Path: blob/21.2-virgl/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c
4574 views
/*1* Copyright (C) 2012 Rob Clark <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*22* Authors:23* Rob Clark <[email protected]>24*/2526#include "pipe/p_state.h"27#include "util/u_inlines.h"28#include "util/u_memory.h"29#include "util/u_string.h"3031#include "freedreno_draw.h"32#include "freedreno_resource.h"33#include "freedreno_state.h"3435#include "ir2/instr-a2xx.h"36#include "fd2_context.h"37#include "fd2_draw.h"38#include "fd2_emit.h"39#include "fd2_gmem.h"40#include "fd2_program.h"41#include "fd2_util.h"42#include "fd2_zsa.h"4344static uint32_t45fmt2swap(enum pipe_format format)46{47switch (format) {48case PIPE_FORMAT_B8G8R8A8_UNORM:49case PIPE_FORMAT_B8G8R8X8_UNORM:50case PIPE_FORMAT_B5G6R5_UNORM:51case PIPE_FORMAT_B5G5R5A1_UNORM:52case PIPE_FORMAT_B5G5R5X1_UNORM:53case PIPE_FORMAT_B4G4R4A4_UNORM:54case PIPE_FORMAT_B4G4R4X4_UNORM:55case PIPE_FORMAT_B2G3R3_UNORM:56return 1;57default:58return 0;59}60}6162static bool63use_hw_binning(struct fd_batch *batch)64{65const struct fd_gmem_stateobj *gmem = batch->gmem_state;6667/* we hardcoded a limit of 8 "pipes", we can increase this limit68* at the cost of a slightly larger command stream69* however very few cases will need more than 870* gmem->num_vsc_pipes == 0 means empty batch (TODO: does it still happen?)71*/72if (gmem->num_vsc_pipes > 8 || !gmem->num_vsc_pipes)73return false;7475/* only a20x hw binning is implement76* a22x is more like a3xx, but perhaps the a20x works? (TODO)77*/78if (!is_a20x(batch->ctx->screen))79return false;8081return fd_binning_enabled && ((gmem->nbins_x * gmem->nbins_y) > 2);82}8384/* transfer from gmem to system memory (ie. normal RAM) */8586static void87emit_gmem2mem_surf(struct fd_batch *batch, uint32_t base,88struct pipe_surface *psurf)89{90struct fd_ringbuffer *ring = batch->tile_fini;91struct fd_resource *rsc = fd_resource(psurf->texture);92uint32_t offset =93fd_resource_offset(rsc, psurf->u.tex.level, psurf->u.tex.first_layer);94enum pipe_format format = fd_gmem_restore_format(psurf->format);95uint32_t pitch = fdl2_pitch_pixels(&rsc->layout, psurf->u.tex.level);9697assert((pitch & 31) == 0);98assert((offset & 0xfff) == 0);99100if (!rsc->valid)101return;102103OUT_PKT3(ring, CP_SET_CONSTANT, 2);104OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));105OUT_RING(ring, A2XX_RB_COLOR_INFO_BASE(base) |106A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format)));107108OUT_PKT3(ring, CP_SET_CONSTANT, 5);109OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_CONTROL));110OUT_RING(ring, 0x00000000); /* RB_COPY_CONTROL */111OUT_RELOC(ring, rsc->bo, offset, 0, 0); /* RB_COPY_DEST_BASE */112OUT_RING(ring, pitch >> 5); /* RB_COPY_DEST_PITCH */113OUT_RING(ring, /* RB_COPY_DEST_INFO */114A2XX_RB_COPY_DEST_INFO_FORMAT(fd2_pipe2color(format)) |115COND(!rsc->layout.tile_mode, A2XX_RB_COPY_DEST_INFO_LINEAR) |116A2XX_RB_COPY_DEST_INFO_WRITE_RED |117A2XX_RB_COPY_DEST_INFO_WRITE_GREEN |118A2XX_RB_COPY_DEST_INFO_WRITE_BLUE |119A2XX_RB_COPY_DEST_INFO_WRITE_ALPHA);120121if (!is_a20x(batch->ctx->screen)) {122OUT_WFI(ring);123124OUT_PKT3(ring, CP_SET_CONSTANT, 3);125OUT_RING(ring, CP_REG(REG_A2XX_VGT_MAX_VTX_INDX));126OUT_RING(ring, 3); /* VGT_MAX_VTX_INDX */127OUT_RING(ring, 0); /* VGT_MIN_VTX_INDX */128}129130fd_draw(batch, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,131DI_SRC_SEL_AUTO_INDEX, 3, 0, INDEX_SIZE_IGN, 0, 0, NULL);132}133134static void135prepare_tile_fini_ib(struct fd_batch *batch) assert_dt136{137struct fd_context *ctx = batch->ctx;138struct fd2_context *fd2_ctx = fd2_context(ctx);139const struct fd_gmem_stateobj *gmem = batch->gmem_state;140struct pipe_framebuffer_state *pfb = &batch->framebuffer;141struct fd_ringbuffer *ring;142143batch->tile_fini =144fd_submit_new_ringbuffer(batch->submit, 0x1000, FD_RINGBUFFER_STREAMING);145ring = batch->tile_fini;146147fd2_emit_vertex_bufs(ring, 0x9c,148(struct fd2_vertex_buf[]){149{.prsc = fd2_ctx->solid_vertexbuf, .size = 36},150},1511);152153OUT_PKT3(ring, CP_SET_CONSTANT, 2);154OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_OFFSET));155OUT_RING(ring, 0x00000000); /* PA_SC_WINDOW_OFFSET */156157OUT_PKT3(ring, CP_SET_CONSTANT, 2);158OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET));159OUT_RING(ring, 0);160161if (!is_a20x(ctx->screen)) {162OUT_PKT3(ring, CP_SET_CONSTANT, 2);163OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));164OUT_RING(ring, 0x0000028f);165}166167fd2_program_emit(ctx, ring, &ctx->solid_prog);168169OUT_PKT3(ring, CP_SET_CONSTANT, 2);170OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK));171OUT_RING(ring, 0x0000ffff);172173OUT_PKT3(ring, CP_SET_CONSTANT, 2);174OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL));175OUT_RING(ring, A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE);176177OUT_PKT3(ring, CP_SET_CONSTANT, 2);178OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_SC_MODE_CNTL));179OUT_RING(180ring,181A2XX_PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST | /* PA_SU_SC_MODE_CNTL */182A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE(PC_DRAW_TRIANGLES) |183A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE(PC_DRAW_TRIANGLES));184185OUT_PKT3(ring, CP_SET_CONSTANT, 3);186OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL));187OUT_RING(ring, xy2d(0, 0)); /* PA_SC_WINDOW_SCISSOR_TL */188OUT_RING(ring, xy2d(pfb->width, pfb->height)); /* PA_SC_WINDOW_SCISSOR_BR */189190OUT_PKT3(ring, CP_SET_CONSTANT, 2);191OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL));192OUT_RING(ring, 0x00000000);193194OUT_PKT3(ring, CP_SET_CONSTANT, 5);195OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE));196OUT_RING(ring, fui((float)gmem->bin_w / 2.0)); /* XSCALE */197OUT_RING(ring, fui((float)gmem->bin_w / 2.0)); /* XOFFSET */198OUT_RING(ring, fui((float)gmem->bin_h / 2.0)); /* YSCALE */199OUT_RING(ring, fui((float)gmem->bin_h / 2.0)); /* YOFFSET */200201OUT_PKT3(ring, CP_SET_CONSTANT, 2);202OUT_RING(ring, CP_REG(REG_A2XX_RB_MODECONTROL));203OUT_RING(ring, A2XX_RB_MODECONTROL_EDRAM_MODE(EDRAM_COPY));204205if (batch->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL))206emit_gmem2mem_surf(batch, gmem->zsbuf_base[0], pfb->zsbuf);207208if (batch->resolve & FD_BUFFER_COLOR)209emit_gmem2mem_surf(batch, gmem->cbuf_base[0], pfb->cbufs[0]);210211OUT_PKT3(ring, CP_SET_CONSTANT, 2);212OUT_RING(ring, CP_REG(REG_A2XX_RB_MODECONTROL));213OUT_RING(ring, A2XX_RB_MODECONTROL_EDRAM_MODE(COLOR_DEPTH));214215if (!is_a20x(ctx->screen)) {216OUT_PKT3(ring, CP_SET_CONSTANT, 2);217OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));218OUT_RING(ring, 0x0000003b);219}220}221222static void223fd2_emit_tile_gmem2mem(struct fd_batch *batch, const struct fd_tile *tile)224{225fd2_emit_ib(batch->gmem, batch->tile_fini);226}227228/* transfer from system memory to gmem */229230static void231emit_mem2gmem_surf(struct fd_batch *batch, uint32_t base,232struct pipe_surface *psurf)233{234struct fd_ringbuffer *ring = batch->gmem;235struct fd_resource *rsc = fd_resource(psurf->texture);236uint32_t offset =237fd_resource_offset(rsc, psurf->u.tex.level, psurf->u.tex.first_layer);238enum pipe_format format = fd_gmem_restore_format(psurf->format);239240OUT_PKT3(ring, CP_SET_CONSTANT, 2);241OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));242OUT_RING(ring, A2XX_RB_COLOR_INFO_BASE(base) |243A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format)));244245/* emit fb as a texture: */246OUT_PKT3(ring, CP_SET_CONSTANT, 7);247OUT_RING(ring, 0x00010000);248OUT_RING(ring, A2XX_SQ_TEX_0_CLAMP_X(SQ_TEX_WRAP) |249A2XX_SQ_TEX_0_CLAMP_Y(SQ_TEX_WRAP) |250A2XX_SQ_TEX_0_CLAMP_Z(SQ_TEX_WRAP) |251A2XX_SQ_TEX_0_PITCH(252fdl2_pitch_pixels(&rsc->layout, psurf->u.tex.level)));253OUT_RELOC(ring, rsc->bo, offset,254A2XX_SQ_TEX_1_FORMAT(fd2_pipe2surface(format).format) |255A2XX_SQ_TEX_1_CLAMP_POLICY(SQ_TEX_CLAMP_POLICY_OGL),2560);257OUT_RING(ring, A2XX_SQ_TEX_2_WIDTH(psurf->width - 1) |258A2XX_SQ_TEX_2_HEIGHT(psurf->height - 1));259OUT_RING(ring, A2XX_SQ_TEX_3_MIP_FILTER(SQ_TEX_FILTER_BASEMAP) |260A2XX_SQ_TEX_3_SWIZ_X(0) | A2XX_SQ_TEX_3_SWIZ_Y(1) |261A2XX_SQ_TEX_3_SWIZ_Z(2) | A2XX_SQ_TEX_3_SWIZ_W(3) |262A2XX_SQ_TEX_3_XY_MAG_FILTER(SQ_TEX_FILTER_POINT) |263A2XX_SQ_TEX_3_XY_MIN_FILTER(SQ_TEX_FILTER_POINT));264OUT_RING(ring, 0x00000000);265OUT_RING(ring, A2XX_SQ_TEX_5_DIMENSION(SQ_TEX_DIMENSION_2D));266267if (!is_a20x(batch->ctx->screen)) {268OUT_PKT3(ring, CP_SET_CONSTANT, 3);269OUT_RING(ring, CP_REG(REG_A2XX_VGT_MAX_VTX_INDX));270OUT_RING(ring, 3); /* VGT_MAX_VTX_INDX */271OUT_RING(ring, 0); /* VGT_MIN_VTX_INDX */272}273274fd_draw(batch, ring, DI_PT_RECTLIST, IGNORE_VISIBILITY,275DI_SRC_SEL_AUTO_INDEX, 3, 0, INDEX_SIZE_IGN, 0, 0, NULL);276}277278static void279fd2_emit_tile_mem2gmem(struct fd_batch *batch,280const struct fd_tile *tile) assert_dt281{282struct fd_context *ctx = batch->ctx;283struct fd2_context *fd2_ctx = fd2_context(ctx);284const struct fd_gmem_stateobj *gmem = batch->gmem_state;285struct fd_ringbuffer *ring = batch->gmem;286struct pipe_framebuffer_state *pfb = &batch->framebuffer;287unsigned bin_w = tile->bin_w;288unsigned bin_h = tile->bin_h;289float x0, y0, x1, y1;290291fd2_emit_vertex_bufs(292ring, 0x9c,293(struct fd2_vertex_buf[]){294{.prsc = fd2_ctx->solid_vertexbuf, .size = 36},295{.prsc = fd2_ctx->solid_vertexbuf, .size = 24, .offset = 36},296},2972);298299/* write texture coordinates to vertexbuf: */300x0 = ((float)tile->xoff) / ((float)pfb->width);301x1 = ((float)tile->xoff + bin_w) / ((float)pfb->width);302y0 = ((float)tile->yoff) / ((float)pfb->height);303y1 = ((float)tile->yoff + bin_h) / ((float)pfb->height);304OUT_PKT3(ring, CP_MEM_WRITE, 7);305OUT_RELOC(ring, fd_resource(fd2_ctx->solid_vertexbuf)->bo, 36, 0, 0);306OUT_RING(ring, fui(x0));307OUT_RING(ring, fui(y0));308OUT_RING(ring, fui(x1));309OUT_RING(ring, fui(y0));310OUT_RING(ring, fui(x0));311OUT_RING(ring, fui(y1));312313OUT_PKT3(ring, CP_SET_CONSTANT, 2);314OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET));315OUT_RING(ring, 0);316317fd2_program_emit(ctx, ring, &ctx->blit_prog[0]);318319OUT_PKT0(ring, REG_A2XX_TC_CNTL_STATUS, 1);320OUT_RING(ring, A2XX_TC_CNTL_STATUS_L2_INVALIDATE);321322OUT_PKT3(ring, CP_SET_CONSTANT, 2);323OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL));324OUT_RING(ring, A2XX_RB_DEPTHCONTROL_EARLY_Z_ENABLE);325326OUT_PKT3(ring, CP_SET_CONSTANT, 2);327OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_SC_MODE_CNTL));328OUT_RING(ring, A2XX_PA_SU_SC_MODE_CNTL_PROVOKING_VTX_LAST |329A2XX_PA_SU_SC_MODE_CNTL_FRONT_PTYPE(PC_DRAW_TRIANGLES) |330A2XX_PA_SU_SC_MODE_CNTL_BACK_PTYPE(PC_DRAW_TRIANGLES));331332OUT_PKT3(ring, CP_SET_CONSTANT, 2);333OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK));334OUT_RING(ring, 0x0000ffff);335336OUT_PKT3(ring, CP_SET_CONSTANT, 2);337OUT_RING(ring, CP_REG(REG_A2XX_RB_COLORCONTROL));338OUT_RING(ring, A2XX_RB_COLORCONTROL_ALPHA_FUNC(FUNC_ALWAYS) |339A2XX_RB_COLORCONTROL_BLEND_DISABLE |340A2XX_RB_COLORCONTROL_ROP_CODE(12) |341A2XX_RB_COLORCONTROL_DITHER_MODE(DITHER_DISABLE) |342A2XX_RB_COLORCONTROL_DITHER_TYPE(DITHER_PIXEL));343344OUT_PKT3(ring, CP_SET_CONSTANT, 2);345OUT_RING(ring, CP_REG(REG_A2XX_RB_BLEND_CONTROL));346OUT_RING(ring, A2XX_RB_BLEND_CONTROL_COLOR_SRCBLEND(FACTOR_ONE) |347A2XX_RB_BLEND_CONTROL_COLOR_COMB_FCN(BLEND2_DST_PLUS_SRC) |348A2XX_RB_BLEND_CONTROL_COLOR_DESTBLEND(FACTOR_ZERO) |349A2XX_RB_BLEND_CONTROL_ALPHA_SRCBLEND(FACTOR_ONE) |350A2XX_RB_BLEND_CONTROL_ALPHA_COMB_FCN(BLEND2_DST_PLUS_SRC) |351A2XX_RB_BLEND_CONTROL_ALPHA_DESTBLEND(FACTOR_ZERO));352353OUT_PKT3(ring, CP_SET_CONSTANT, 3);354OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL));355OUT_RING(ring, A2XX_PA_SC_WINDOW_OFFSET_DISABLE |356xy2d(0, 0)); /* PA_SC_WINDOW_SCISSOR_TL */357OUT_RING(ring, xy2d(bin_w, bin_h)); /* PA_SC_WINDOW_SCISSOR_BR */358359OUT_PKT3(ring, CP_SET_CONSTANT, 5);360OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE));361OUT_RING(ring, fui((float)bin_w / 2.0)); /* PA_CL_VPORT_XSCALE */362OUT_RING(ring, fui((float)bin_w / 2.0)); /* PA_CL_VPORT_XOFFSET */363OUT_RING(ring, fui(-(float)bin_h / 2.0)); /* PA_CL_VPORT_YSCALE */364OUT_RING(ring, fui((float)bin_h / 2.0)); /* PA_CL_VPORT_YOFFSET */365366OUT_PKT3(ring, CP_SET_CONSTANT, 2);367OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VTE_CNTL));368OUT_RING(ring, A2XX_PA_CL_VTE_CNTL_VTX_XY_FMT |369A2XX_PA_CL_VTE_CNTL_VTX_Z_FMT | // XXX check this???370A2XX_PA_CL_VTE_CNTL_VPORT_X_SCALE_ENA |371A2XX_PA_CL_VTE_CNTL_VPORT_X_OFFSET_ENA |372A2XX_PA_CL_VTE_CNTL_VPORT_Y_SCALE_ENA |373A2XX_PA_CL_VTE_CNTL_VPORT_Y_OFFSET_ENA);374375OUT_PKT3(ring, CP_SET_CONSTANT, 2);376OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL));377OUT_RING(ring, 0x00000000);378379if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_DEPTH | FD_BUFFER_STENCIL))380emit_mem2gmem_surf(batch, gmem->zsbuf_base[0], pfb->zsbuf);381382if (fd_gmem_needs_restore(batch, tile, FD_BUFFER_COLOR))383emit_mem2gmem_surf(batch, gmem->cbuf_base[0], pfb->cbufs[0]);384385OUT_PKT3(ring, CP_SET_CONSTANT, 2);386OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VTE_CNTL));387OUT_RING(ring, A2XX_PA_CL_VTE_CNTL_VTX_W0_FMT |388A2XX_PA_CL_VTE_CNTL_VPORT_X_SCALE_ENA |389A2XX_PA_CL_VTE_CNTL_VPORT_X_OFFSET_ENA |390A2XX_PA_CL_VTE_CNTL_VPORT_Y_SCALE_ENA |391A2XX_PA_CL_VTE_CNTL_VPORT_Y_OFFSET_ENA |392A2XX_PA_CL_VTE_CNTL_VPORT_Z_SCALE_ENA |393A2XX_PA_CL_VTE_CNTL_VPORT_Z_OFFSET_ENA);394395/* TODO blob driver seems to toss in a CACHE_FLUSH after each DRAW_INDX.. */396}397398static void399patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode)400{401unsigned i;402403if (!is_a20x(batch->ctx->screen)) {404/* identical to a3xx */405for (i = 0; i < fd_patch_num_elements(&batch->draw_patches); i++) {406struct fd_cs_patch *patch = fd_patch_element(&batch->draw_patches, i);407*patch->cs = patch->val | DRAW(0, 0, 0, vismode, 0);408}409util_dynarray_clear(&batch->draw_patches);410return;411}412413if (vismode == USE_VISIBILITY)414return;415416for (i = 0; i < batch->draw_patches.size / sizeof(uint32_t *); i++) {417uint32_t *ptr =418*util_dynarray_element(&batch->draw_patches, uint32_t *, i);419unsigned cnt = ptr[0] >> 16 & 0xfff; /* 5 with idx buffer, 3 without */420421/* convert CP_DRAW_INDX_BIN to a CP_DRAW_INDX422* replace first two DWORDS with NOP and move the rest down423* (we don't want to have to move the idx buffer reloc)424*/425ptr[0] = CP_TYPE3_PKT | (CP_NOP << 8);426ptr[1] = 0x00000000;427428ptr[4] = ptr[2] & ~(1 << 14 | 1 << 15); /* remove cull_enable bits */429ptr[2] = CP_TYPE3_PKT | ((cnt - 2) << 16) | (CP_DRAW_INDX << 8);430ptr[3] = 0x00000000;431}432}433434static void435fd2_emit_sysmem_prep(struct fd_batch *batch)436{437struct fd_context *ctx = batch->ctx;438struct fd_ringbuffer *ring = batch->gmem;439struct pipe_framebuffer_state *pfb = &batch->framebuffer;440struct pipe_surface *psurf = pfb->cbufs[0];441442if (!psurf)443return;444445struct fd_resource *rsc = fd_resource(psurf->texture);446uint32_t offset =447fd_resource_offset(rsc, psurf->u.tex.level, psurf->u.tex.first_layer);448uint32_t pitch = fdl2_pitch_pixels(&rsc->layout, psurf->u.tex.level);449450assert((pitch & 31) == 0);451assert((offset & 0xfff) == 0);452453fd2_emit_restore(ctx, ring);454455OUT_PKT3(ring, CP_SET_CONSTANT, 2);456OUT_RING(ring, CP_REG(REG_A2XX_RB_SURFACE_INFO));457OUT_RING(ring, A2XX_RB_SURFACE_INFO_SURFACE_PITCH(pitch));458459OUT_PKT3(ring, CP_SET_CONSTANT, 2);460OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));461OUT_RELOC(ring, rsc->bo, offset,462COND(!rsc->layout.tile_mode, A2XX_RB_COLOR_INFO_LINEAR) |463A2XX_RB_COLOR_INFO_SWAP(fmt2swap(psurf->format)) |464A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(psurf->format)),4650);466467OUT_PKT3(ring, CP_SET_CONSTANT, 3);468OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_SCREEN_SCISSOR_TL));469OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_TL_WINDOW_OFFSET_DISABLE);470OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_BR_X(pfb->width) |471A2XX_PA_SC_SCREEN_SCISSOR_BR_Y(pfb->height));472473OUT_PKT3(ring, CP_SET_CONSTANT, 2);474OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_OFFSET));475OUT_RING(ring,476A2XX_PA_SC_WINDOW_OFFSET_X(0) | A2XX_PA_SC_WINDOW_OFFSET_Y(0));477478patch_draws(batch, IGNORE_VISIBILITY);479util_dynarray_clear(&batch->draw_patches);480util_dynarray_clear(&batch->shader_patches);481}482483/* before first tile */484static void485fd2_emit_tile_init(struct fd_batch *batch) assert_dt486{487struct fd_context *ctx = batch->ctx;488struct fd_ringbuffer *ring = batch->gmem;489struct pipe_framebuffer_state *pfb = &batch->framebuffer;490const struct fd_gmem_stateobj *gmem = batch->gmem_state;491enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);492uint32_t reg;493494fd2_emit_restore(ctx, ring);495496prepare_tile_fini_ib(batch);497498OUT_PKT3(ring, CP_SET_CONSTANT, 4);499OUT_RING(ring, CP_REG(REG_A2XX_RB_SURFACE_INFO));500OUT_RING(ring, gmem->bin_w); /* RB_SURFACE_INFO */501OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(fmt2swap(format)) |502A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format)));503reg = A2XX_RB_DEPTH_INFO_DEPTH_BASE(gmem->zsbuf_base[0]);504if (pfb->zsbuf)505reg |= A2XX_RB_DEPTH_INFO_DEPTH_FORMAT(fd_pipe2depth(pfb->zsbuf->format));506OUT_RING(ring, reg); /* RB_DEPTH_INFO */507508/* fast clear patches */509int depth_size = -1;510int color_size = -1;511512if (pfb->cbufs[0])513color_size = util_format_get_blocksizebits(format) == 32 ? 4 : 2;514515if (pfb->zsbuf)516depth_size = fd_pipe2depth(pfb->zsbuf->format) == 1 ? 4 : 2;517518for (int i = 0; i < fd_patch_num_elements(&batch->gmem_patches); i++) {519struct fd_cs_patch *patch = fd_patch_element(&batch->gmem_patches, i);520uint32_t color_base = 0, depth_base = gmem->zsbuf_base[0];521uint32_t size, lines;522523/* note: 1 "line" is 512 bytes in both color/depth areas (1K total) */524switch (patch->val) {525case GMEM_PATCH_FASTCLEAR_COLOR:526size = align(gmem->bin_w * gmem->bin_h * color_size, 0x8000);527lines = size / 1024;528depth_base = size / 2;529break;530case GMEM_PATCH_FASTCLEAR_DEPTH:531size = align(gmem->bin_w * gmem->bin_h * depth_size, 0x8000);532lines = size / 1024;533color_base = depth_base;534depth_base = depth_base + size / 2;535break;536case GMEM_PATCH_FASTCLEAR_COLOR_DEPTH:537lines =538align(gmem->bin_w * gmem->bin_h * color_size * 2, 0x8000) / 1024;539break;540case GMEM_PATCH_RESTORE_INFO:541patch->cs[0] = gmem->bin_w;542patch->cs[1] = A2XX_RB_COLOR_INFO_SWAP(fmt2swap(format)) |543A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format));544patch->cs[2] = A2XX_RB_DEPTH_INFO_DEPTH_BASE(gmem->zsbuf_base[0]);545if (pfb->zsbuf)546patch->cs[2] |= A2XX_RB_DEPTH_INFO_DEPTH_FORMAT(547fd_pipe2depth(pfb->zsbuf->format));548continue;549default:550continue;551}552553patch->cs[0] = A2XX_PA_SC_SCREEN_SCISSOR_BR_X(32) |554A2XX_PA_SC_SCREEN_SCISSOR_BR_Y(lines);555patch->cs[4] = A2XX_RB_COLOR_INFO_BASE(color_base) |556A2XX_RB_COLOR_INFO_FORMAT(COLORX_8_8_8_8);557patch->cs[5] = A2XX_RB_DEPTH_INFO_DEPTH_BASE(depth_base) |558A2XX_RB_DEPTH_INFO_DEPTH_FORMAT(1);559}560util_dynarray_clear(&batch->gmem_patches);561562/* set to zero, for some reason hardware doesn't like certain values */563OUT_PKT3(ring, CP_SET_CONSTANT, 2);564OUT_RING(ring, CP_REG(REG_A2XX_VGT_CURRENT_BIN_ID_MIN));565OUT_RING(ring, 0);566567OUT_PKT3(ring, CP_SET_CONSTANT, 2);568OUT_RING(ring, CP_REG(REG_A2XX_VGT_CURRENT_BIN_ID_MAX));569OUT_RING(ring, 0);570571if (use_hw_binning(batch)) {572/* patch out unneeded memory exports by changing EXEC CF to EXEC_END573*574* in the shader compiler, we guarantee that the shader ends with575* a specific pattern of ALLOC/EXEC CF pairs for the hw binning exports576*577* the since patches point only to dwords and CFs are 1.5 dwords578* the patch is aligned and might point to a ALLOC CF579*/580for (int i = 0; i < batch->shader_patches.size / sizeof(void *); i++) {581instr_cf_t *cf =582*util_dynarray_element(&batch->shader_patches, instr_cf_t *, i);583if (cf->opc == ALLOC)584cf++;585assert(cf->opc == EXEC);586assert(cf[ctx->screen->info->num_vsc_pipes * 2 - 2].opc == EXEC_END);587cf[2 * (gmem->num_vsc_pipes - 1)].opc = EXEC_END;588}589590patch_draws(batch, USE_VISIBILITY);591592/* initialize shader constants for the binning memexport */593OUT_PKT3(ring, CP_SET_CONSTANT, 1 + gmem->num_vsc_pipes * 4);594OUT_RING(ring, 0x0000000C);595596for (int i = 0; i < gmem->num_vsc_pipes; i++) {597/* allocate in 64k increments to avoid reallocs */598uint32_t bo_size = align(batch->num_vertices, 0x10000);599if (!ctx->vsc_pipe_bo[i] ||600fd_bo_size(ctx->vsc_pipe_bo[i]) < bo_size) {601if (ctx->vsc_pipe_bo[i])602fd_bo_del(ctx->vsc_pipe_bo[i]);603ctx->vsc_pipe_bo[i] =604fd_bo_new(ctx->dev, bo_size, 0, "vsc_pipe[%u]", i);605assert(ctx->vsc_pipe_bo[i]);606}607608/* memory export address (export32):609* .x: (base_address >> 2) | 0x40000000 (?)610* .y: index (float) - set by shader611* .z: 0x4B00D000 (?)612* .w: 0x4B000000 (?) | max_index (?)613*/614OUT_RELOC(ring, ctx->vsc_pipe_bo[i], 0, 0x40000000, -2);615OUT_RING(ring, 0x00000000);616OUT_RING(ring, 0x4B00D000);617OUT_RING(ring, 0x4B000000 | bo_size);618}619620OUT_PKT3(ring, CP_SET_CONSTANT, 1 + gmem->num_vsc_pipes * 8);621OUT_RING(ring, 0x0000018C);622623for (int i = 0; i < gmem->num_vsc_pipes; i++) {624const struct fd_vsc_pipe *pipe = &gmem->vsc_pipe[i];625float off_x, off_y, mul_x, mul_y;626627/* const to tranform from [-1,1] to bin coordinates for this pipe628* for x/y, [0,256/2040] = 0, [256/2040,512/2040] = 1, etc629* 8 possible values on x/y axis,630* to clip at binning stage: only use center 6x6631* TODO: set the z parameters too so that hw binning632* can clip primitives in Z too633*/634635mul_x = 1.0f / (float)(gmem->bin_w * 8);636mul_y = 1.0f / (float)(gmem->bin_h * 8);637off_x = -pipe->x * (1.0 / 8.0f) + 0.125f - mul_x * gmem->minx;638off_y = -pipe->y * (1.0 / 8.0f) + 0.125f - mul_y * gmem->miny;639640OUT_RING(ring, fui(off_x * (256.0f / 255.0f)));641OUT_RING(ring, fui(off_y * (256.0f / 255.0f)));642OUT_RING(ring, 0x3f000000);643OUT_RING(ring, fui(0.0f));644645OUT_RING(ring, fui(mul_x * (256.0f / 255.0f)));646OUT_RING(ring, fui(mul_y * (256.0f / 255.0f)));647OUT_RING(ring, fui(0.0f));648OUT_RING(ring, fui(0.0f));649}650651OUT_PKT3(ring, CP_SET_CONSTANT, 2);652OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));653OUT_RING(ring, 0);654655fd2_emit_ib(ring, batch->binning);656657OUT_PKT3(ring, CP_SET_CONSTANT, 2);658OUT_RING(ring, CP_REG(REG_A2XX_VGT_VERTEX_REUSE_BLOCK_CNTL));659OUT_RING(ring, 0x00000002);660} else {661patch_draws(batch, IGNORE_VISIBILITY);662}663664util_dynarray_clear(&batch->draw_patches);665util_dynarray_clear(&batch->shader_patches);666}667668/* before mem2gmem */669static void670fd2_emit_tile_prep(struct fd_batch *batch, const struct fd_tile *tile)671{672struct fd_ringbuffer *ring = batch->gmem;673struct pipe_framebuffer_state *pfb = &batch->framebuffer;674enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);675676OUT_PKT3(ring, CP_SET_CONSTANT, 2);677OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));678OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(1) | /* RB_COLOR_INFO */679A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format)));680681/* setup screen scissor for current tile (same for mem2gmem): */682OUT_PKT3(ring, CP_SET_CONSTANT, 3);683OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_SCREEN_SCISSOR_TL));684OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_TL_X(0) |685A2XX_PA_SC_SCREEN_SCISSOR_TL_Y(0));686OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_BR_X(tile->bin_w) |687A2XX_PA_SC_SCREEN_SCISSOR_BR_Y(tile->bin_h));688}689690/* before IB to rendering cmds: */691static void692fd2_emit_tile_renderprep(struct fd_batch *batch,693const struct fd_tile *tile) assert_dt694{695struct fd_context *ctx = batch->ctx;696struct fd2_context *fd2_ctx = fd2_context(ctx);697struct fd_ringbuffer *ring = batch->gmem;698struct pipe_framebuffer_state *pfb = &batch->framebuffer;699enum pipe_format format = pipe_surface_format(pfb->cbufs[0]);700701OUT_PKT3(ring, CP_SET_CONSTANT, 2);702OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_INFO));703OUT_RING(ring, A2XX_RB_COLOR_INFO_SWAP(fmt2swap(format)) |704A2XX_RB_COLOR_INFO_FORMAT(fd2_pipe2color(format)));705706/* setup window scissor and offset for current tile (different707* from mem2gmem):708*/709OUT_PKT3(ring, CP_SET_CONSTANT, 2);710OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_OFFSET));711OUT_RING(ring, A2XX_PA_SC_WINDOW_OFFSET_X(-tile->xoff) |712A2XX_PA_SC_WINDOW_OFFSET_Y(-tile->yoff));713714/* write SCISSOR_BR to memory so fast clear path can restore from it */715OUT_PKT3(ring, CP_MEM_WRITE, 2);716OUT_RELOC(ring, fd_resource(fd2_ctx->solid_vertexbuf)->bo, 60, 0, 0);717OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_BR_X(tile->bin_w) |718A2XX_PA_SC_SCREEN_SCISSOR_BR_Y(tile->bin_h));719720/* set the copy offset for gmem2mem */721OUT_PKT3(ring, CP_SET_CONSTANT, 2);722OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_DEST_OFFSET));723OUT_RING(ring, A2XX_RB_COPY_DEST_OFFSET_X(tile->xoff) |724A2XX_RB_COPY_DEST_OFFSET_Y(tile->yoff));725726/* tile offset for gl_FragCoord on a20x (C64 in fragment shader) */727if (is_a20x(ctx->screen)) {728OUT_PKT3(ring, CP_SET_CONSTANT, 5);729OUT_RING(ring, 0x00000580);730OUT_RING(ring, fui(tile->xoff));731OUT_RING(ring, fui(tile->yoff));732OUT_RING(ring, fui(0.0f));733OUT_RING(ring, fui(0.0f));734}735736if (use_hw_binning(batch)) {737struct fd_bo *pipe_bo = ctx->vsc_pipe_bo[tile->p];738739OUT_PKT3(ring, CP_SET_CONSTANT, 2);740OUT_RING(ring, CP_REG(REG_A2XX_VGT_CURRENT_BIN_ID_MIN));741OUT_RING(ring, tile->n);742743OUT_PKT3(ring, CP_SET_CONSTANT, 2);744OUT_RING(ring, CP_REG(REG_A2XX_VGT_CURRENT_BIN_ID_MAX));745OUT_RING(ring, tile->n);746747/* TODO only emit this when tile->p changes */748OUT_PKT3(ring, CP_SET_DRAW_INIT_FLAGS, 1);749OUT_RELOC(ring, pipe_bo, 0, 0, 0);750}751}752753void754fd2_gmem_init(struct pipe_context *pctx) disable_thread_safety_analysis755{756struct fd_context *ctx = fd_context(pctx);757758ctx->emit_sysmem_prep = fd2_emit_sysmem_prep;759ctx->emit_tile_init = fd2_emit_tile_init;760ctx->emit_tile_prep = fd2_emit_tile_prep;761ctx->emit_tile_mem2gmem = fd2_emit_tile_mem2gmem;762ctx->emit_tile_renderprep = fd2_emit_tile_renderprep;763ctx->emit_tile_gmem2mem = fd2_emit_tile_gmem2mem;764}765766767