diff options
Diffstat (limited to 'src/gallium/drivers/vc5/vc5_rcl.c')
-rw-r--r-- | src/gallium/drivers/vc5/vc5_rcl.c | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/gallium/drivers/vc5/vc5_rcl.c b/src/gallium/drivers/vc5/vc5_rcl.c new file mode 100644 index 00000000000..287a35aa33e --- /dev/null +++ b/src/gallium/drivers/vc5/vc5_rcl.c @@ -0,0 +1,218 @@ +/* + * Copyright © 2017 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "util/u_format.h" +#include "vc5_context.h" +#include "vc5_tiling.h" +#include "broadcom/cle/v3d_packet_v33_pack.h" + +void +vc5_emit_rcl(struct vc5_job *job) +{ + uint32_t min_x_tile = job->draw_min_x / job->tile_width; + uint32_t min_y_tile = job->draw_min_y / job->tile_height; + uint32_t max_x_tile = (job->draw_max_x - 1) / job->tile_width; + uint32_t max_y_tile = (job->draw_max_y - 1) / job->tile_height; + + /* The RCL list should be empty. */ + assert(!job->rcl.bo); + + vc5_cl_ensure_space(&job->rcl, + 256 + + (64 * + (max_x_tile - min_x_tile + 1) * + (max_y_tile - min_y_tile + 1)), 1); + + job->submit.rcl_start = job->rcl.bo->offset; + vc5_job_add_bo(job, job->rcl.bo); + + int nr_cbufs = 0; + for (int i = 0; i < VC5_MAX_DRAW_BUFFERS; i++) { + if (job->cbufs[i]) + nr_cbufs = i + 1; + } + + /* Comon config must be the first TILE_RENDERING_MODE_CONFIGURATION + * and Z_STENCIL_CLEAR_VALUES must be last. The ones in between are + * optional updates to the previous HW state. + */ + cl_emit(&job->rcl, TILE_RENDERING_MODE_CONFIGURATION_COMMON_CONFIGURATION, + config) { + config.enable_z_store = job->resolve & PIPE_CLEAR_DEPTH; + config.enable_stencil_store = job->resolve & PIPE_CLEAR_STENCIL; + + config.early_z_disable = !job->uses_early_z; + + config.image_width_pixels = job->draw_width; + config.image_height_pixels = job->draw_height; + + config.number_of_render_targets_minus_1 = + MAX2(nr_cbufs, 1) - 1; + + config.maximum_bpp_of_all_render_targets = job->internal_bpp; + } + + for (int i = 0; i < nr_cbufs; i++) { + cl_emit(&job->rcl, TILE_RENDERING_MODE_CONFIGURATION_RENDER_TARGET_CONFIG, rt) { + struct pipe_surface *psurf = job->cbufs[i]; + if (!psurf) + continue; + + struct vc5_surface *surf = vc5_surface(psurf); + struct vc5_resource *rsc = vc5_resource(psurf->texture); + rt.address = cl_address(rsc->bo, surf->offset); + rt.internal_type = surf->internal_type; + rt.output_image_format = surf->format; + rt.memory_format = surf->tiling; + rt.internal_bpp = surf->internal_bpp; + rt.render_target_number = i; + + if (job->resolve & PIPE_CLEAR_COLOR0 << i) + rsc->writes++; + } + } + + /* TODO: Don't bother emitting if we don't load/clear Z/S. */ + if (job->zsbuf) { + struct pipe_surface *psurf = job->zsbuf; + struct vc5_surface *surf = vc5_surface(psurf); + struct vc5_resource *rsc = vc5_resource(psurf->texture); + + cl_emit(&job->rcl, TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CONFIG, zs) { + zs.address = cl_address(rsc->bo, surf->offset); + + zs.internal_type = surf->internal_type; + zs.output_image_format = surf->format; + + struct vc5_resource_slice *slice = &rsc->slices[psurf->u.tex.level]; + /* XXX */ + zs.padded_height_of_output_image_in_uif_blocks = + (slice->size / slice->stride) / (2 * vc5_utile_height(rsc->cpp)); + + assert(surf->tiling != VC5_TILING_RASTER); + zs.memory_format = surf->tiling; + } + + if (job->resolve & PIPE_CLEAR_DEPTHSTENCIL) + rsc->writes++; + } + + cl_emit(&job->rcl, TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART1, + clear) { + clear.clear_color_low_32_bits = job->clear_color[0]; + }; + + /* Ends rendering mode config. */ + cl_emit(&job->rcl, TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CLEAR_VALUES, + clear) { + clear.z_s_clear_value = job->clear_zs; + }; + + /* Always set initial block size before the first branch, which needs + * to match the value from binning mode config. + */ + cl_emit(&job->rcl, TILE_LIST_INITIAL_BLOCK_SIZE, init) { + init.use_auto_chained_tile_lists = true; + init.size_of_first_block_in_chained_tile_lists = + TILE_ALLOCATION_BLOCK_SIZE_64B; + } + + cl_emit(&job->rcl, WAIT_ON_SEMAPHORE, sem); + + /* Start by clearing the tile buffer. */ + cl_emit(&job->rcl, TILE_COORDINATES, coords) { + coords.tile_column_number = 0; + coords.tile_row_number = 0; + } + + cl_emit(&job->rcl, STORE_TILE_BUFFER_GENERAL, store) { + store.buffer_to_store = NONE; + } + + cl_emit(&job->rcl, FLUSH_VCD_CACHE, flush); + + const uint32_t pipe_clear_color_buffers = (PIPE_CLEAR_COLOR0 | + PIPE_CLEAR_COLOR1 | + PIPE_CLEAR_COLOR2 | + PIPE_CLEAR_COLOR3); + const uint32_t first_color_buffer_bit = (ffs(PIPE_CLEAR_COLOR0) - 1); + + for (int y = min_y_tile; y <= max_y_tile; y++) { + for (int x = min_x_tile; x <= max_x_tile; x++) { + uint32_t read_but_not_cleared = job->resolve & ~job->cleared; + + /* The initial reload will be queued until we get the + * tile coordinates. + */ + if (read_but_not_cleared) { + cl_emit(&job->rcl, RELOAD_TILE_COLOUR_BUFFER, load) { + load.disable_colour_buffer_load = + (~read_but_not_cleared & pipe_clear_color_buffers) >> + first_color_buffer_bit; + load.enable_z_load = + read_but_not_cleared & PIPE_CLEAR_DEPTH; + load.enable_stencil_load = + read_but_not_cleared & PIPE_CLEAR_STENCIL; + } + } + + /* Tile Coordinates triggers the reload and sets where + * the stores go. There must be one per store packet. + */ + cl_emit(&job->rcl, TILE_COORDINATES, coords) { + coords.tile_column_number = x; + coords.tile_row_number = y; + } + + cl_emit(&job->rcl, BRANCH_TO_AUTO_CHAINED_SUB_LIST, branch) { + uint32_t bin_tile_stride = + (align(job->draw_width, + job->tile_width) / + job->tile_width); + uint32_t bin_index = + (y * bin_tile_stride + x); + branch.address = cl_address(job->tile_alloc, + 64 * bin_index); + } + + cl_emit(&job->rcl, STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED, store) { + uint32_t color_write_enables = + job->resolve >> first_color_buffer_bit; + + store.disable_color_buffer_write = (~color_write_enables) & 0xf; + store.enable_z_write = job->resolve & PIPE_CLEAR_DEPTH; + store.enable_stencil_write = job->resolve & PIPE_CLEAR_STENCIL; + + store.disable_colour_buffers_clear_on_write = + (job->cleared & pipe_clear_color_buffers) == 0; + store.disable_z_buffer_clear_on_write = + !(job->cleared & PIPE_CLEAR_DEPTH); + store.disable_stencil_buffer_clear_on_write = + !(job->cleared & PIPE_CLEAR_STENCIL); + + store.last_tile_of_frame = (x == max_x_tile && + y == max_y_tile); + }; + } + } +} |