1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2010 Jerome Glisse <glisse@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 * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci#include "r600_pipe.h" 24bf215546Sopenharmony_ci#include "compute_memory_pool.h" 25bf215546Sopenharmony_ci#include "evergreen_compute.h" 26bf215546Sopenharmony_ci#include "util/u_surface.h" 27bf215546Sopenharmony_ci#include "util/format/u_format.h" 28bf215546Sopenharmony_ci#include "evergreend.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_cienum r600_blitter_op /* bitmask */ 31bf215546Sopenharmony_ci{ 32bf215546Sopenharmony_ci R600_SAVE_FRAGMENT_STATE = 1, 33bf215546Sopenharmony_ci R600_SAVE_TEXTURES = 2, 34bf215546Sopenharmony_ci R600_SAVE_FRAMEBUFFER = 4, 35bf215546Sopenharmony_ci R600_DISABLE_RENDER_COND = 8, 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci R600_CLEAR = R600_SAVE_FRAGMENT_STATE, 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci R600_CLEAR_SURFACE = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER, 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci R600_COPY_BUFFER = R600_DISABLE_RENDER_COND, 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci R600_COPY_TEXTURE = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_SAVE_TEXTURES | 44bf215546Sopenharmony_ci R600_DISABLE_RENDER_COND, 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci R600_BLIT = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_SAVE_TEXTURES, 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci R600_DECOMPRESS = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_DISABLE_RENDER_COND, 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci R600_COLOR_RESOLVE = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER 51bf215546Sopenharmony_ci}; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_cistatic void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op) 54bf215546Sopenharmony_ci{ 55bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context *)ctx; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci if (rctx->cmd_buf_is_compute) { 58bf215546Sopenharmony_ci rctx->b.gfx.flush(rctx, PIPE_FLUSH_ASYNC, NULL); 59bf215546Sopenharmony_ci rctx->cmd_buf_is_compute = false; 60bf215546Sopenharmony_ci } 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci util_blitter_save_vertex_buffer_slot(rctx->blitter, rctx->vertex_buffer_state.vb); 63bf215546Sopenharmony_ci util_blitter_save_vertex_elements(rctx->blitter, rctx->vertex_fetch_shader.cso); 64bf215546Sopenharmony_ci util_blitter_save_vertex_shader(rctx->blitter, rctx->vs_shader); 65bf215546Sopenharmony_ci util_blitter_save_geometry_shader(rctx->blitter, rctx->gs_shader); 66bf215546Sopenharmony_ci util_blitter_save_tessctrl_shader(rctx->blitter, rctx->tcs_shader); 67bf215546Sopenharmony_ci util_blitter_save_tesseval_shader(rctx->blitter, rctx->tes_shader); 68bf215546Sopenharmony_ci util_blitter_save_so_targets(rctx->blitter, rctx->b.streamout.num_targets, 69bf215546Sopenharmony_ci (struct pipe_stream_output_target**)rctx->b.streamout.targets); 70bf215546Sopenharmony_ci util_blitter_save_rasterizer(rctx->blitter, rctx->rasterizer_state.cso); 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci if (op & R600_SAVE_FRAGMENT_STATE) { 73bf215546Sopenharmony_ci util_blitter_save_viewport(rctx->blitter, &rctx->b.viewports.states[0]); 74bf215546Sopenharmony_ci util_blitter_save_scissor(rctx->blitter, &rctx->b.scissors.states[0]); 75bf215546Sopenharmony_ci util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader); 76bf215546Sopenharmony_ci util_blitter_save_blend(rctx->blitter, rctx->blend_state.cso); 77bf215546Sopenharmony_ci util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->dsa_state.cso); 78bf215546Sopenharmony_ci util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref.pipe_state); 79bf215546Sopenharmony_ci util_blitter_save_sample_mask(rctx->blitter, rctx->sample_mask.sample_mask, rctx->ps_iter_samples); 80bf215546Sopenharmony_ci util_blitter_save_fragment_constant_buffer_slot(rctx->blitter, 81bf215546Sopenharmony_ci &rctx->constbuf_state[PIPE_SHADER_FRAGMENT].cb[0]); 82bf215546Sopenharmony_ci } 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci if (op & R600_SAVE_FRAMEBUFFER) 85bf215546Sopenharmony_ci util_blitter_save_framebuffer(rctx->blitter, &rctx->framebuffer.state); 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci if (op & R600_SAVE_TEXTURES) { 88bf215546Sopenharmony_ci util_blitter_save_fragment_sampler_states( 89bf215546Sopenharmony_ci rctx->blitter, util_last_bit(rctx->samplers[PIPE_SHADER_FRAGMENT].states.enabled_mask), 90bf215546Sopenharmony_ci (void**)rctx->samplers[PIPE_SHADER_FRAGMENT].states.states); 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci util_blitter_save_fragment_sampler_views( 93bf215546Sopenharmony_ci rctx->blitter, util_last_bit(rctx->samplers[PIPE_SHADER_FRAGMENT].views.enabled_mask), 94bf215546Sopenharmony_ci (struct pipe_sampler_view**)rctx->samplers[PIPE_SHADER_FRAGMENT].views.views); 95bf215546Sopenharmony_ci } 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci if (op & R600_DISABLE_RENDER_COND) 98bf215546Sopenharmony_ci rctx->b.render_cond_force_off = true; 99bf215546Sopenharmony_ci} 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_cistatic void r600_blitter_end(struct pipe_context *ctx) 102bf215546Sopenharmony_ci{ 103bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context *)ctx; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci rctx->b.render_cond_force_off = false; 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_cistatic unsigned u_max_sample(struct pipe_resource *r) 109bf215546Sopenharmony_ci{ 110bf215546Sopenharmony_ci return r->nr_samples ? r->nr_samples - 1 : 0; 111bf215546Sopenharmony_ci} 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_cistatic void r600_blit_decompress_depth(struct pipe_context *ctx, 114bf215546Sopenharmony_ci struct r600_texture *texture, 115bf215546Sopenharmony_ci struct r600_texture *staging, 116bf215546Sopenharmony_ci unsigned first_level, unsigned last_level, 117bf215546Sopenharmony_ci unsigned first_layer, unsigned last_layer, 118bf215546Sopenharmony_ci unsigned first_sample, unsigned last_sample) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context *)ctx; 121bf215546Sopenharmony_ci unsigned layer, level, sample, checked_last_layer, max_layer, max_sample; 122bf215546Sopenharmony_ci struct r600_texture *flushed_depth_texture = staging ? 123bf215546Sopenharmony_ci staging : texture->flushed_depth_texture; 124bf215546Sopenharmony_ci const struct util_format_description *desc = 125bf215546Sopenharmony_ci util_format_description(texture->resource.b.b.format); 126bf215546Sopenharmony_ci float depth; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci if (!staging && !texture->dirty_level_mask) 129bf215546Sopenharmony_ci return; 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci max_sample = u_max_sample(&texture->resource.b.b); 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci /* XXX Decompressing MSAA depth textures is broken on R6xx. 134bf215546Sopenharmony_ci * There is also a hardlock if CMASK and FMASK are not present. 135bf215546Sopenharmony_ci * Just skip this until we find out how to fix it. */ 136bf215546Sopenharmony_ci if (rctx->b.gfx_level == R600 && max_sample > 0) { 137bf215546Sopenharmony_ci texture->dirty_level_mask = 0; 138bf215546Sopenharmony_ci return; 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci if (rctx->b.family == CHIP_RV610 || rctx->b.family == CHIP_RV630 || 142bf215546Sopenharmony_ci rctx->b.family == CHIP_RV620 || rctx->b.family == CHIP_RV635) 143bf215546Sopenharmony_ci depth = 0.0f; 144bf215546Sopenharmony_ci else 145bf215546Sopenharmony_ci depth = 1.0f; 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci /* Enable decompression in DB_RENDER_CONTROL */ 148bf215546Sopenharmony_ci rctx->db_misc_state.flush_depthstencil_through_cb = true; 149bf215546Sopenharmony_ci rctx->db_misc_state.copy_depth = util_format_has_depth(desc); 150bf215546Sopenharmony_ci rctx->db_misc_state.copy_stencil = util_format_has_stencil(desc); 151bf215546Sopenharmony_ci rctx->db_misc_state.copy_sample = first_sample; 152bf215546Sopenharmony_ci r600_mark_atom_dirty(rctx, &rctx->db_misc_state.atom); 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci for (level = first_level; level <= last_level; level++) { 155bf215546Sopenharmony_ci if (!staging && !(texture->dirty_level_mask & (1 << level))) 156bf215546Sopenharmony_ci continue; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci /* The smaller the mipmap level, the less layers there are 159bf215546Sopenharmony_ci * as far as 3D textures are concerned. */ 160bf215546Sopenharmony_ci max_layer = util_max_layer(&texture->resource.b.b, level); 161bf215546Sopenharmony_ci checked_last_layer = last_layer < max_layer ? last_layer : max_layer; 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci for (layer = first_layer; layer <= checked_last_layer; layer++) { 164bf215546Sopenharmony_ci for (sample = first_sample; sample <= last_sample; sample++) { 165bf215546Sopenharmony_ci struct pipe_surface *zsurf, *cbsurf, surf_tmpl; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci if (sample != rctx->db_misc_state.copy_sample) { 168bf215546Sopenharmony_ci rctx->db_misc_state.copy_sample = sample; 169bf215546Sopenharmony_ci r600_mark_atom_dirty(rctx, &rctx->db_misc_state.atom); 170bf215546Sopenharmony_ci } 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci surf_tmpl.format = texture->resource.b.b.format; 173bf215546Sopenharmony_ci surf_tmpl.u.tex.level = level; 174bf215546Sopenharmony_ci surf_tmpl.u.tex.first_layer = layer; 175bf215546Sopenharmony_ci surf_tmpl.u.tex.last_layer = layer; 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci zsurf = ctx->create_surface(ctx, &texture->resource.b.b, &surf_tmpl); 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci surf_tmpl.format = flushed_depth_texture->resource.b.b.format; 180bf215546Sopenharmony_ci cbsurf = ctx->create_surface(ctx, 181bf215546Sopenharmony_ci &flushed_depth_texture->resource.b.b, &surf_tmpl); 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci r600_blitter_begin(ctx, R600_DECOMPRESS); 184bf215546Sopenharmony_ci util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, 1 << sample, 185bf215546Sopenharmony_ci rctx->custom_dsa_flush, depth); 186bf215546Sopenharmony_ci r600_blitter_end(ctx); 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci pipe_surface_reference(&zsurf, NULL); 189bf215546Sopenharmony_ci pipe_surface_reference(&cbsurf, NULL); 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci } 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci /* The texture will always be dirty if some layers or samples aren't flushed. 194bf215546Sopenharmony_ci * I don't think this case occurs often though. */ 195bf215546Sopenharmony_ci if (!staging && 196bf215546Sopenharmony_ci first_layer == 0 && last_layer == max_layer && 197bf215546Sopenharmony_ci first_sample == 0 && last_sample == max_sample) { 198bf215546Sopenharmony_ci texture->dirty_level_mask &= ~(1 << level); 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci } 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci /* reenable compression in DB_RENDER_CONTROL */ 203bf215546Sopenharmony_ci rctx->db_misc_state.flush_depthstencil_through_cb = false; 204bf215546Sopenharmony_ci r600_mark_atom_dirty(rctx, &rctx->db_misc_state.atom); 205bf215546Sopenharmony_ci} 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_cistatic void r600_blit_decompress_depth_in_place(struct r600_context *rctx, 208bf215546Sopenharmony_ci struct r600_texture *texture, 209bf215546Sopenharmony_ci bool is_stencil_sampler, 210bf215546Sopenharmony_ci unsigned first_level, unsigned last_level, 211bf215546Sopenharmony_ci unsigned first_layer, unsigned last_layer) 212bf215546Sopenharmony_ci{ 213bf215546Sopenharmony_ci struct pipe_surface *zsurf, surf_tmpl = {{0}}; 214bf215546Sopenharmony_ci unsigned layer, max_layer, checked_last_layer, level; 215bf215546Sopenharmony_ci unsigned *dirty_level_mask; 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci /* Enable decompression in DB_RENDER_CONTROL */ 218bf215546Sopenharmony_ci if (is_stencil_sampler) { 219bf215546Sopenharmony_ci rctx->db_misc_state.flush_stencil_inplace = true; 220bf215546Sopenharmony_ci dirty_level_mask = &texture->stencil_dirty_level_mask; 221bf215546Sopenharmony_ci } else { 222bf215546Sopenharmony_ci rctx->db_misc_state.flush_depth_inplace = true; 223bf215546Sopenharmony_ci dirty_level_mask = &texture->dirty_level_mask; 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci r600_mark_atom_dirty(rctx, &rctx->db_misc_state.atom); 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci surf_tmpl.format = texture->resource.b.b.format; 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci for (level = first_level; level <= last_level; level++) { 230bf215546Sopenharmony_ci if (!(*dirty_level_mask & (1 << level))) 231bf215546Sopenharmony_ci continue; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci surf_tmpl.u.tex.level = level; 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci /* The smaller the mipmap level, the less layers there are 236bf215546Sopenharmony_ci * as far as 3D textures are concerned. */ 237bf215546Sopenharmony_ci max_layer = util_max_layer(&texture->resource.b.b, level); 238bf215546Sopenharmony_ci checked_last_layer = last_layer < max_layer ? last_layer : max_layer; 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci for (layer = first_layer; layer <= checked_last_layer; layer++) { 241bf215546Sopenharmony_ci surf_tmpl.u.tex.first_layer = layer; 242bf215546Sopenharmony_ci surf_tmpl.u.tex.last_layer = layer; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci zsurf = rctx->b.b.create_surface(&rctx->b.b, &texture->resource.b.b, &surf_tmpl); 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci r600_blitter_begin(&rctx->b.b, R600_DECOMPRESS); 247bf215546Sopenharmony_ci util_blitter_custom_depth_stencil(rctx->blitter, zsurf, NULL, ~0, 248bf215546Sopenharmony_ci rctx->custom_dsa_flush, 1.0f); 249bf215546Sopenharmony_ci r600_blitter_end(&rctx->b.b); 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci pipe_surface_reference(&zsurf, NULL); 252bf215546Sopenharmony_ci } 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci /* The texture will always be dirty if some layers or samples aren't flushed. 255bf215546Sopenharmony_ci * I don't think this case occurs often though. */ 256bf215546Sopenharmony_ci if (first_layer == 0 && last_layer == max_layer) { 257bf215546Sopenharmony_ci *dirty_level_mask &= ~(1 << level); 258bf215546Sopenharmony_ci } 259bf215546Sopenharmony_ci } 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci /* Disable decompression in DB_RENDER_CONTROL */ 262bf215546Sopenharmony_ci rctx->db_misc_state.flush_depth_inplace = false; 263bf215546Sopenharmony_ci rctx->db_misc_state.flush_stencil_inplace = false; 264bf215546Sopenharmony_ci r600_mark_atom_dirty(rctx, &rctx->db_misc_state.atom); 265bf215546Sopenharmony_ci} 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_civoid r600_decompress_depth_textures(struct r600_context *rctx, 268bf215546Sopenharmony_ci struct r600_samplerview_state *textures) 269bf215546Sopenharmony_ci{ 270bf215546Sopenharmony_ci unsigned i; 271bf215546Sopenharmony_ci unsigned depth_texture_mask = textures->compressed_depthtex_mask; 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci while (depth_texture_mask) { 274bf215546Sopenharmony_ci struct pipe_sampler_view *view; 275bf215546Sopenharmony_ci struct r600_pipe_sampler_view *rview; 276bf215546Sopenharmony_ci struct r600_texture *tex; 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci i = u_bit_scan(&depth_texture_mask); 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci view = &textures->views[i]->base; 281bf215546Sopenharmony_ci assert(view); 282bf215546Sopenharmony_ci rview = (struct r600_pipe_sampler_view*)view; 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci tex = (struct r600_texture *)view->texture; 285bf215546Sopenharmony_ci assert(tex->db_compatible); 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci if (r600_can_sample_zs(tex, rview->is_stencil_sampler)) { 288bf215546Sopenharmony_ci r600_blit_decompress_depth_in_place(rctx, tex, 289bf215546Sopenharmony_ci rview->is_stencil_sampler, 290bf215546Sopenharmony_ci view->u.tex.first_level, view->u.tex.last_level, 291bf215546Sopenharmony_ci 0, util_max_layer(&tex->resource.b.b, view->u.tex.first_level)); 292bf215546Sopenharmony_ci } else { 293bf215546Sopenharmony_ci r600_blit_decompress_depth(&rctx->b.b, tex, NULL, 294bf215546Sopenharmony_ci view->u.tex.first_level, view->u.tex.last_level, 295bf215546Sopenharmony_ci 0, util_max_layer(&tex->resource.b.b, view->u.tex.first_level), 296bf215546Sopenharmony_ci 0, u_max_sample(&tex->resource.b.b)); 297bf215546Sopenharmony_ci } 298bf215546Sopenharmony_ci } 299bf215546Sopenharmony_ci} 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_civoid r600_decompress_depth_images(struct r600_context *rctx, 302bf215546Sopenharmony_ci struct r600_image_state *images) 303bf215546Sopenharmony_ci{ 304bf215546Sopenharmony_ci unsigned i; 305bf215546Sopenharmony_ci unsigned depth_texture_mask = images->compressed_depthtex_mask; 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci while (depth_texture_mask) { 308bf215546Sopenharmony_ci struct r600_image_view *view; 309bf215546Sopenharmony_ci struct r600_texture *tex; 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci i = u_bit_scan(&depth_texture_mask); 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci view = &images->views[i]; 314bf215546Sopenharmony_ci assert(view); 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci tex = (struct r600_texture *)view->base.resource; 317bf215546Sopenharmony_ci assert(tex->db_compatible); 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci if (r600_can_sample_zs(tex, false)) { 320bf215546Sopenharmony_ci r600_blit_decompress_depth_in_place(rctx, tex, 321bf215546Sopenharmony_ci false, 322bf215546Sopenharmony_ci view->base.u.tex.level, 323bf215546Sopenharmony_ci view->base.u.tex.level, 324bf215546Sopenharmony_ci 0, util_max_layer(&tex->resource.b.b, view->base.u.tex.level)); 325bf215546Sopenharmony_ci } else { 326bf215546Sopenharmony_ci r600_blit_decompress_depth(&rctx->b.b, tex, NULL, 327bf215546Sopenharmony_ci view->base.u.tex.level, 328bf215546Sopenharmony_ci view->base.u.tex.level, 329bf215546Sopenharmony_ci 0, util_max_layer(&tex->resource.b.b, view->base.u.tex.level), 330bf215546Sopenharmony_ci 0, u_max_sample(&tex->resource.b.b)); 331bf215546Sopenharmony_ci } 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci} 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_cistatic void r600_blit_decompress_color(struct pipe_context *ctx, 336bf215546Sopenharmony_ci struct r600_texture *rtex, 337bf215546Sopenharmony_ci unsigned first_level, unsigned last_level, 338bf215546Sopenharmony_ci unsigned first_layer, unsigned last_layer) 339bf215546Sopenharmony_ci{ 340bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context *)ctx; 341bf215546Sopenharmony_ci unsigned layer, level, checked_last_layer, max_layer; 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci if (!rtex->dirty_level_mask) 344bf215546Sopenharmony_ci return; 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci for (level = first_level; level <= last_level; level++) { 347bf215546Sopenharmony_ci if (!(rtex->dirty_level_mask & (1 << level))) 348bf215546Sopenharmony_ci continue; 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci /* The smaller the mipmap level, the less layers there are 351bf215546Sopenharmony_ci * as far as 3D textures are concerned. */ 352bf215546Sopenharmony_ci max_layer = util_max_layer(&rtex->resource.b.b, level); 353bf215546Sopenharmony_ci checked_last_layer = last_layer < max_layer ? last_layer : max_layer; 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci for (layer = first_layer; layer <= checked_last_layer; layer++) { 356bf215546Sopenharmony_ci struct pipe_surface *cbsurf, surf_tmpl; 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci surf_tmpl.format = rtex->resource.b.b.format; 359bf215546Sopenharmony_ci surf_tmpl.u.tex.level = level; 360bf215546Sopenharmony_ci surf_tmpl.u.tex.first_layer = layer; 361bf215546Sopenharmony_ci surf_tmpl.u.tex.last_layer = layer; 362bf215546Sopenharmony_ci cbsurf = ctx->create_surface(ctx, &rtex->resource.b.b, &surf_tmpl); 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci r600_blitter_begin(ctx, R600_DECOMPRESS); 365bf215546Sopenharmony_ci util_blitter_custom_color(rctx->blitter, cbsurf, 366bf215546Sopenharmony_ci rtex->fmask.size ? rctx->custom_blend_decompress : rctx->custom_blend_fastclear); 367bf215546Sopenharmony_ci r600_blitter_end(ctx); 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci pipe_surface_reference(&cbsurf, NULL); 370bf215546Sopenharmony_ci } 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci /* The texture will always be dirty if some layers aren't flushed. 373bf215546Sopenharmony_ci * I don't think this case occurs often though. */ 374bf215546Sopenharmony_ci if (first_layer == 0 && last_layer == max_layer) { 375bf215546Sopenharmony_ci rtex->dirty_level_mask &= ~(1 << level); 376bf215546Sopenharmony_ci } 377bf215546Sopenharmony_ci } 378bf215546Sopenharmony_ci} 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_civoid r600_decompress_color_textures(struct r600_context *rctx, 381bf215546Sopenharmony_ci struct r600_samplerview_state *textures) 382bf215546Sopenharmony_ci{ 383bf215546Sopenharmony_ci unsigned i; 384bf215546Sopenharmony_ci unsigned mask = textures->compressed_colortex_mask; 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci while (mask) { 387bf215546Sopenharmony_ci struct pipe_sampler_view *view; 388bf215546Sopenharmony_ci struct r600_texture *tex; 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci i = u_bit_scan(&mask); 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci view = &textures->views[i]->base; 393bf215546Sopenharmony_ci assert(view); 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci tex = (struct r600_texture *)view->texture; 396bf215546Sopenharmony_ci assert(tex->cmask.size); 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci r600_blit_decompress_color(&rctx->b.b, tex, 399bf215546Sopenharmony_ci view->u.tex.first_level, view->u.tex.last_level, 400bf215546Sopenharmony_ci 0, util_max_layer(&tex->resource.b.b, view->u.tex.first_level)); 401bf215546Sopenharmony_ci } 402bf215546Sopenharmony_ci} 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_civoid r600_decompress_color_images(struct r600_context *rctx, 405bf215546Sopenharmony_ci struct r600_image_state *images) 406bf215546Sopenharmony_ci{ 407bf215546Sopenharmony_ci unsigned i; 408bf215546Sopenharmony_ci unsigned mask = images->compressed_colortex_mask; 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci while (mask) { 411bf215546Sopenharmony_ci struct r600_image_view *view; 412bf215546Sopenharmony_ci struct r600_texture *tex; 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci i = u_bit_scan(&mask); 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci view = &images->views[i]; 417bf215546Sopenharmony_ci assert(view); 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci tex = (struct r600_texture *)view->base.resource; 420bf215546Sopenharmony_ci assert(tex->cmask.size); 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci r600_blit_decompress_color(&rctx->b.b, tex, 423bf215546Sopenharmony_ci view->base.u.tex.level, view->base.u.tex.level, 424bf215546Sopenharmony_ci view->base.u.tex.first_layer, 425bf215546Sopenharmony_ci view->base.u.tex.last_layer); 426bf215546Sopenharmony_ci } 427bf215546Sopenharmony_ci} 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci/* Helper for decompressing a portion of a color or depth resource before 430bf215546Sopenharmony_ci * blitting if any decompression is needed. 431bf215546Sopenharmony_ci * The driver doesn't decompress resources automatically while u_blitter is 432bf215546Sopenharmony_ci * rendering. */ 433bf215546Sopenharmony_cistatic bool r600_decompress_subresource(struct pipe_context *ctx, 434bf215546Sopenharmony_ci struct pipe_resource *tex, 435bf215546Sopenharmony_ci unsigned level, 436bf215546Sopenharmony_ci unsigned first_layer, unsigned last_layer) 437bf215546Sopenharmony_ci{ 438bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context *)ctx; 439bf215546Sopenharmony_ci struct r600_texture *rtex = (struct r600_texture*)tex; 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci if (rtex->db_compatible) { 442bf215546Sopenharmony_ci if (r600_can_sample_zs(rtex, false)) { 443bf215546Sopenharmony_ci r600_blit_decompress_depth_in_place(rctx, rtex, false, 444bf215546Sopenharmony_ci level, level, 445bf215546Sopenharmony_ci first_layer, last_layer); 446bf215546Sopenharmony_ci if (rtex->surface.has_stencil) { 447bf215546Sopenharmony_ci r600_blit_decompress_depth_in_place(rctx, rtex, true, 448bf215546Sopenharmony_ci level, level, 449bf215546Sopenharmony_ci first_layer, last_layer); 450bf215546Sopenharmony_ci } 451bf215546Sopenharmony_ci } else { 452bf215546Sopenharmony_ci if (!r600_init_flushed_depth_texture(ctx, tex, NULL)) 453bf215546Sopenharmony_ci return false; /* error */ 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci r600_blit_decompress_depth(ctx, rtex, NULL, 456bf215546Sopenharmony_ci level, level, 457bf215546Sopenharmony_ci first_layer, last_layer, 458bf215546Sopenharmony_ci 0, u_max_sample(tex)); 459bf215546Sopenharmony_ci } 460bf215546Sopenharmony_ci } else if (rtex->cmask.size) { 461bf215546Sopenharmony_ci r600_blit_decompress_color(ctx, rtex, level, level, 462bf215546Sopenharmony_ci first_layer, last_layer); 463bf215546Sopenharmony_ci } 464bf215546Sopenharmony_ci return true; 465bf215546Sopenharmony_ci} 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_cistatic void r600_clear(struct pipe_context *ctx, unsigned buffers, 468bf215546Sopenharmony_ci const struct pipe_scissor_state *scissor_state, 469bf215546Sopenharmony_ci const union pipe_color_union *color, 470bf215546Sopenharmony_ci double depth, unsigned stencil) 471bf215546Sopenharmony_ci{ 472bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context *)ctx; 473bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb = &rctx->framebuffer.state; 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_COLOR && rctx->b.gfx_level >= EVERGREEN) { 476bf215546Sopenharmony_ci evergreen_do_fast_color_clear(&rctx->b, fb, &rctx->framebuffer.atom, 477bf215546Sopenharmony_ci &buffers, NULL, color); 478bf215546Sopenharmony_ci if (!buffers) 479bf215546Sopenharmony_ci return; /* all buffers have been fast cleared */ 480bf215546Sopenharmony_ci } 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci if (buffers & PIPE_CLEAR_COLOR) { 483bf215546Sopenharmony_ci int i; 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci /* These buffers cannot use fast clear, make sure to disable expansion. */ 486bf215546Sopenharmony_ci for (i = 0; i < fb->nr_cbufs; i++) { 487bf215546Sopenharmony_ci struct r600_texture *tex; 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci /* If not clearing this buffer, skip. */ 490bf215546Sopenharmony_ci if (!(buffers & (PIPE_CLEAR_COLOR0 << i))) 491bf215546Sopenharmony_ci continue; 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci if (!fb->cbufs[i]) 494bf215546Sopenharmony_ci continue; 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci tex = (struct r600_texture *)fb->cbufs[i]->texture; 497bf215546Sopenharmony_ci if (tex->fmask.size == 0) 498bf215546Sopenharmony_ci tex->dirty_level_mask &= ~(1 << fb->cbufs[i]->u.tex.level); 499bf215546Sopenharmony_ci } 500bf215546Sopenharmony_ci } 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ci /* if hyperz enabled just clear hyperz */ 503bf215546Sopenharmony_ci if (fb->zsbuf && (buffers & PIPE_CLEAR_DEPTH)) { 504bf215546Sopenharmony_ci struct r600_texture *rtex; 505bf215546Sopenharmony_ci unsigned level = fb->zsbuf->u.tex.level; 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci rtex = (struct r600_texture*)fb->zsbuf->texture; 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci /* We can't use hyperz fast clear if each slice of a texture 510bf215546Sopenharmony_ci * array are clear to different value. To simplify code just 511bf215546Sopenharmony_ci * disable fast clear for texture array. 512bf215546Sopenharmony_ci */ 513bf215546Sopenharmony_ci if (r600_htile_enabled(rtex, level) && 514bf215546Sopenharmony_ci fb->zsbuf->u.tex.first_layer == 0 && 515bf215546Sopenharmony_ci fb->zsbuf->u.tex.last_layer == util_max_layer(&rtex->resource.b.b, level)) { 516bf215546Sopenharmony_ci if (rtex->depth_clear_value != depth) { 517bf215546Sopenharmony_ci rtex->depth_clear_value = depth; 518bf215546Sopenharmony_ci r600_mark_atom_dirty(rctx, &rctx->db_state.atom); 519bf215546Sopenharmony_ci } 520bf215546Sopenharmony_ci rctx->db_misc_state.htile_clear = true; 521bf215546Sopenharmony_ci r600_mark_atom_dirty(rctx, &rctx->db_misc_state.atom); 522bf215546Sopenharmony_ci } 523bf215546Sopenharmony_ci } 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci r600_blitter_begin(ctx, R600_CLEAR); 526bf215546Sopenharmony_ci util_blitter_clear(rctx->blitter, fb->width, fb->height, 527bf215546Sopenharmony_ci util_framebuffer_get_num_layers(fb), 528bf215546Sopenharmony_ci buffers, color, depth, stencil, 529bf215546Sopenharmony_ci util_framebuffer_get_num_samples(fb) > 1); 530bf215546Sopenharmony_ci r600_blitter_end(ctx); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci /* disable fast clear */ 533bf215546Sopenharmony_ci if (rctx->db_misc_state.htile_clear) { 534bf215546Sopenharmony_ci rctx->db_misc_state.htile_clear = false; 535bf215546Sopenharmony_ci r600_mark_atom_dirty(rctx, &rctx->db_misc_state.atom); 536bf215546Sopenharmony_ci } 537bf215546Sopenharmony_ci} 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_cistatic void r600_clear_render_target(struct pipe_context *ctx, 540bf215546Sopenharmony_ci struct pipe_surface *dst, 541bf215546Sopenharmony_ci const union pipe_color_union *color, 542bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, 543bf215546Sopenharmony_ci unsigned width, unsigned height, 544bf215546Sopenharmony_ci bool render_condition_enabled) 545bf215546Sopenharmony_ci{ 546bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context *)ctx; 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_ci r600_blitter_begin(ctx, R600_CLEAR_SURFACE | 549bf215546Sopenharmony_ci (render_condition_enabled ? 0 : R600_DISABLE_RENDER_COND)); 550bf215546Sopenharmony_ci util_blitter_clear_render_target(rctx->blitter, dst, color, 551bf215546Sopenharmony_ci dstx, dsty, width, height); 552bf215546Sopenharmony_ci r600_blitter_end(ctx); 553bf215546Sopenharmony_ci} 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_cistatic void r600_clear_depth_stencil(struct pipe_context *ctx, 556bf215546Sopenharmony_ci struct pipe_surface *dst, 557bf215546Sopenharmony_ci unsigned clear_flags, 558bf215546Sopenharmony_ci double depth, 559bf215546Sopenharmony_ci unsigned stencil, 560bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, 561bf215546Sopenharmony_ci unsigned width, unsigned height, 562bf215546Sopenharmony_ci bool render_condition_enabled) 563bf215546Sopenharmony_ci{ 564bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context *)ctx; 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci r600_blitter_begin(ctx, R600_CLEAR_SURFACE | 567bf215546Sopenharmony_ci (render_condition_enabled ? 0 : R600_DISABLE_RENDER_COND)); 568bf215546Sopenharmony_ci util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil, 569bf215546Sopenharmony_ci dstx, dsty, width, height); 570bf215546Sopenharmony_ci r600_blitter_end(ctx); 571bf215546Sopenharmony_ci} 572bf215546Sopenharmony_ci 573bf215546Sopenharmony_cistatic void r600_copy_buffer(struct pipe_context *ctx, struct pipe_resource *dst, unsigned dstx, 574bf215546Sopenharmony_ci struct pipe_resource *src, const struct pipe_box *src_box) 575bf215546Sopenharmony_ci{ 576bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context*)ctx; 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci if (rctx->screen->b.has_cp_dma) 579bf215546Sopenharmony_ci r600_cp_dma_copy_buffer(rctx, dst, dstx, src, src_box->x, src_box->width); 580bf215546Sopenharmony_ci else 581bf215546Sopenharmony_ci util_resource_copy_region(ctx, dst, 0, dstx, 0, 0, src, 0, src_box); 582bf215546Sopenharmony_ci} 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci/** 585bf215546Sopenharmony_ci * Global buffers are not really resources, they are are actually offsets 586bf215546Sopenharmony_ci * into a single global resource (r600_screen::global_pool). The means 587bf215546Sopenharmony_ci * they don't have their own buf handle, so they cannot be passed 588bf215546Sopenharmony_ci * to r600_copy_buffer() and must be handled separately. 589bf215546Sopenharmony_ci */ 590bf215546Sopenharmony_cistatic void r600_copy_global_buffer(struct pipe_context *ctx, 591bf215546Sopenharmony_ci struct pipe_resource *dst, unsigned 592bf215546Sopenharmony_ci dstx, struct pipe_resource *src, 593bf215546Sopenharmony_ci const struct pipe_box *src_box) 594bf215546Sopenharmony_ci{ 595bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context*)ctx; 596bf215546Sopenharmony_ci struct compute_memory_pool *pool = rctx->screen->global_pool; 597bf215546Sopenharmony_ci struct pipe_box new_src_box = *src_box; 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_ci if (src->bind & PIPE_BIND_GLOBAL) { 600bf215546Sopenharmony_ci struct r600_resource_global *rsrc = 601bf215546Sopenharmony_ci (struct r600_resource_global *)src; 602bf215546Sopenharmony_ci struct compute_memory_item *item = rsrc->chunk; 603bf215546Sopenharmony_ci 604bf215546Sopenharmony_ci if (is_item_in_pool(item)) { 605bf215546Sopenharmony_ci new_src_box.x += 4 * item->start_in_dw; 606bf215546Sopenharmony_ci src = (struct pipe_resource *)pool->bo; 607bf215546Sopenharmony_ci } else { 608bf215546Sopenharmony_ci if (item->real_buffer == NULL) { 609bf215546Sopenharmony_ci item->real_buffer = 610bf215546Sopenharmony_ci r600_compute_buffer_alloc_vram(pool->screen, 611bf215546Sopenharmony_ci item->size_in_dw * 4); 612bf215546Sopenharmony_ci } 613bf215546Sopenharmony_ci src = (struct pipe_resource*)item->real_buffer; 614bf215546Sopenharmony_ci } 615bf215546Sopenharmony_ci } 616bf215546Sopenharmony_ci if (dst->bind & PIPE_BIND_GLOBAL) { 617bf215546Sopenharmony_ci struct r600_resource_global *rdst = 618bf215546Sopenharmony_ci (struct r600_resource_global *)dst; 619bf215546Sopenharmony_ci struct compute_memory_item *item = rdst->chunk; 620bf215546Sopenharmony_ci 621bf215546Sopenharmony_ci if (is_item_in_pool(item)) { 622bf215546Sopenharmony_ci dstx += 4 * item->start_in_dw; 623bf215546Sopenharmony_ci dst = (struct pipe_resource *)pool->bo; 624bf215546Sopenharmony_ci } else { 625bf215546Sopenharmony_ci if (item->real_buffer == NULL) { 626bf215546Sopenharmony_ci item->real_buffer = 627bf215546Sopenharmony_ci r600_compute_buffer_alloc_vram(pool->screen, 628bf215546Sopenharmony_ci item->size_in_dw * 4); 629bf215546Sopenharmony_ci } 630bf215546Sopenharmony_ci dst = (struct pipe_resource*)item->real_buffer; 631bf215546Sopenharmony_ci } 632bf215546Sopenharmony_ci } 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci r600_copy_buffer(ctx, dst, dstx, src, &new_src_box); 635bf215546Sopenharmony_ci} 636bf215546Sopenharmony_ci 637bf215546Sopenharmony_cistatic void r600_clear_buffer(struct pipe_context *ctx, struct pipe_resource *dst, 638bf215546Sopenharmony_ci uint64_t offset, uint64_t size, unsigned value, 639bf215546Sopenharmony_ci enum r600_coherency coher) 640bf215546Sopenharmony_ci{ 641bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context*)ctx; 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci if (rctx->screen->b.has_cp_dma && 644bf215546Sopenharmony_ci rctx->b.gfx_level >= EVERGREEN && 645bf215546Sopenharmony_ci offset % 4 == 0 && size % 4 == 0) { 646bf215546Sopenharmony_ci evergreen_cp_dma_clear_buffer(rctx, dst, offset, size, value, coher); 647bf215546Sopenharmony_ci } else if (rctx->screen->b.has_streamout && offset % 4 == 0 && size % 4 == 0) { 648bf215546Sopenharmony_ci union pipe_color_union clear_value; 649bf215546Sopenharmony_ci clear_value.ui[0] = value; 650bf215546Sopenharmony_ci 651bf215546Sopenharmony_ci r600_blitter_begin(ctx, R600_DISABLE_RENDER_COND); 652bf215546Sopenharmony_ci util_blitter_clear_buffer(rctx->blitter, dst, offset, size, 653bf215546Sopenharmony_ci 1, &clear_value); 654bf215546Sopenharmony_ci r600_blitter_end(ctx); 655bf215546Sopenharmony_ci } else { 656bf215546Sopenharmony_ci uint32_t *map = r600_buffer_map_sync_with_rings(&rctx->b, r600_resource(dst), 657bf215546Sopenharmony_ci PIPE_MAP_WRITE); 658bf215546Sopenharmony_ci map += offset / 4; 659bf215546Sopenharmony_ci size /= 4; 660bf215546Sopenharmony_ci for (unsigned i = 0; i < size; i++) 661bf215546Sopenharmony_ci *map++ = value; 662bf215546Sopenharmony_ci } 663bf215546Sopenharmony_ci} 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_civoid r600_resource_copy_region(struct pipe_context *ctx, 666bf215546Sopenharmony_ci struct pipe_resource *dst, 667bf215546Sopenharmony_ci unsigned dst_level, 668bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 669bf215546Sopenharmony_ci struct pipe_resource *src, 670bf215546Sopenharmony_ci unsigned src_level, 671bf215546Sopenharmony_ci const struct pipe_box *src_box) 672bf215546Sopenharmony_ci{ 673bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context *)ctx; 674bf215546Sopenharmony_ci struct pipe_surface *dst_view, dst_templ; 675bf215546Sopenharmony_ci struct pipe_sampler_view src_templ, *src_view; 676bf215546Sopenharmony_ci unsigned dst_width, dst_height, src_width0, src_height0, src_widthFL, src_heightFL; 677bf215546Sopenharmony_ci unsigned src_force_level = 0; 678bf215546Sopenharmony_ci struct pipe_box sbox, dstbox; 679bf215546Sopenharmony_ci 680bf215546Sopenharmony_ci /* Handle buffers first. */ 681bf215546Sopenharmony_ci if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 682bf215546Sopenharmony_ci if ((src->bind & PIPE_BIND_GLOBAL) || 683bf215546Sopenharmony_ci (dst->bind & PIPE_BIND_GLOBAL)) { 684bf215546Sopenharmony_ci r600_copy_global_buffer(ctx, dst, dstx, src, src_box); 685bf215546Sopenharmony_ci } else { 686bf215546Sopenharmony_ci r600_copy_buffer(ctx, dst, dstx, src, src_box); 687bf215546Sopenharmony_ci } 688bf215546Sopenharmony_ci return; 689bf215546Sopenharmony_ci } 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci assert(u_max_sample(dst) == u_max_sample(src)); 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci /* The driver doesn't decompress resources automatically while 694bf215546Sopenharmony_ci * u_blitter is rendering. */ 695bf215546Sopenharmony_ci if (!r600_decompress_subresource(ctx, src, src_level, 696bf215546Sopenharmony_ci src_box->z, src_box->z + src_box->depth - 1)) { 697bf215546Sopenharmony_ci return; /* error */ 698bf215546Sopenharmony_ci } 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci dst_width = u_minify(dst->width0, dst_level); 701bf215546Sopenharmony_ci dst_height = u_minify(dst->height0, dst_level); 702bf215546Sopenharmony_ci src_width0 = src->width0; 703bf215546Sopenharmony_ci src_height0 = src->height0; 704bf215546Sopenharmony_ci src_widthFL = u_minify(src->width0, src_level); 705bf215546Sopenharmony_ci src_heightFL = u_minify(src->height0, src_level); 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz); 708bf215546Sopenharmony_ci util_blitter_default_src_texture(rctx->blitter, &src_templ, src, src_level); 709bf215546Sopenharmony_ci 710bf215546Sopenharmony_ci if (util_format_is_compressed(src->format) || 711bf215546Sopenharmony_ci util_format_is_compressed(dst->format)) { 712bf215546Sopenharmony_ci unsigned blocksize = util_format_get_blocksize(src->format); 713bf215546Sopenharmony_ci 714bf215546Sopenharmony_ci if (blocksize == 8) 715bf215546Sopenharmony_ci src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ 716bf215546Sopenharmony_ci else 717bf215546Sopenharmony_ci src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */ 718bf215546Sopenharmony_ci dst_templ.format = src_templ.format; 719bf215546Sopenharmony_ci 720bf215546Sopenharmony_ci dst_width = util_format_get_nblocksx(dst->format, dst_width); 721bf215546Sopenharmony_ci dst_height = util_format_get_nblocksy(dst->format, dst_height); 722bf215546Sopenharmony_ci src_width0 = util_format_get_nblocksx(src->format, src_width0); 723bf215546Sopenharmony_ci src_height0 = util_format_get_nblocksy(src->format, src_height0); 724bf215546Sopenharmony_ci src_widthFL = util_format_get_nblocksx(src->format, src_widthFL); 725bf215546Sopenharmony_ci src_heightFL = util_format_get_nblocksy(src->format, src_heightFL); 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci dstx = util_format_get_nblocksx(dst->format, dstx); 728bf215546Sopenharmony_ci dsty = util_format_get_nblocksy(dst->format, dsty); 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci sbox.x = util_format_get_nblocksx(src->format, src_box->x); 731bf215546Sopenharmony_ci sbox.y = util_format_get_nblocksy(src->format, src_box->y); 732bf215546Sopenharmony_ci sbox.z = src_box->z; 733bf215546Sopenharmony_ci sbox.width = util_format_get_nblocksx(src->format, src_box->width); 734bf215546Sopenharmony_ci sbox.height = util_format_get_nblocksy(src->format, src_box->height); 735bf215546Sopenharmony_ci sbox.depth = src_box->depth; 736bf215546Sopenharmony_ci src_box = &sbox; 737bf215546Sopenharmony_ci 738bf215546Sopenharmony_ci src_force_level = src_level; 739bf215546Sopenharmony_ci } else if (!util_blitter_is_copy_supported(rctx->blitter, dst, src)) { 740bf215546Sopenharmony_ci if (util_format_is_subsampled_422(src->format)) { 741bf215546Sopenharmony_ci 742bf215546Sopenharmony_ci src_templ.format = PIPE_FORMAT_R8G8B8A8_UINT; 743bf215546Sopenharmony_ci dst_templ.format = PIPE_FORMAT_R8G8B8A8_UINT; 744bf215546Sopenharmony_ci 745bf215546Sopenharmony_ci dst_width = util_format_get_nblocksx(dst->format, dst_width); 746bf215546Sopenharmony_ci src_width0 = util_format_get_nblocksx(src->format, src_width0); 747bf215546Sopenharmony_ci src_widthFL = util_format_get_nblocksx(src->format, src_widthFL); 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_ci dstx = util_format_get_nblocksx(dst->format, dstx); 750bf215546Sopenharmony_ci 751bf215546Sopenharmony_ci sbox = *src_box; 752bf215546Sopenharmony_ci sbox.x = util_format_get_nblocksx(src->format, src_box->x); 753bf215546Sopenharmony_ci sbox.width = util_format_get_nblocksx(src->format, src_box->width); 754bf215546Sopenharmony_ci src_box = &sbox; 755bf215546Sopenharmony_ci } else { 756bf215546Sopenharmony_ci unsigned blocksize = util_format_get_blocksize(src->format); 757bf215546Sopenharmony_ci 758bf215546Sopenharmony_ci switch (blocksize) { 759bf215546Sopenharmony_ci case 1: 760bf215546Sopenharmony_ci dst_templ.format = PIPE_FORMAT_R8_UNORM; 761bf215546Sopenharmony_ci src_templ.format = PIPE_FORMAT_R8_UNORM; 762bf215546Sopenharmony_ci break; 763bf215546Sopenharmony_ci case 2: 764bf215546Sopenharmony_ci dst_templ.format = PIPE_FORMAT_R8G8_UNORM; 765bf215546Sopenharmony_ci src_templ.format = PIPE_FORMAT_R8G8_UNORM; 766bf215546Sopenharmony_ci break; 767bf215546Sopenharmony_ci case 4: 768bf215546Sopenharmony_ci dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; 769bf215546Sopenharmony_ci src_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; 770bf215546Sopenharmony_ci break; 771bf215546Sopenharmony_ci case 8: 772bf215546Sopenharmony_ci dst_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; 773bf215546Sopenharmony_ci src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; 774bf215546Sopenharmony_ci break; 775bf215546Sopenharmony_ci case 16: 776bf215546Sopenharmony_ci dst_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; 777bf215546Sopenharmony_ci src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; 778bf215546Sopenharmony_ci break; 779bf215546Sopenharmony_ci default: 780bf215546Sopenharmony_ci fprintf(stderr, "Unhandled format %s with blocksize %u\n", 781bf215546Sopenharmony_ci util_format_short_name(src->format), blocksize); 782bf215546Sopenharmony_ci assert(0); 783bf215546Sopenharmony_ci } 784bf215546Sopenharmony_ci } 785bf215546Sopenharmony_ci } 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_ci dst_view = r600_create_surface_custom(ctx, dst, &dst_templ, 788bf215546Sopenharmony_ci /* we don't care about these two for r600g */ 789bf215546Sopenharmony_ci dst->width0, dst->height0, 790bf215546Sopenharmony_ci dst_width, dst_height); 791bf215546Sopenharmony_ci 792bf215546Sopenharmony_ci if (rctx->b.gfx_level >= EVERGREEN) { 793bf215546Sopenharmony_ci src_view = evergreen_create_sampler_view_custom(ctx, src, &src_templ, 794bf215546Sopenharmony_ci src_width0, src_height0, 795bf215546Sopenharmony_ci src_force_level); 796bf215546Sopenharmony_ci } else { 797bf215546Sopenharmony_ci src_view = r600_create_sampler_view_custom(ctx, src, &src_templ, 798bf215546Sopenharmony_ci src_widthFL, src_heightFL); 799bf215546Sopenharmony_ci } 800bf215546Sopenharmony_ci 801bf215546Sopenharmony_ci u_box_3d(dstx, dsty, dstz, abs(src_box->width), abs(src_box->height), 802bf215546Sopenharmony_ci abs(src_box->depth), &dstbox); 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_ci /* Copy. */ 805bf215546Sopenharmony_ci r600_blitter_begin(ctx, R600_COPY_TEXTURE); 806bf215546Sopenharmony_ci util_blitter_blit_generic(rctx->blitter, dst_view, &dstbox, 807bf215546Sopenharmony_ci src_view, src_box, src_width0, src_height0, 808bf215546Sopenharmony_ci PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL, 809bf215546Sopenharmony_ci FALSE, FALSE, 0); 810bf215546Sopenharmony_ci r600_blitter_end(ctx); 811bf215546Sopenharmony_ci 812bf215546Sopenharmony_ci pipe_surface_reference(&dst_view, NULL); 813bf215546Sopenharmony_ci pipe_sampler_view_reference(&src_view, NULL); 814bf215546Sopenharmony_ci} 815bf215546Sopenharmony_ci 816bf215546Sopenharmony_cistatic bool do_hardware_msaa_resolve(struct pipe_context *ctx, 817bf215546Sopenharmony_ci const struct pipe_blit_info *info) 818bf215546Sopenharmony_ci{ 819bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context*)ctx; 820bf215546Sopenharmony_ci struct r600_texture *dst = (struct r600_texture*)info->dst.resource; 821bf215546Sopenharmony_ci unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level); 822bf215546Sopenharmony_ci unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level); 823bf215546Sopenharmony_ci enum pipe_format format = info->src.format; 824bf215546Sopenharmony_ci unsigned sample_mask = 825bf215546Sopenharmony_ci rctx->b.gfx_level == CAYMAN ? ~0 : 826bf215546Sopenharmony_ci ((1ull << MAX2(1, info->src.resource->nr_samples)) - 1); 827bf215546Sopenharmony_ci struct pipe_resource *tmp, templ; 828bf215546Sopenharmony_ci struct pipe_blit_info blit; 829bf215546Sopenharmony_ci 830bf215546Sopenharmony_ci /* Check basic requirements for hw resolve. */ 831bf215546Sopenharmony_ci if (!(info->src.resource->nr_samples > 1 && 832bf215546Sopenharmony_ci info->dst.resource->nr_samples <= 1 && 833bf215546Sopenharmony_ci !util_format_is_pure_integer(format) && 834bf215546Sopenharmony_ci !util_format_is_depth_or_stencil(format) && 835bf215546Sopenharmony_ci util_max_layer(info->src.resource, 0) == 0)) 836bf215546Sopenharmony_ci return false; 837bf215546Sopenharmony_ci 838bf215546Sopenharmony_ci /* Check the remaining requirements for hw resolve. */ 839bf215546Sopenharmony_ci if (util_max_layer(info->dst.resource, info->dst.level) == 0 && 840bf215546Sopenharmony_ci util_is_format_compatible(util_format_description(info->src.format), 841bf215546Sopenharmony_ci util_format_description(info->dst.format)) && 842bf215546Sopenharmony_ci !info->scissor_enable && 843bf215546Sopenharmony_ci (info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA && 844bf215546Sopenharmony_ci dst_width == info->src.resource->width0 && 845bf215546Sopenharmony_ci dst_height == info->src.resource->height0 && 846bf215546Sopenharmony_ci info->dst.box.x == 0 && 847bf215546Sopenharmony_ci info->dst.box.y == 0 && 848bf215546Sopenharmony_ci info->dst.box.width == dst_width && 849bf215546Sopenharmony_ci info->dst.box.height == dst_height && 850bf215546Sopenharmony_ci info->dst.box.depth == 1 && 851bf215546Sopenharmony_ci info->src.box.x == 0 && 852bf215546Sopenharmony_ci info->src.box.y == 0 && 853bf215546Sopenharmony_ci info->src.box.width == dst_width && 854bf215546Sopenharmony_ci info->src.box.height == dst_height && 855bf215546Sopenharmony_ci info->src.box.depth == 1 && 856bf215546Sopenharmony_ci dst->surface.u.legacy.level[info->dst.level].mode >= RADEON_SURF_MODE_1D && 857bf215546Sopenharmony_ci (!dst->cmask.size || !dst->dirty_level_mask) /* dst cannot be fast-cleared */) { 858bf215546Sopenharmony_ci r600_blitter_begin(ctx, R600_COLOR_RESOLVE | 859bf215546Sopenharmony_ci (info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND)); 860bf215546Sopenharmony_ci util_blitter_custom_resolve_color(rctx->blitter, 861bf215546Sopenharmony_ci info->dst.resource, info->dst.level, 862bf215546Sopenharmony_ci info->dst.box.z, 863bf215546Sopenharmony_ci info->src.resource, info->src.box.z, 864bf215546Sopenharmony_ci sample_mask, rctx->custom_blend_resolve, 865bf215546Sopenharmony_ci format); 866bf215546Sopenharmony_ci r600_blitter_end(ctx); 867bf215546Sopenharmony_ci return true; 868bf215546Sopenharmony_ci } 869bf215546Sopenharmony_ci 870bf215546Sopenharmony_ci /* Shader-based resolve is VERY SLOW. Instead, resolve into 871bf215546Sopenharmony_ci * a temporary texture and blit. 872bf215546Sopenharmony_ci */ 873bf215546Sopenharmony_ci memset(&templ, 0, sizeof(templ)); 874bf215546Sopenharmony_ci templ.target = PIPE_TEXTURE_2D; 875bf215546Sopenharmony_ci templ.format = info->src.resource->format; 876bf215546Sopenharmony_ci templ.width0 = info->src.resource->width0; 877bf215546Sopenharmony_ci templ.height0 = info->src.resource->height0; 878bf215546Sopenharmony_ci templ.depth0 = 1; 879bf215546Sopenharmony_ci templ.array_size = 1; 880bf215546Sopenharmony_ci templ.usage = PIPE_USAGE_DEFAULT; 881bf215546Sopenharmony_ci templ.flags = R600_RESOURCE_FLAG_FORCE_TILING; 882bf215546Sopenharmony_ci 883bf215546Sopenharmony_ci tmp = ctx->screen->resource_create(ctx->screen, &templ); 884bf215546Sopenharmony_ci if (!tmp) 885bf215546Sopenharmony_ci return false; 886bf215546Sopenharmony_ci 887bf215546Sopenharmony_ci /* resolve */ 888bf215546Sopenharmony_ci r600_blitter_begin(ctx, R600_COLOR_RESOLVE | 889bf215546Sopenharmony_ci (info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND)); 890bf215546Sopenharmony_ci util_blitter_custom_resolve_color(rctx->blitter, tmp, 0, 0, 891bf215546Sopenharmony_ci info->src.resource, info->src.box.z, 892bf215546Sopenharmony_ci sample_mask, rctx->custom_blend_resolve, 893bf215546Sopenharmony_ci format); 894bf215546Sopenharmony_ci r600_blitter_end(ctx); 895bf215546Sopenharmony_ci 896bf215546Sopenharmony_ci /* blit */ 897bf215546Sopenharmony_ci blit = *info; 898bf215546Sopenharmony_ci blit.src.resource = tmp; 899bf215546Sopenharmony_ci blit.src.box.z = 0; 900bf215546Sopenharmony_ci 901bf215546Sopenharmony_ci r600_blitter_begin(ctx, R600_BLIT | 902bf215546Sopenharmony_ci (info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND)); 903bf215546Sopenharmony_ci util_blitter_blit(rctx->blitter, &blit); 904bf215546Sopenharmony_ci r600_blitter_end(ctx); 905bf215546Sopenharmony_ci 906bf215546Sopenharmony_ci pipe_resource_reference(&tmp, NULL); 907bf215546Sopenharmony_ci return true; 908bf215546Sopenharmony_ci} 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_cistatic void r600_blit(struct pipe_context *ctx, 911bf215546Sopenharmony_ci const struct pipe_blit_info *info) 912bf215546Sopenharmony_ci{ 913bf215546Sopenharmony_ci struct r600_context *rctx = (struct r600_context*)ctx; 914bf215546Sopenharmony_ci struct r600_texture *rdst = (struct r600_texture *)info->dst.resource; 915bf215546Sopenharmony_ci 916bf215546Sopenharmony_ci if (do_hardware_msaa_resolve(ctx, info)) { 917bf215546Sopenharmony_ci return; 918bf215546Sopenharmony_ci } 919bf215546Sopenharmony_ci 920bf215546Sopenharmony_ci /* Using SDMA for copying to a linear texture in GTT is much faster. 921bf215546Sopenharmony_ci * This improves DRI PRIME performance. 922bf215546Sopenharmony_ci * 923bf215546Sopenharmony_ci * resource_copy_region can't do this yet, because dma_copy calls it 924bf215546Sopenharmony_ci * on failure (recursion). 925bf215546Sopenharmony_ci */ 926bf215546Sopenharmony_ci if (rdst->surface.u.legacy.level[info->dst.level].mode == 927bf215546Sopenharmony_ci RADEON_SURF_MODE_LINEAR_ALIGNED && 928bf215546Sopenharmony_ci rctx->b.dma_copy && 929bf215546Sopenharmony_ci util_can_blit_via_copy_region(info, false, rctx->b.render_cond != NULL)) { 930bf215546Sopenharmony_ci rctx->b.dma_copy(ctx, info->dst.resource, info->dst.level, 931bf215546Sopenharmony_ci info->dst.box.x, info->dst.box.y, 932bf215546Sopenharmony_ci info->dst.box.z, 933bf215546Sopenharmony_ci info->src.resource, info->src.level, 934bf215546Sopenharmony_ci &info->src.box); 935bf215546Sopenharmony_ci return; 936bf215546Sopenharmony_ci } 937bf215546Sopenharmony_ci 938bf215546Sopenharmony_ci assert(util_blitter_is_blit_supported(rctx->blitter, info)); 939bf215546Sopenharmony_ci 940bf215546Sopenharmony_ci /* The driver doesn't decompress resources automatically while 941bf215546Sopenharmony_ci * u_blitter is rendering. */ 942bf215546Sopenharmony_ci if (!r600_decompress_subresource(ctx, info->src.resource, info->src.level, 943bf215546Sopenharmony_ci info->src.box.z, 944bf215546Sopenharmony_ci info->src.box.z + info->src.box.depth - 1)) { 945bf215546Sopenharmony_ci return; /* error */ 946bf215546Sopenharmony_ci } 947bf215546Sopenharmony_ci 948bf215546Sopenharmony_ci if (rctx->screen->b.debug_flags & DBG_FORCE_DMA && 949bf215546Sopenharmony_ci util_try_blit_via_copy_region(ctx, info, rctx->b.render_cond != NULL)) 950bf215546Sopenharmony_ci return; 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_ci r600_blitter_begin(ctx, R600_BLIT | 953bf215546Sopenharmony_ci (info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND)); 954bf215546Sopenharmony_ci util_blitter_blit(rctx->blitter, info); 955bf215546Sopenharmony_ci r600_blitter_end(ctx); 956bf215546Sopenharmony_ci} 957bf215546Sopenharmony_ci 958bf215546Sopenharmony_cistatic void r600_flush_resource(struct pipe_context *ctx, 959bf215546Sopenharmony_ci struct pipe_resource *res) 960bf215546Sopenharmony_ci{ 961bf215546Sopenharmony_ci struct r600_texture *rtex = (struct r600_texture*)res; 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_ci assert(res->target != PIPE_BUFFER); 964bf215546Sopenharmony_ci 965bf215546Sopenharmony_ci if (!rtex->is_depth && rtex->cmask.size) { 966bf215546Sopenharmony_ci r600_blit_decompress_color(ctx, rtex, 0, res->last_level, 967bf215546Sopenharmony_ci 0, util_max_layer(res, 0)); 968bf215546Sopenharmony_ci } 969bf215546Sopenharmony_ci} 970bf215546Sopenharmony_ci 971bf215546Sopenharmony_civoid r600_init_blit_functions(struct r600_context *rctx) 972bf215546Sopenharmony_ci{ 973bf215546Sopenharmony_ci rctx->b.b.clear = r600_clear; 974bf215546Sopenharmony_ci rctx->b.b.clear_render_target = r600_clear_render_target; 975bf215546Sopenharmony_ci rctx->b.b.clear_depth_stencil = r600_clear_depth_stencil; 976bf215546Sopenharmony_ci rctx->b.b.resource_copy_region = r600_resource_copy_region; 977bf215546Sopenharmony_ci rctx->b.b.blit = r600_blit; 978bf215546Sopenharmony_ci rctx->b.b.flush_resource = r600_flush_resource; 979bf215546Sopenharmony_ci rctx->b.clear_buffer = r600_clear_buffer; 980bf215546Sopenharmony_ci rctx->b.blit_decompress_depth = r600_blit_decompress_depth; 981bf215546Sopenharmony_ci} 982