1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2017 Broadcom 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 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "util/format/u_format.h" 25bf215546Sopenharmony_ci#include "v3d_context.h" 26bf215546Sopenharmony_ci#include "broadcom/common/v3d_tiling.h" 27bf215546Sopenharmony_ci#include "broadcom/common/v3d_macros.h" 28bf215546Sopenharmony_ci#include "broadcom/cle/v3dx_pack.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#define PIPE_CLEAR_COLOR_BUFFERS (PIPE_CLEAR_COLOR0 | \ 31bf215546Sopenharmony_ci PIPE_CLEAR_COLOR1 | \ 32bf215546Sopenharmony_ci PIPE_CLEAR_COLOR2 | \ 33bf215546Sopenharmony_ci PIPE_CLEAR_COLOR3) \ 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#define PIPE_FIRST_COLOR_BUFFER_BIT (ffs(PIPE_CLEAR_COLOR0) - 1) 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci/* The HW queues up the load until the tile coordinates show up, but can only 38bf215546Sopenharmony_ci * track one at a time. If we need to do more than one load, then we need to 39bf215546Sopenharmony_ci * flush out the previous load by emitting the tile coordinates and doing a 40bf215546Sopenharmony_ci * dummy store. 41bf215546Sopenharmony_ci */ 42bf215546Sopenharmony_cistatic void 43bf215546Sopenharmony_ciflush_last_load(struct v3d_cl *cl) 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci if (V3D_VERSION >= 40) 46bf215546Sopenharmony_ci return; 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords); 49bf215546Sopenharmony_ci cl_emit(cl, STORE_TILE_BUFFER_GENERAL, store) { 50bf215546Sopenharmony_ci store.buffer_to_store = NONE; 51bf215546Sopenharmony_ci } 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_cistatic void 55bf215546Sopenharmony_ciload_general(struct v3d_cl *cl, struct pipe_surface *psurf, int buffer, 56bf215546Sopenharmony_ci int layer, uint32_t pipe_bit, uint32_t *loads_pending) 57bf215546Sopenharmony_ci{ 58bf215546Sopenharmony_ci struct v3d_surface *surf = v3d_surface(psurf); 59bf215546Sopenharmony_ci bool separate_stencil = surf->separate_stencil && buffer == STENCIL; 60bf215546Sopenharmony_ci if (separate_stencil) { 61bf215546Sopenharmony_ci psurf = surf->separate_stencil; 62bf215546Sopenharmony_ci surf = v3d_surface(psurf); 63bf215546Sopenharmony_ci } 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci struct v3d_resource *rsc = v3d_resource(psurf->texture); 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci uint32_t layer_offset = 68bf215546Sopenharmony_ci v3d_layer_offset(&rsc->base, psurf->u.tex.level, 69bf215546Sopenharmony_ci psurf->u.tex.first_layer + layer); 70bf215546Sopenharmony_ci cl_emit(cl, LOAD_TILE_BUFFER_GENERAL, load) { 71bf215546Sopenharmony_ci load.buffer_to_load = buffer; 72bf215546Sopenharmony_ci load.address = cl_address(rsc->bo, layer_offset); 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci#if V3D_VERSION >= 40 75bf215546Sopenharmony_ci load.memory_format = surf->tiling; 76bf215546Sopenharmony_ci if (separate_stencil) 77bf215546Sopenharmony_ci load.input_image_format = V3D_OUTPUT_IMAGE_FORMAT_S8; 78bf215546Sopenharmony_ci else 79bf215546Sopenharmony_ci load.input_image_format = surf->format; 80bf215546Sopenharmony_ci load.r_b_swap = surf->swap_rb; 81bf215546Sopenharmony_ci load.force_alpha_1 = util_format_has_alpha1(psurf->format); 82bf215546Sopenharmony_ci if (surf->tiling == V3D_TILING_UIF_NO_XOR || 83bf215546Sopenharmony_ci surf->tiling == V3D_TILING_UIF_XOR) { 84bf215546Sopenharmony_ci load.height_in_ub_or_stride = 85bf215546Sopenharmony_ci surf->padded_height_of_output_image_in_uif_blocks; 86bf215546Sopenharmony_ci } else if (surf->tiling == V3D_TILING_RASTER) { 87bf215546Sopenharmony_ci struct v3d_resource_slice *slice = 88bf215546Sopenharmony_ci &rsc->slices[psurf->u.tex.level]; 89bf215546Sopenharmony_ci load.height_in_ub_or_stride = slice->stride; 90bf215546Sopenharmony_ci } 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci if (psurf->texture->nr_samples > 1) 93bf215546Sopenharmony_ci load.decimate_mode = V3D_DECIMATE_MODE_ALL_SAMPLES; 94bf215546Sopenharmony_ci else 95bf215546Sopenharmony_ci load.decimate_mode = V3D_DECIMATE_MODE_SAMPLE_0; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci#else /* V3D_VERSION < 40 */ 98bf215546Sopenharmony_ci /* Can't do raw ZSTENCIL loads -- need to load/store them to 99bf215546Sopenharmony_ci * separate buffers for Z and stencil. 100bf215546Sopenharmony_ci */ 101bf215546Sopenharmony_ci assert(buffer != ZSTENCIL); 102bf215546Sopenharmony_ci load.raw_mode = true; 103bf215546Sopenharmony_ci load.padded_height_of_output_image_in_uif_blocks = 104bf215546Sopenharmony_ci surf->padded_height_of_output_image_in_uif_blocks; 105bf215546Sopenharmony_ci#endif /* V3D_VERSION < 40 */ 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci *loads_pending &= ~pipe_bit; 109bf215546Sopenharmony_ci if (*loads_pending) 110bf215546Sopenharmony_ci flush_last_load(cl); 111bf215546Sopenharmony_ci} 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_cistatic void 114bf215546Sopenharmony_cistore_general(struct v3d_job *job, 115bf215546Sopenharmony_ci struct v3d_cl *cl, struct pipe_surface *psurf, 116bf215546Sopenharmony_ci int layer, int buffer, int pipe_bit, 117bf215546Sopenharmony_ci uint32_t *stores_pending, bool general_color_clear, 118bf215546Sopenharmony_ci bool resolve_4x) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci struct v3d_surface *surf = v3d_surface(psurf); 121bf215546Sopenharmony_ci bool separate_stencil = surf->separate_stencil && buffer == STENCIL; 122bf215546Sopenharmony_ci if (separate_stencil) { 123bf215546Sopenharmony_ci psurf = surf->separate_stencil; 124bf215546Sopenharmony_ci surf = v3d_surface(psurf); 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci *stores_pending &= ~pipe_bit; 128bf215546Sopenharmony_ci bool last_store = !(*stores_pending); 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci struct v3d_resource *rsc = v3d_resource(psurf->texture); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci rsc->writes++; 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci uint32_t layer_offset = 135bf215546Sopenharmony_ci v3d_layer_offset(&rsc->base, psurf->u.tex.level, 136bf215546Sopenharmony_ci psurf->u.tex.first_layer + layer); 137bf215546Sopenharmony_ci cl_emit(cl, STORE_TILE_BUFFER_GENERAL, store) { 138bf215546Sopenharmony_ci store.buffer_to_store = buffer; 139bf215546Sopenharmony_ci store.address = cl_address(rsc->bo, layer_offset); 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci#if V3D_VERSION >= 40 142bf215546Sopenharmony_ci store.clear_buffer_being_stored = false; 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci if (separate_stencil) 145bf215546Sopenharmony_ci store.output_image_format = V3D_OUTPUT_IMAGE_FORMAT_S8; 146bf215546Sopenharmony_ci else 147bf215546Sopenharmony_ci store.output_image_format = surf->format; 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci store.r_b_swap = surf->swap_rb; 150bf215546Sopenharmony_ci store.memory_format = surf->tiling; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci if (surf->tiling == V3D_TILING_UIF_NO_XOR || 153bf215546Sopenharmony_ci surf->tiling == V3D_TILING_UIF_XOR) { 154bf215546Sopenharmony_ci store.height_in_ub_or_stride = 155bf215546Sopenharmony_ci surf->padded_height_of_output_image_in_uif_blocks; 156bf215546Sopenharmony_ci } else if (surf->tiling == V3D_TILING_RASTER) { 157bf215546Sopenharmony_ci struct v3d_resource_slice *slice = 158bf215546Sopenharmony_ci &rsc->slices[psurf->u.tex.level]; 159bf215546Sopenharmony_ci store.height_in_ub_or_stride = slice->stride; 160bf215546Sopenharmony_ci } 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci assert(!resolve_4x || job->bbuf); 163bf215546Sopenharmony_ci if (psurf->texture->nr_samples > 1) 164bf215546Sopenharmony_ci store.decimate_mode = V3D_DECIMATE_MODE_ALL_SAMPLES; 165bf215546Sopenharmony_ci else if (resolve_4x && job->bbuf->texture->nr_samples > 1) 166bf215546Sopenharmony_ci store.decimate_mode = V3D_DECIMATE_MODE_4X; 167bf215546Sopenharmony_ci else 168bf215546Sopenharmony_ci store.decimate_mode = V3D_DECIMATE_MODE_SAMPLE_0; 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci#else /* V3D_VERSION < 40 */ 171bf215546Sopenharmony_ci /* Can't do raw ZSTENCIL stores -- need to load/store them to 172bf215546Sopenharmony_ci * separate buffers for Z and stencil. 173bf215546Sopenharmony_ci */ 174bf215546Sopenharmony_ci assert(buffer != ZSTENCIL); 175bf215546Sopenharmony_ci store.raw_mode = true; 176bf215546Sopenharmony_ci if (!last_store) { 177bf215546Sopenharmony_ci store.disable_color_buffers_clear_on_write = true; 178bf215546Sopenharmony_ci store.disable_z_buffer_clear_on_write = true; 179bf215546Sopenharmony_ci store.disable_stencil_buffer_clear_on_write = true; 180bf215546Sopenharmony_ci } else { 181bf215546Sopenharmony_ci store.disable_color_buffers_clear_on_write = 182bf215546Sopenharmony_ci !(((pipe_bit & PIPE_CLEAR_COLOR_BUFFERS) && 183bf215546Sopenharmony_ci general_color_clear && 184bf215546Sopenharmony_ci (job->clear & pipe_bit))); 185bf215546Sopenharmony_ci store.disable_z_buffer_clear_on_write = 186bf215546Sopenharmony_ci !(job->clear & PIPE_CLEAR_DEPTH); 187bf215546Sopenharmony_ci store.disable_stencil_buffer_clear_on_write = 188bf215546Sopenharmony_ci !(job->clear & PIPE_CLEAR_STENCIL); 189bf215546Sopenharmony_ci } 190bf215546Sopenharmony_ci store.padded_height_of_output_image_in_uif_blocks = 191bf215546Sopenharmony_ci surf->padded_height_of_output_image_in_uif_blocks; 192bf215546Sopenharmony_ci#endif /* V3D_VERSION < 40 */ 193bf215546Sopenharmony_ci } 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci /* There must be a TILE_COORDINATES_IMPLICIT between each store. */ 196bf215546Sopenharmony_ci if (V3D_VERSION < 40 && !last_store) { 197bf215546Sopenharmony_ci cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords); 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci} 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_cistatic int 202bf215546Sopenharmony_cizs_buffer_from_pipe_bits(int pipe_clear_bits) 203bf215546Sopenharmony_ci{ 204bf215546Sopenharmony_ci switch (pipe_clear_bits & PIPE_CLEAR_DEPTHSTENCIL) { 205bf215546Sopenharmony_ci case PIPE_CLEAR_DEPTHSTENCIL: 206bf215546Sopenharmony_ci return ZSTENCIL; 207bf215546Sopenharmony_ci case PIPE_CLEAR_DEPTH: 208bf215546Sopenharmony_ci return Z; 209bf215546Sopenharmony_ci case PIPE_CLEAR_STENCIL: 210bf215546Sopenharmony_ci return STENCIL; 211bf215546Sopenharmony_ci default: 212bf215546Sopenharmony_ci return NONE; 213bf215546Sopenharmony_ci } 214bf215546Sopenharmony_ci} 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_cistatic void 217bf215546Sopenharmony_civ3d_rcl_emit_loads(struct v3d_job *job, struct v3d_cl *cl, int layer) 218bf215546Sopenharmony_ci{ 219bf215546Sopenharmony_ci /* When blitting, no color or zs buffer is loaded; instead the blit 220bf215546Sopenharmony_ci * source buffer is loaded for the aspects that we are going to blit. 221bf215546Sopenharmony_ci */ 222bf215546Sopenharmony_ci assert(!job->bbuf || job->load == 0); 223bf215546Sopenharmony_ci assert(!job->bbuf || job->nr_cbufs <= 1); 224bf215546Sopenharmony_ci assert(!job->bbuf || V3D_VERSION >= 40); 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci uint32_t loads_pending = job->bbuf ? job->store : job->load; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci for (int i = 0; i < job->nr_cbufs; i++) { 229bf215546Sopenharmony_ci uint32_t bit = PIPE_CLEAR_COLOR0 << i; 230bf215546Sopenharmony_ci if (!(loads_pending & bit)) 231bf215546Sopenharmony_ci continue; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci struct pipe_surface *psurf = job->bbuf ? job->bbuf : job->cbufs[i]; 234bf215546Sopenharmony_ci assert(!job->bbuf || i == 0); 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci if (!psurf || (V3D_VERSION < 40 && 237bf215546Sopenharmony_ci psurf->texture->nr_samples <= 1)) { 238bf215546Sopenharmony_ci continue; 239bf215546Sopenharmony_ci } 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci load_general(cl, psurf, RENDER_TARGET_0 + i, layer, 242bf215546Sopenharmony_ci bit, &loads_pending); 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci if ((loads_pending & PIPE_CLEAR_DEPTHSTENCIL) && 246bf215546Sopenharmony_ci (V3D_VERSION >= 40 || 247bf215546Sopenharmony_ci (job->zsbuf && job->zsbuf->texture->nr_samples > 1))) { 248bf215546Sopenharmony_ci assert(!job->early_zs_clear); 249bf215546Sopenharmony_ci struct pipe_surface *src = job->bbuf ? job->bbuf : job->zsbuf; 250bf215546Sopenharmony_ci struct v3d_resource *rsc = v3d_resource(src->texture); 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci if (rsc->separate_stencil && 253bf215546Sopenharmony_ci (loads_pending & PIPE_CLEAR_STENCIL)) { 254bf215546Sopenharmony_ci load_general(cl, src, 255bf215546Sopenharmony_ci STENCIL, layer, 256bf215546Sopenharmony_ci PIPE_CLEAR_STENCIL, 257bf215546Sopenharmony_ci &loads_pending); 258bf215546Sopenharmony_ci } 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci if (loads_pending & PIPE_CLEAR_DEPTHSTENCIL) { 261bf215546Sopenharmony_ci load_general(cl, src, 262bf215546Sopenharmony_ci zs_buffer_from_pipe_bits(loads_pending), 263bf215546Sopenharmony_ci layer, 264bf215546Sopenharmony_ci loads_pending & PIPE_CLEAR_DEPTHSTENCIL, 265bf215546Sopenharmony_ci &loads_pending); 266bf215546Sopenharmony_ci } 267bf215546Sopenharmony_ci } 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci#if V3D_VERSION < 40 270bf215546Sopenharmony_ci /* The initial reload will be queued until we get the 271bf215546Sopenharmony_ci * tile coordinates. 272bf215546Sopenharmony_ci */ 273bf215546Sopenharmony_ci if (loads_pending) { 274bf215546Sopenharmony_ci cl_emit(cl, RELOAD_TILE_COLOR_BUFFER, load) { 275bf215546Sopenharmony_ci load.disable_color_buffer_load = 276bf215546Sopenharmony_ci (~loads_pending & 277bf215546Sopenharmony_ci PIPE_CLEAR_COLOR_BUFFERS) >> 278bf215546Sopenharmony_ci PIPE_FIRST_COLOR_BUFFER_BIT; 279bf215546Sopenharmony_ci load.enable_z_load = 280bf215546Sopenharmony_ci loads_pending & PIPE_CLEAR_DEPTH; 281bf215546Sopenharmony_ci load.enable_stencil_load = 282bf215546Sopenharmony_ci loads_pending & PIPE_CLEAR_STENCIL; 283bf215546Sopenharmony_ci } 284bf215546Sopenharmony_ci } 285bf215546Sopenharmony_ci#else /* V3D_VERSION >= 40 */ 286bf215546Sopenharmony_ci assert(!loads_pending); 287bf215546Sopenharmony_ci cl_emit(cl, END_OF_LOADS, end); 288bf215546Sopenharmony_ci#endif 289bf215546Sopenharmony_ci} 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_cistatic void 292bf215546Sopenharmony_civ3d_rcl_emit_stores(struct v3d_job *job, struct v3d_cl *cl, int layer) 293bf215546Sopenharmony_ci{ 294bf215546Sopenharmony_ci#if V3D_VERSION < 40 295bf215546Sopenharmony_ci UNUSED bool needs_color_clear = job->clear & PIPE_CLEAR_COLOR_BUFFERS; 296bf215546Sopenharmony_ci UNUSED bool needs_z_clear = job->clear & PIPE_CLEAR_DEPTH; 297bf215546Sopenharmony_ci UNUSED bool needs_s_clear = job->clear & PIPE_CLEAR_STENCIL; 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci /* For clearing color in a TLB general on V3D 3.3: 300bf215546Sopenharmony_ci * 301bf215546Sopenharmony_ci * - NONE buffer store clears all TLB color buffers. 302bf215546Sopenharmony_ci * - color buffer store clears just the TLB color buffer being stored. 303bf215546Sopenharmony_ci * - Z/S buffers store may not clear the TLB color buffer. 304bf215546Sopenharmony_ci * 305bf215546Sopenharmony_ci * And on V3D 4.1, we only have one flag for "clear the buffer being 306bf215546Sopenharmony_ci * stored" in the general packet, and a separate packet to clear all 307bf215546Sopenharmony_ci * color TLB buffers. 308bf215546Sopenharmony_ci * 309bf215546Sopenharmony_ci * As a result, we only bother flagging TLB color clears in a general 310bf215546Sopenharmony_ci * packet when we don't have to emit a separate packet to clear all 311bf215546Sopenharmony_ci * TLB color buffers. 312bf215546Sopenharmony_ci */ 313bf215546Sopenharmony_ci bool general_color_clear = (needs_color_clear && 314bf215546Sopenharmony_ci (job->clear & PIPE_CLEAR_COLOR_BUFFERS) == 315bf215546Sopenharmony_ci (job->store & PIPE_CLEAR_COLOR_BUFFERS)); 316bf215546Sopenharmony_ci#else 317bf215546Sopenharmony_ci bool general_color_clear = false; 318bf215546Sopenharmony_ci#endif 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci uint32_t stores_pending = job->store; 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci /* For V3D 4.1, use general stores for all TLB stores. 323bf215546Sopenharmony_ci * 324bf215546Sopenharmony_ci * For V3D 3.3, we only use general stores to do raw stores for any 325bf215546Sopenharmony_ci * MSAA surfaces. These output UIF tiled images where each 4x MSAA 326bf215546Sopenharmony_ci * pixel is a 2x2 quad, and the format will be that of the 327bf215546Sopenharmony_ci * internal_type/internal_bpp, rather than the format from GL's 328bf215546Sopenharmony_ci * perspective. Non-MSAA surfaces will use 329bf215546Sopenharmony_ci * STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED. 330bf215546Sopenharmony_ci */ 331bf215546Sopenharmony_ci assert(!job->bbuf || job->nr_cbufs <= 1); 332bf215546Sopenharmony_ci for (int i = 0; i < job->nr_cbufs; i++) { 333bf215546Sopenharmony_ci uint32_t bit = PIPE_CLEAR_COLOR0 << i; 334bf215546Sopenharmony_ci if (!(job->store & bit)) 335bf215546Sopenharmony_ci continue; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci struct pipe_surface *psurf = job->cbufs[i]; 338bf215546Sopenharmony_ci if (!psurf || 339bf215546Sopenharmony_ci (V3D_VERSION < 40 && psurf->texture->nr_samples <= 1)) { 340bf215546Sopenharmony_ci continue; 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci store_general(job, cl, psurf, layer, RENDER_TARGET_0 + i, bit, 344bf215546Sopenharmony_ci &stores_pending, general_color_clear, job->bbuf); 345bf215546Sopenharmony_ci } 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci if (job->store & PIPE_CLEAR_DEPTHSTENCIL && job->zsbuf && 348bf215546Sopenharmony_ci !(V3D_VERSION < 40 && job->zsbuf->texture->nr_samples <= 1)) { 349bf215546Sopenharmony_ci assert(!job->early_zs_clear); 350bf215546Sopenharmony_ci struct v3d_resource *rsc = v3d_resource(job->zsbuf->texture); 351bf215546Sopenharmony_ci if (rsc->separate_stencil) { 352bf215546Sopenharmony_ci if (job->store & PIPE_CLEAR_DEPTH) { 353bf215546Sopenharmony_ci store_general(job, cl, job->zsbuf, layer, 354bf215546Sopenharmony_ci Z, PIPE_CLEAR_DEPTH, 355bf215546Sopenharmony_ci &stores_pending, 356bf215546Sopenharmony_ci general_color_clear, 357bf215546Sopenharmony_ci false); 358bf215546Sopenharmony_ci } 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci if (job->store & PIPE_CLEAR_STENCIL) { 361bf215546Sopenharmony_ci store_general(job, cl, job->zsbuf, layer, 362bf215546Sopenharmony_ci STENCIL, PIPE_CLEAR_STENCIL, 363bf215546Sopenharmony_ci &stores_pending, 364bf215546Sopenharmony_ci general_color_clear, 365bf215546Sopenharmony_ci false); 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci } else { 368bf215546Sopenharmony_ci store_general(job, cl, job->zsbuf, layer, 369bf215546Sopenharmony_ci zs_buffer_from_pipe_bits(job->store), 370bf215546Sopenharmony_ci job->store & PIPE_CLEAR_DEPTHSTENCIL, 371bf215546Sopenharmony_ci &stores_pending, general_color_clear, 372bf215546Sopenharmony_ci false); 373bf215546Sopenharmony_ci } 374bf215546Sopenharmony_ci } 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci#if V3D_VERSION < 40 377bf215546Sopenharmony_ci if (stores_pending) { 378bf215546Sopenharmony_ci cl_emit(cl, STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED, store) { 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci store.disable_color_buffer_write = 381bf215546Sopenharmony_ci (~stores_pending >> 382bf215546Sopenharmony_ci PIPE_FIRST_COLOR_BUFFER_BIT) & 0xf; 383bf215546Sopenharmony_ci store.enable_z_write = stores_pending & PIPE_CLEAR_DEPTH; 384bf215546Sopenharmony_ci store.enable_stencil_write = stores_pending & PIPE_CLEAR_STENCIL; 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci /* Note that when set this will clear all of the color 387bf215546Sopenharmony_ci * buffers. 388bf215546Sopenharmony_ci */ 389bf215546Sopenharmony_ci store.disable_color_buffers_clear_on_write = 390bf215546Sopenharmony_ci !needs_color_clear; 391bf215546Sopenharmony_ci store.disable_z_buffer_clear_on_write = 392bf215546Sopenharmony_ci !needs_z_clear; 393bf215546Sopenharmony_ci store.disable_stencil_buffer_clear_on_write = 394bf215546Sopenharmony_ci !needs_s_clear; 395bf215546Sopenharmony_ci }; 396bf215546Sopenharmony_ci } else if (needs_color_clear && !general_color_clear) { 397bf215546Sopenharmony_ci /* If we didn't do our color clears in the general packet, 398bf215546Sopenharmony_ci * then emit a packet to clear all the TLB color buffers now. 399bf215546Sopenharmony_ci */ 400bf215546Sopenharmony_ci cl_emit(cl, STORE_TILE_BUFFER_GENERAL, store) { 401bf215546Sopenharmony_ci store.buffer_to_store = NONE; 402bf215546Sopenharmony_ci } 403bf215546Sopenharmony_ci } 404bf215546Sopenharmony_ci#else /* V3D_VERSION >= 40 */ 405bf215546Sopenharmony_ci /* If we're emitting an RCL with GL_ARB_framebuffer_no_attachments, 406bf215546Sopenharmony_ci * we still need to emit some sort of store. 407bf215546Sopenharmony_ci */ 408bf215546Sopenharmony_ci if (!job->store) { 409bf215546Sopenharmony_ci cl_emit(cl, STORE_TILE_BUFFER_GENERAL, store) { 410bf215546Sopenharmony_ci store.buffer_to_store = NONE; 411bf215546Sopenharmony_ci } 412bf215546Sopenharmony_ci } 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci assert(!stores_pending); 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci /* GFXH-1461/GFXH-1689: The per-buffer store command's clear 417bf215546Sopenharmony_ci * buffer bit is broken for depth/stencil. In addition, the 418bf215546Sopenharmony_ci * clear packet's Z/S bit is broken, but the RTs bit ends up 419bf215546Sopenharmony_ci * clearing Z/S. 420bf215546Sopenharmony_ci */ 421bf215546Sopenharmony_ci if (job->clear) { 422bf215546Sopenharmony_ci cl_emit(cl, CLEAR_TILE_BUFFERS, clear) { 423bf215546Sopenharmony_ci clear.clear_z_stencil_buffer = !job->early_zs_clear; 424bf215546Sopenharmony_ci clear.clear_all_render_targets = true; 425bf215546Sopenharmony_ci } 426bf215546Sopenharmony_ci } 427bf215546Sopenharmony_ci#endif /* V3D_VERSION >= 40 */ 428bf215546Sopenharmony_ci} 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_cistatic void 431bf215546Sopenharmony_civ3d_rcl_emit_generic_per_tile_list(struct v3d_job *job, int layer) 432bf215546Sopenharmony_ci{ 433bf215546Sopenharmony_ci /* Emit the generic list in our indirect state -- the rcl will just 434bf215546Sopenharmony_ci * have pointers into it. 435bf215546Sopenharmony_ci */ 436bf215546Sopenharmony_ci struct v3d_cl *cl = &job->indirect; 437bf215546Sopenharmony_ci v3d_cl_ensure_space(cl, 200, 1); 438bf215546Sopenharmony_ci struct v3d_cl_reloc tile_list_start = cl_get_address(cl); 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci if (V3D_VERSION >= 40) { 441bf215546Sopenharmony_ci /* V3D 4.x only requires a single tile coordinates, and 442bf215546Sopenharmony_ci * END_OF_LOADS switches us between loading and rendering. 443bf215546Sopenharmony_ci */ 444bf215546Sopenharmony_ci cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords); 445bf215546Sopenharmony_ci } 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci v3d_rcl_emit_loads(job, cl, layer); 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ci if (V3D_VERSION < 40) { 450bf215546Sopenharmony_ci /* Tile Coordinates triggers the last reload and sets where 451bf215546Sopenharmony_ci * the stores go. There must be one per store packet. 452bf215546Sopenharmony_ci */ 453bf215546Sopenharmony_ci cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords); 454bf215546Sopenharmony_ci } 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci /* The binner starts out writing tiles assuming that the initial mode 457bf215546Sopenharmony_ci * is triangles, so make sure that's the case. 458bf215546Sopenharmony_ci */ 459bf215546Sopenharmony_ci cl_emit(cl, PRIM_LIST_FORMAT, fmt) { 460bf215546Sopenharmony_ci fmt.primitive_type = LIST_TRIANGLES; 461bf215546Sopenharmony_ci } 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci#if V3D_VERSION >= 41 464bf215546Sopenharmony_ci /* PTB assumes that value to be 0, but hw will not set it. */ 465bf215546Sopenharmony_ci cl_emit(cl, SET_INSTANCEID, set) { 466bf215546Sopenharmony_ci set.instance_id = 0; 467bf215546Sopenharmony_ci } 468bf215546Sopenharmony_ci#endif 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci cl_emit(cl, BRANCH_TO_IMPLICIT_TILE_LIST, branch); 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_ci v3d_rcl_emit_stores(job, cl, layer); 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci#if V3D_VERSION >= 40 475bf215546Sopenharmony_ci cl_emit(cl, END_OF_TILE_MARKER, end); 476bf215546Sopenharmony_ci#endif 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci cl_emit(cl, RETURN_FROM_SUB_LIST, ret); 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci cl_emit(&job->rcl, START_ADDRESS_OF_GENERIC_TILE_LIST, branch) { 481bf215546Sopenharmony_ci branch.start = tile_list_start; 482bf215546Sopenharmony_ci branch.end = cl_get_address(cl); 483bf215546Sopenharmony_ci } 484bf215546Sopenharmony_ci} 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci#if V3D_VERSION >= 40 487bf215546Sopenharmony_cistatic void 488bf215546Sopenharmony_civ3d_setup_render_target(struct v3d_job *job, int cbuf, 489bf215546Sopenharmony_ci uint32_t *rt_bpp, uint32_t *rt_type, uint32_t *rt_clamp) 490bf215546Sopenharmony_ci{ 491bf215546Sopenharmony_ci if (!job->cbufs[cbuf]) 492bf215546Sopenharmony_ci return; 493bf215546Sopenharmony_ci 494bf215546Sopenharmony_ci struct v3d_surface *surf = v3d_surface(job->cbufs[cbuf]); 495bf215546Sopenharmony_ci *rt_bpp = surf->internal_bpp; 496bf215546Sopenharmony_ci if (job->bbuf) { 497bf215546Sopenharmony_ci struct v3d_surface *bsurf = v3d_surface(job->bbuf); 498bf215546Sopenharmony_ci *rt_bpp = MAX2(*rt_bpp, bsurf->internal_bpp); 499bf215546Sopenharmony_ci } 500bf215546Sopenharmony_ci *rt_type = surf->internal_type; 501bf215546Sopenharmony_ci *rt_clamp = V3D_RENDER_TARGET_CLAMP_NONE; 502bf215546Sopenharmony_ci} 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci#else /* V3D_VERSION < 40 */ 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_cistatic void 507bf215546Sopenharmony_civ3d_emit_z_stencil_config(struct v3d_job *job, struct v3d_surface *surf, 508bf215546Sopenharmony_ci struct v3d_resource *rsc, bool is_separate_stencil) 509bf215546Sopenharmony_ci{ 510bf215546Sopenharmony_ci cl_emit(&job->rcl, TILE_RENDERING_MODE_CFG_Z_STENCIL, zs) { 511bf215546Sopenharmony_ci zs.address = cl_address(rsc->bo, surf->offset); 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci if (!is_separate_stencil) { 514bf215546Sopenharmony_ci zs.internal_type = surf->internal_type; 515bf215546Sopenharmony_ci zs.output_image_format = surf->format; 516bf215546Sopenharmony_ci } else { 517bf215546Sopenharmony_ci zs.z_stencil_id = 1; /* Separate stencil */ 518bf215546Sopenharmony_ci } 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci zs.padded_height_of_output_image_in_uif_blocks = 521bf215546Sopenharmony_ci surf->padded_height_of_output_image_in_uif_blocks; 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci assert(surf->tiling != V3D_TILING_RASTER); 524bf215546Sopenharmony_ci zs.memory_format = surf->tiling; 525bf215546Sopenharmony_ci } 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci if (job->store & (is_separate_stencil ? 528bf215546Sopenharmony_ci PIPE_CLEAR_STENCIL : 529bf215546Sopenharmony_ci PIPE_CLEAR_DEPTHSTENCIL)) { 530bf215546Sopenharmony_ci rsc->writes++; 531bf215546Sopenharmony_ci } 532bf215546Sopenharmony_ci} 533bf215546Sopenharmony_ci#endif /* V3D_VERSION < 40 */ 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci#define div_round_up(a, b) (((a) + (b) - 1) / b) 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_cistatic bool 538bf215546Sopenharmony_cisupertile_in_job_scissors(struct v3d_job *job, 539bf215546Sopenharmony_ci uint32_t x, uint32_t y, uint32_t w, uint32_t h) 540bf215546Sopenharmony_ci{ 541bf215546Sopenharmony_ci if (job->scissor.disabled || job->scissor.count == 0) 542bf215546Sopenharmony_ci return true; 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_ci const uint32_t min_x = x * w; 545bf215546Sopenharmony_ci const uint32_t min_y = y * h; 546bf215546Sopenharmony_ci const uint32_t max_x = min_x + w - 1; 547bf215546Sopenharmony_ci const uint32_t max_y = min_y + h - 1; 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci for (uint32_t i = 0; i < job->scissor.count; i++) { 550bf215546Sopenharmony_ci const uint32_t min_s_x = job->scissor.rects[i].min_x; 551bf215546Sopenharmony_ci const uint32_t min_s_y = job->scissor.rects[i].min_y; 552bf215546Sopenharmony_ci const uint32_t max_s_x = job->scissor.rects[i].max_x; 553bf215546Sopenharmony_ci const uint32_t max_s_y = job->scissor.rects[i].max_y; 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci if (max_x < min_s_x || min_x > max_s_x || 556bf215546Sopenharmony_ci max_y < min_s_y || min_y > max_s_y) { 557bf215546Sopenharmony_ci continue; 558bf215546Sopenharmony_ci } 559bf215546Sopenharmony_ci 560bf215546Sopenharmony_ci return true; 561bf215546Sopenharmony_ci } 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci return false; 564bf215546Sopenharmony_ci} 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci#if V3D_VERSION >= 40 567bf215546Sopenharmony_cistatic inline bool 568bf215546Sopenharmony_cido_double_initial_tile_clear(const struct v3d_job *job) 569bf215546Sopenharmony_ci{ 570bf215546Sopenharmony_ci /* Our rendering code emits an initial clear per layer, unlike the 571bf215546Sopenharmony_ci * Vulkan driver, which only executes a single initial clear for all 572bf215546Sopenharmony_ci * layers. This is because in GL we don't use the 573bf215546Sopenharmony_ci * 'clear_buffer_being_stored' bit when storing tiles, so each layer 574bf215546Sopenharmony_ci * needs the iniital clear. This is also why this helper, unlike the 575bf215546Sopenharmony_ci * Vulkan version, doesn't check the layer count to decide if double 576bf215546Sopenharmony_ci * clear for double buffer mode is required. 577bf215546Sopenharmony_ci */ 578bf215546Sopenharmony_ci return job->double_buffer && 579bf215546Sopenharmony_ci (job->draw_tiles_x > 1 || job->draw_tiles_y > 1); 580bf215546Sopenharmony_ci} 581bf215546Sopenharmony_ci#endif 582bf215546Sopenharmony_ci 583bf215546Sopenharmony_cistatic void 584bf215546Sopenharmony_ciemit_render_layer(struct v3d_job *job, uint32_t layer) 585bf215546Sopenharmony_ci{ 586bf215546Sopenharmony_ci uint32_t supertile_w = 1, supertile_h = 1; 587bf215546Sopenharmony_ci 588bf215546Sopenharmony_ci /* If doing multicore binning, we would need to initialize each 589bf215546Sopenharmony_ci * core's tile list here. 590bf215546Sopenharmony_ci */ 591bf215546Sopenharmony_ci uint32_t tile_alloc_offset = 592bf215546Sopenharmony_ci layer * job->draw_tiles_x * job->draw_tiles_y * 64; 593bf215546Sopenharmony_ci cl_emit(&job->rcl, MULTICORE_RENDERING_TILE_LIST_SET_BASE, list) { 594bf215546Sopenharmony_ci list.address = cl_address(job->tile_alloc, tile_alloc_offset); 595bf215546Sopenharmony_ci } 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_ci cl_emit(&job->rcl, MULTICORE_RENDERING_SUPERTILE_CFG, config) { 598bf215546Sopenharmony_ci uint32_t frame_w_in_supertiles, frame_h_in_supertiles; 599bf215546Sopenharmony_ci const uint32_t max_supertiles = 256; 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci /* Size up our supertiles until we get under the limit. */ 602bf215546Sopenharmony_ci for (;;) { 603bf215546Sopenharmony_ci frame_w_in_supertiles = div_round_up(job->draw_tiles_x, 604bf215546Sopenharmony_ci supertile_w); 605bf215546Sopenharmony_ci frame_h_in_supertiles = div_round_up(job->draw_tiles_y, 606bf215546Sopenharmony_ci supertile_h); 607bf215546Sopenharmony_ci if (frame_w_in_supertiles * 608bf215546Sopenharmony_ci frame_h_in_supertiles < max_supertiles) { 609bf215546Sopenharmony_ci break; 610bf215546Sopenharmony_ci } 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci if (supertile_w < supertile_h) 613bf215546Sopenharmony_ci supertile_w++; 614bf215546Sopenharmony_ci else 615bf215546Sopenharmony_ci supertile_h++; 616bf215546Sopenharmony_ci } 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci config.number_of_bin_tile_lists = 1; 619bf215546Sopenharmony_ci config.total_frame_width_in_tiles = job->draw_tiles_x; 620bf215546Sopenharmony_ci config.total_frame_height_in_tiles = job->draw_tiles_y; 621bf215546Sopenharmony_ci 622bf215546Sopenharmony_ci config.supertile_width_in_tiles = supertile_w; 623bf215546Sopenharmony_ci config.supertile_height_in_tiles = supertile_h; 624bf215546Sopenharmony_ci 625bf215546Sopenharmony_ci config.total_frame_width_in_supertiles = frame_w_in_supertiles; 626bf215546Sopenharmony_ci config.total_frame_height_in_supertiles = frame_h_in_supertiles; 627bf215546Sopenharmony_ci } 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_ci /* Start by clearing the tile buffer. */ 630bf215546Sopenharmony_ci cl_emit(&job->rcl, TILE_COORDINATES, coords) { 631bf215546Sopenharmony_ci coords.tile_column_number = 0; 632bf215546Sopenharmony_ci coords.tile_row_number = 0; 633bf215546Sopenharmony_ci } 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_ci /* Emit an initial clear of the tile buffers. This is necessary 636bf215546Sopenharmony_ci * for any buffers that should be cleared (since clearing 637bf215546Sopenharmony_ci * normally happens at the *end* of the generic tile list), but 638bf215546Sopenharmony_ci * it's also nice to clear everything so the first tile doesn't 639bf215546Sopenharmony_ci * inherit any contents from some previous frame. 640bf215546Sopenharmony_ci * 641bf215546Sopenharmony_ci * Also, implement the GFXH-1742 workaround. There's a race in 642bf215546Sopenharmony_ci * the HW between the RCL updating the TLB's internal type/size 643bf215546Sopenharmony_ci * and thespawning of the QPU instances using the TLB's current 644bf215546Sopenharmony_ci * internal type/size. To make sure the QPUs get the right 645bf215546Sopenharmony_ci * state, we need 1 dummy store in between internal type/size 646bf215546Sopenharmony_ci * changes on V3D 3.x, and 2 dummy stores on 4.x. 647bf215546Sopenharmony_ci */ 648bf215546Sopenharmony_ci#if V3D_VERSION < 40 649bf215546Sopenharmony_ci cl_emit(&job->rcl, STORE_TILE_BUFFER_GENERAL, store) { 650bf215546Sopenharmony_ci store.buffer_to_store = NONE; 651bf215546Sopenharmony_ci } 652bf215546Sopenharmony_ci#else 653bf215546Sopenharmony_ci for (int i = 0; i < 2; i++) { 654bf215546Sopenharmony_ci if (i > 0) 655bf215546Sopenharmony_ci cl_emit(&job->rcl, TILE_COORDINATES, coords); 656bf215546Sopenharmony_ci cl_emit(&job->rcl, END_OF_LOADS, end); 657bf215546Sopenharmony_ci cl_emit(&job->rcl, STORE_TILE_BUFFER_GENERAL, store) { 658bf215546Sopenharmony_ci store.buffer_to_store = NONE; 659bf215546Sopenharmony_ci } 660bf215546Sopenharmony_ci if (i == 0 || do_double_initial_tile_clear(job)) { 661bf215546Sopenharmony_ci cl_emit(&job->rcl, CLEAR_TILE_BUFFERS, clear) { 662bf215546Sopenharmony_ci clear.clear_z_stencil_buffer = !job->early_zs_clear; 663bf215546Sopenharmony_ci clear.clear_all_render_targets = true; 664bf215546Sopenharmony_ci } 665bf215546Sopenharmony_ci } 666bf215546Sopenharmony_ci cl_emit(&job->rcl, END_OF_TILE_MARKER, end); 667bf215546Sopenharmony_ci } 668bf215546Sopenharmony_ci#endif 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci cl_emit(&job->rcl, FLUSH_VCD_CACHE, flush); 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci v3d_rcl_emit_generic_per_tile_list(job, layer); 673bf215546Sopenharmony_ci 674bf215546Sopenharmony_ci /* XXX perf: We should expose GL_MESA_tile_raster_order to 675bf215546Sopenharmony_ci * improve X11 performance, but we should use Morton order 676bf215546Sopenharmony_ci * otherwise to improve cache locality. 677bf215546Sopenharmony_ci */ 678bf215546Sopenharmony_ci uint32_t supertile_w_in_pixels = job->tile_width * supertile_w; 679bf215546Sopenharmony_ci uint32_t supertile_h_in_pixels = job->tile_height * supertile_h; 680bf215546Sopenharmony_ci uint32_t min_x_supertile = job->draw_min_x / supertile_w_in_pixels; 681bf215546Sopenharmony_ci uint32_t min_y_supertile = job->draw_min_y / supertile_h_in_pixels; 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci uint32_t max_x_supertile = 0; 684bf215546Sopenharmony_ci uint32_t max_y_supertile = 0; 685bf215546Sopenharmony_ci if (job->draw_max_x != 0 && job->draw_max_y != 0) { 686bf215546Sopenharmony_ci max_x_supertile = (job->draw_max_x - 1) / supertile_w_in_pixels; 687bf215546Sopenharmony_ci max_y_supertile = (job->draw_max_y - 1) / supertile_h_in_pixels; 688bf215546Sopenharmony_ci } 689bf215546Sopenharmony_ci 690bf215546Sopenharmony_ci for (int y = min_y_supertile; y <= max_y_supertile; y++) { 691bf215546Sopenharmony_ci for (int x = min_x_supertile; x <= max_x_supertile; x++) { 692bf215546Sopenharmony_ci if (supertile_in_job_scissors(job, x, y, 693bf215546Sopenharmony_ci supertile_w_in_pixels, 694bf215546Sopenharmony_ci supertile_h_in_pixels)) { 695bf215546Sopenharmony_ci cl_emit(&job->rcl, SUPERTILE_COORDINATES, coords) { 696bf215546Sopenharmony_ci coords.column_number_in_supertiles = x; 697bf215546Sopenharmony_ci coords.row_number_in_supertiles = y; 698bf215546Sopenharmony_ci } 699bf215546Sopenharmony_ci } 700bf215546Sopenharmony_ci } 701bf215546Sopenharmony_ci } 702bf215546Sopenharmony_ci} 703bf215546Sopenharmony_ci 704bf215546Sopenharmony_civoid 705bf215546Sopenharmony_civ3dX(emit_rcl)(struct v3d_job *job) 706bf215546Sopenharmony_ci{ 707bf215546Sopenharmony_ci /* The RCL list should be empty. */ 708bf215546Sopenharmony_ci assert(!job->rcl.bo); 709bf215546Sopenharmony_ci 710bf215546Sopenharmony_ci v3d_cl_ensure_space_with_branch(&job->rcl, 200 + 711bf215546Sopenharmony_ci MAX2(job->num_layers, 1) * 256 * 712bf215546Sopenharmony_ci cl_packet_length(SUPERTILE_COORDINATES)); 713bf215546Sopenharmony_ci job->submit.rcl_start = job->rcl.bo->offset; 714bf215546Sopenharmony_ci v3d_job_add_bo(job, job->rcl.bo); 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_ci /* Common config must be the first TILE_RENDERING_MODE_CFG 717bf215546Sopenharmony_ci * and Z_STENCIL_CLEAR_VALUES must be last. The ones in between are 718bf215546Sopenharmony_ci * optional updates to the previous HW state. 719bf215546Sopenharmony_ci */ 720bf215546Sopenharmony_ci cl_emit(&job->rcl, TILE_RENDERING_MODE_CFG_COMMON, config) { 721bf215546Sopenharmony_ci#if V3D_VERSION < 40 722bf215546Sopenharmony_ci config.enable_z_store = job->store & PIPE_CLEAR_DEPTH; 723bf215546Sopenharmony_ci config.enable_stencil_store = job->store & PIPE_CLEAR_STENCIL; 724bf215546Sopenharmony_ci#else /* V3D_VERSION >= 40 */ 725bf215546Sopenharmony_ci if (job->zsbuf) { 726bf215546Sopenharmony_ci struct v3d_surface *surf = v3d_surface(job->zsbuf); 727bf215546Sopenharmony_ci config.internal_depth_type = surf->internal_type; 728bf215546Sopenharmony_ci } 729bf215546Sopenharmony_ci#endif /* V3D_VERSION >= 40 */ 730bf215546Sopenharmony_ci 731bf215546Sopenharmony_ci if (job->decided_global_ez_enable) { 732bf215546Sopenharmony_ci switch (job->first_ez_state) { 733bf215546Sopenharmony_ci case V3D_EZ_UNDECIDED: 734bf215546Sopenharmony_ci case V3D_EZ_LT_LE: 735bf215546Sopenharmony_ci config.early_z_disable = false; 736bf215546Sopenharmony_ci config.early_z_test_and_update_direction = 737bf215546Sopenharmony_ci EARLY_Z_DIRECTION_LT_LE; 738bf215546Sopenharmony_ci break; 739bf215546Sopenharmony_ci case V3D_EZ_GT_GE: 740bf215546Sopenharmony_ci config.early_z_disable = false; 741bf215546Sopenharmony_ci config.early_z_test_and_update_direction = 742bf215546Sopenharmony_ci EARLY_Z_DIRECTION_GT_GE; 743bf215546Sopenharmony_ci break; 744bf215546Sopenharmony_ci case V3D_EZ_DISABLED: 745bf215546Sopenharmony_ci config.early_z_disable = true; 746bf215546Sopenharmony_ci } 747bf215546Sopenharmony_ci } else { 748bf215546Sopenharmony_ci assert(job->draw_calls_queued == 0); 749bf215546Sopenharmony_ci config.early_z_disable = true; 750bf215546Sopenharmony_ci } 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci#if V3D_VERSION >= 40 753bf215546Sopenharmony_ci assert(job->zsbuf || config.early_z_disable); 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_ci job->early_zs_clear = (job->clear & PIPE_CLEAR_DEPTHSTENCIL) && 756bf215546Sopenharmony_ci !(job->load & PIPE_CLEAR_DEPTHSTENCIL) && 757bf215546Sopenharmony_ci !(job->store & PIPE_CLEAR_DEPTHSTENCIL); 758bf215546Sopenharmony_ci 759bf215546Sopenharmony_ci config.early_depth_stencil_clear = job->early_zs_clear; 760bf215546Sopenharmony_ci#endif /* V3D_VERSION >= 40 */ 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ci config.image_width_pixels = job->draw_width; 763bf215546Sopenharmony_ci config.image_height_pixels = job->draw_height; 764bf215546Sopenharmony_ci 765bf215546Sopenharmony_ci config.number_of_render_targets = MAX2(job->nr_cbufs, 1); 766bf215546Sopenharmony_ci 767bf215546Sopenharmony_ci assert(!job->msaa || !job->double_buffer); 768bf215546Sopenharmony_ci config.multisample_mode_4x = job->msaa; 769bf215546Sopenharmony_ci config.double_buffer_in_non_ms_mode = job->double_buffer; 770bf215546Sopenharmony_ci 771bf215546Sopenharmony_ci config.maximum_bpp_of_all_render_targets = job->internal_bpp; 772bf215546Sopenharmony_ci } 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_ci for (int i = 0; i < job->nr_cbufs; i++) { 775bf215546Sopenharmony_ci struct pipe_surface *psurf = job->cbufs[i]; 776bf215546Sopenharmony_ci if (!psurf) 777bf215546Sopenharmony_ci continue; 778bf215546Sopenharmony_ci struct v3d_surface *surf = v3d_surface(psurf); 779bf215546Sopenharmony_ci struct v3d_resource *rsc = v3d_resource(psurf->texture); 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci UNUSED uint32_t config_pad = 0; 782bf215546Sopenharmony_ci uint32_t clear_pad = 0; 783bf215546Sopenharmony_ci 784bf215546Sopenharmony_ci /* XXX: Set the pad for raster. */ 785bf215546Sopenharmony_ci if (surf->tiling == V3D_TILING_UIF_NO_XOR || 786bf215546Sopenharmony_ci surf->tiling == V3D_TILING_UIF_XOR) { 787bf215546Sopenharmony_ci int uif_block_height = v3d_utile_height(rsc->cpp) * 2; 788bf215546Sopenharmony_ci uint32_t implicit_padded_height = (align(job->draw_height, uif_block_height) / 789bf215546Sopenharmony_ci uif_block_height); 790bf215546Sopenharmony_ci if (surf->padded_height_of_output_image_in_uif_blocks - 791bf215546Sopenharmony_ci implicit_padded_height < 15) { 792bf215546Sopenharmony_ci config_pad = (surf->padded_height_of_output_image_in_uif_blocks - 793bf215546Sopenharmony_ci implicit_padded_height); 794bf215546Sopenharmony_ci } else { 795bf215546Sopenharmony_ci config_pad = 15; 796bf215546Sopenharmony_ci clear_pad = surf->padded_height_of_output_image_in_uif_blocks; 797bf215546Sopenharmony_ci } 798bf215546Sopenharmony_ci } 799bf215546Sopenharmony_ci 800bf215546Sopenharmony_ci#if V3D_VERSION < 40 801bf215546Sopenharmony_ci cl_emit(&job->rcl, TILE_RENDERING_MODE_CFG_COLOR, rt) { 802bf215546Sopenharmony_ci rt.address = cl_address(rsc->bo, surf->offset); 803bf215546Sopenharmony_ci rt.internal_type = surf->internal_type; 804bf215546Sopenharmony_ci rt.output_image_format = surf->format; 805bf215546Sopenharmony_ci rt.memory_format = surf->tiling; 806bf215546Sopenharmony_ci rt.internal_bpp = surf->internal_bpp; 807bf215546Sopenharmony_ci rt.render_target_number = i; 808bf215546Sopenharmony_ci rt.pad = config_pad; 809bf215546Sopenharmony_ci 810bf215546Sopenharmony_ci if (job->store & PIPE_CLEAR_COLOR0 << i) 811bf215546Sopenharmony_ci rsc->writes++; 812bf215546Sopenharmony_ci } 813bf215546Sopenharmony_ci#endif /* V3D_VERSION < 40 */ 814bf215546Sopenharmony_ci 815bf215546Sopenharmony_ci cl_emit(&job->rcl, TILE_RENDERING_MODE_CFG_CLEAR_COLORS_PART1, 816bf215546Sopenharmony_ci clear) { 817bf215546Sopenharmony_ci clear.clear_color_low_32_bits = job->clear_color[i][0]; 818bf215546Sopenharmony_ci clear.clear_color_next_24_bits = job->clear_color[i][1] & 0xffffff; 819bf215546Sopenharmony_ci clear.render_target_number = i; 820bf215546Sopenharmony_ci }; 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_ci if (surf->internal_bpp >= V3D_INTERNAL_BPP_64) { 823bf215546Sopenharmony_ci cl_emit(&job->rcl, TILE_RENDERING_MODE_CFG_CLEAR_COLORS_PART2, 824bf215546Sopenharmony_ci clear) { 825bf215546Sopenharmony_ci clear.clear_color_mid_low_32_bits = 826bf215546Sopenharmony_ci ((job->clear_color[i][1] >> 24) | 827bf215546Sopenharmony_ci (job->clear_color[i][2] << 8)); 828bf215546Sopenharmony_ci clear.clear_color_mid_high_24_bits = 829bf215546Sopenharmony_ci ((job->clear_color[i][2] >> 24) | 830bf215546Sopenharmony_ci ((job->clear_color[i][3] & 0xffff) << 8)); 831bf215546Sopenharmony_ci clear.render_target_number = i; 832bf215546Sopenharmony_ci }; 833bf215546Sopenharmony_ci } 834bf215546Sopenharmony_ci 835bf215546Sopenharmony_ci if (surf->internal_bpp >= V3D_INTERNAL_BPP_128 || clear_pad) { 836bf215546Sopenharmony_ci cl_emit(&job->rcl, TILE_RENDERING_MODE_CFG_CLEAR_COLORS_PART3, 837bf215546Sopenharmony_ci clear) { 838bf215546Sopenharmony_ci clear.uif_padded_height_in_uif_blocks = clear_pad; 839bf215546Sopenharmony_ci clear.clear_color_high_16_bits = job->clear_color[i][3] >> 16; 840bf215546Sopenharmony_ci clear.render_target_number = i; 841bf215546Sopenharmony_ci }; 842bf215546Sopenharmony_ci } 843bf215546Sopenharmony_ci } 844bf215546Sopenharmony_ci 845bf215546Sopenharmony_ci#if V3D_VERSION >= 40 846bf215546Sopenharmony_ci cl_emit(&job->rcl, TILE_RENDERING_MODE_CFG_COLOR, rt) { 847bf215546Sopenharmony_ci v3d_setup_render_target(job, 0, 848bf215546Sopenharmony_ci &rt.render_target_0_internal_bpp, 849bf215546Sopenharmony_ci &rt.render_target_0_internal_type, 850bf215546Sopenharmony_ci &rt.render_target_0_clamp); 851bf215546Sopenharmony_ci v3d_setup_render_target(job, 1, 852bf215546Sopenharmony_ci &rt.render_target_1_internal_bpp, 853bf215546Sopenharmony_ci &rt.render_target_1_internal_type, 854bf215546Sopenharmony_ci &rt.render_target_1_clamp); 855bf215546Sopenharmony_ci v3d_setup_render_target(job, 2, 856bf215546Sopenharmony_ci &rt.render_target_2_internal_bpp, 857bf215546Sopenharmony_ci &rt.render_target_2_internal_type, 858bf215546Sopenharmony_ci &rt.render_target_2_clamp); 859bf215546Sopenharmony_ci v3d_setup_render_target(job, 3, 860bf215546Sopenharmony_ci &rt.render_target_3_internal_bpp, 861bf215546Sopenharmony_ci &rt.render_target_3_internal_type, 862bf215546Sopenharmony_ci &rt.render_target_3_clamp); 863bf215546Sopenharmony_ci } 864bf215546Sopenharmony_ci#endif 865bf215546Sopenharmony_ci 866bf215546Sopenharmony_ci#if V3D_VERSION < 40 867bf215546Sopenharmony_ci /* TODO: Don't bother emitting if we don't load/clear Z/S. */ 868bf215546Sopenharmony_ci if (job->zsbuf) { 869bf215546Sopenharmony_ci struct pipe_surface *psurf = job->zsbuf; 870bf215546Sopenharmony_ci struct v3d_surface *surf = v3d_surface(psurf); 871bf215546Sopenharmony_ci struct v3d_resource *rsc = v3d_resource(psurf->texture); 872bf215546Sopenharmony_ci 873bf215546Sopenharmony_ci v3d_emit_z_stencil_config(job, surf, rsc, false); 874bf215546Sopenharmony_ci 875bf215546Sopenharmony_ci /* Emit the separate stencil packet if we have a resource for 876bf215546Sopenharmony_ci * it. The HW will only load/store this buffer if the 877bf215546Sopenharmony_ci * Z/Stencil config doesn't have stencil in its format. 878bf215546Sopenharmony_ci */ 879bf215546Sopenharmony_ci if (surf->separate_stencil) { 880bf215546Sopenharmony_ci v3d_emit_z_stencil_config(job, 881bf215546Sopenharmony_ci v3d_surface(surf->separate_stencil), 882bf215546Sopenharmony_ci rsc->separate_stencil, true); 883bf215546Sopenharmony_ci } 884bf215546Sopenharmony_ci } 885bf215546Sopenharmony_ci#endif /* V3D_VERSION < 40 */ 886bf215546Sopenharmony_ci 887bf215546Sopenharmony_ci /* Ends rendering mode config. */ 888bf215546Sopenharmony_ci cl_emit(&job->rcl, TILE_RENDERING_MODE_CFG_ZS_CLEAR_VALUES, 889bf215546Sopenharmony_ci clear) { 890bf215546Sopenharmony_ci clear.z_clear_value = job->clear_z; 891bf215546Sopenharmony_ci clear.stencil_clear_value = job->clear_s; 892bf215546Sopenharmony_ci }; 893bf215546Sopenharmony_ci 894bf215546Sopenharmony_ci /* Always set initial block size before the first branch, which needs 895bf215546Sopenharmony_ci * to match the value from binning mode config. 896bf215546Sopenharmony_ci */ 897bf215546Sopenharmony_ci cl_emit(&job->rcl, TILE_LIST_INITIAL_BLOCK_SIZE, init) { 898bf215546Sopenharmony_ci init.use_auto_chained_tile_lists = true; 899bf215546Sopenharmony_ci init.size_of_first_block_in_chained_tile_lists = 900bf215546Sopenharmony_ci TILE_ALLOCATION_BLOCK_SIZE_64B; 901bf215546Sopenharmony_ci } 902bf215546Sopenharmony_ci 903bf215546Sopenharmony_ci /* ARB_framebuffer_no_attachments allows rendering to happen even when 904bf215546Sopenharmony_ci * the framebuffer has no attachments, the idea being that fragment 905bf215546Sopenharmony_ci * shaders can still do image load/store, ssbo, etc without having to 906bf215546Sopenharmony_ci * write to actual attachments, so always run at least one iteration 907bf215546Sopenharmony_ci * of the loop. 908bf215546Sopenharmony_ci */ 909bf215546Sopenharmony_ci assert(job->num_layers > 0 || (job->load == 0 && job->store == 0)); 910bf215546Sopenharmony_ci for (int layer = 0; layer < MAX2(1, job->num_layers); layer++) 911bf215546Sopenharmony_ci emit_render_layer(job, layer); 912bf215546Sopenharmony_ci 913bf215546Sopenharmony_ci cl_emit(&job->rcl, END_OF_RENDERING, end); 914bf215546Sopenharmony_ci} 915