Path: blob/21.2-virgl/src/broadcom/vulkan/v3dvx_cmd_buffer.c
4560 views
/*1* Copyright © 2021 Raspberry Pi2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "v3dv_private.h"24#include "broadcom/common/v3d_macros.h"25#include "broadcom/cle/v3dx_pack.h"26#include "broadcom/compiler/v3d_compiler.h"2728#include "util/half_float.h"29#include "vulkan/util/vk_format.h"30#include "util/u_pack_color.h"3132#include "vk_format_info.h"3334void35v3dX(job_emit_binning_flush)(struct v3dv_job *job)36{37assert(job);3839v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(FLUSH));40v3dv_return_if_oom(NULL, job);4142cl_emit(&job->bcl, FLUSH, flush);43}4445void46v3dX(job_emit_binning_prolog)(struct v3dv_job *job,47const struct v3dv_frame_tiling *tiling,48uint32_t layers)49{50/* This must go before the binning mode configuration. It is51* required for layered framebuffers to work.52*/53cl_emit(&job->bcl, NUMBER_OF_LAYERS, config) {54config.number_of_layers = layers;55}5657cl_emit(&job->bcl, TILE_BINNING_MODE_CFG, config) {58config.width_in_pixels = tiling->width;59config.height_in_pixels = tiling->height;60config.number_of_render_targets = MAX2(tiling->render_target_count, 1);61config.multisample_mode_4x = tiling->msaa;62config.maximum_bpp_of_all_render_targets = tiling->internal_bpp;63}6465/* There's definitely nothing in the VCD cache we want. */66cl_emit(&job->bcl, FLUSH_VCD_CACHE, bin);6768/* "Binning mode lists must have a Start Tile Binning item (6) after69* any prefix state data before the binning list proper starts."70*/71cl_emit(&job->bcl, START_TILE_BINNING, bin);72}7374void75v3dX(cmd_buffer_end_render_pass_secondary)(struct v3dv_cmd_buffer *cmd_buffer)76{77assert(cmd_buffer->state.job);78v3dv_cl_ensure_space_with_branch(&cmd_buffer->state.job->bcl,79cl_packet_length(RETURN_FROM_SUB_LIST));80v3dv_return_if_oom(cmd_buffer, NULL);81cl_emit(&cmd_buffer->state.job->bcl, RETURN_FROM_SUB_LIST, ret);82}8384void85v3dX(job_emit_clip_window)(struct v3dv_job *job, const VkRect2D *rect)86{87assert(job);8889v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(CLIP_WINDOW));90v3dv_return_if_oom(NULL, job);9192cl_emit(&job->bcl, CLIP_WINDOW, clip) {93clip.clip_window_left_pixel_coordinate = rect->offset.x;94clip.clip_window_bottom_pixel_coordinate = rect->offset.y;95clip.clip_window_width_in_pixels = rect->extent.width;96clip.clip_window_height_in_pixels = rect->extent.height;97}98}99100static void101cmd_buffer_render_pass_emit_load(struct v3dv_cmd_buffer *cmd_buffer,102struct v3dv_cl *cl,103struct v3dv_image_view *iview,104uint32_t layer,105uint32_t buffer)106{107const struct v3dv_image *image = iview->image;108const struct v3d_resource_slice *slice = &image->slices[iview->base_level];109uint32_t layer_offset = v3dv_layer_offset(image,110iview->base_level,111iview->first_layer + layer);112113cl_emit(cl, LOAD_TILE_BUFFER_GENERAL, load) {114load.buffer_to_load = buffer;115load.address = v3dv_cl_address(image->mem->bo, layer_offset);116117load.input_image_format = iview->format->rt_type;118load.r_b_swap = iview->swap_rb;119load.memory_format = slice->tiling;120121if (slice->tiling == V3D_TILING_UIF_NO_XOR ||122slice->tiling == V3D_TILING_UIF_XOR) {123load.height_in_ub_or_stride =124slice->padded_height_of_output_image_in_uif_blocks;125} else if (slice->tiling == V3D_TILING_RASTER) {126load.height_in_ub_or_stride = slice->stride;127}128129if (image->samples > VK_SAMPLE_COUNT_1_BIT)130load.decimate_mode = V3D_DECIMATE_MODE_ALL_SAMPLES;131else132load.decimate_mode = V3D_DECIMATE_MODE_SAMPLE_0;133}134}135136static bool137check_needs_load(const struct v3dv_cmd_buffer_state *state,138VkImageAspectFlags aspect,139uint32_t att_first_subpass_idx,140VkAttachmentLoadOp load_op)141{142/* We call this with image->aspects & aspect, so 0 means the aspect we are143* testing does not exist in the image.144*/145if (!aspect)146return false;147148/* Attachment load operations apply on the first subpass that uses the149* attachment, otherwise we always need to load.150*/151if (state->job->first_subpass > att_first_subpass_idx)152return true;153154/* If the job is continuing a subpass started in another job, we always155* need to load.156*/157if (state->job->is_subpass_continue)158return true;159160/* If the area is not aligned to tile boundaries, we always need to load */161if (!state->tile_aligned_render_area)162return true;163164/* The attachment load operations must be LOAD */165return load_op == VK_ATTACHMENT_LOAD_OP_LOAD;166}167168static inline uint32_t169v3dv_zs_buffer(bool depth, bool stencil)170{171if (depth && stencil)172return ZSTENCIL;173else if (depth)174return Z;175else if (stencil)176return STENCIL;177return NONE;178}179180static void181cmd_buffer_render_pass_emit_loads(struct v3dv_cmd_buffer *cmd_buffer,182struct v3dv_cl *cl,183uint32_t layer)184{185const struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;186const struct v3dv_framebuffer *framebuffer = state->framebuffer;187const struct v3dv_render_pass *pass = state->pass;188const struct v3dv_subpass *subpass = &pass->subpasses[state->subpass_idx];189190for (uint32_t i = 0; i < subpass->color_count; i++) {191uint32_t attachment_idx = subpass->color_attachments[i].attachment;192193if (attachment_idx == VK_ATTACHMENT_UNUSED)194continue;195196const struct v3dv_render_pass_attachment *attachment =197&state->pass->attachments[attachment_idx];198199/* According to the Vulkan spec:200*201* "The load operation for each sample in an attachment happens before202* any recorded command which accesses the sample in the first subpass203* where the attachment is used."204*205* If the load operation is CLEAR, we must only clear once on the first206* subpass that uses the attachment (and in that case we don't LOAD).207* After that, we always want to load so we don't lose any rendering done208* by a previous subpass to the same attachment. We also want to load209* if the current job is continuing subpass work started by a previous210* job, for the same reason.211*212* If the render area is not aligned to tile boundaries then we have213* tiles which are partially covered by it. In this case, we need to214* load the tiles so we can preserve the pixels that are outside the215* render area for any such tiles.216*/217bool needs_load = check_needs_load(state,218VK_IMAGE_ASPECT_COLOR_BIT,219attachment->first_subpass,220attachment->desc.loadOp);221if (needs_load) {222struct v3dv_image_view *iview = framebuffer->attachments[attachment_idx];223cmd_buffer_render_pass_emit_load(cmd_buffer, cl, iview,224layer, RENDER_TARGET_0 + i);225}226}227228uint32_t ds_attachment_idx = subpass->ds_attachment.attachment;229if (ds_attachment_idx != VK_ATTACHMENT_UNUSED) {230const struct v3dv_render_pass_attachment *ds_attachment =231&state->pass->attachments[ds_attachment_idx];232233const VkImageAspectFlags ds_aspects =234vk_format_aspects(ds_attachment->desc.format);235236const bool needs_depth_load =237check_needs_load(state,238ds_aspects & VK_IMAGE_ASPECT_DEPTH_BIT,239ds_attachment->first_subpass,240ds_attachment->desc.loadOp);241242const bool needs_stencil_load =243check_needs_load(state,244ds_aspects & VK_IMAGE_ASPECT_STENCIL_BIT,245ds_attachment->first_subpass,246ds_attachment->desc.stencilLoadOp);247248if (needs_depth_load || needs_stencil_load) {249struct v3dv_image_view *iview =250framebuffer->attachments[ds_attachment_idx];251/* From the Vulkan spec:252*253* "When an image view of a depth/stencil image is used as a254* depth/stencil framebuffer attachment, the aspectMask is ignored255* and both depth and stencil image subresources are used."256*257* So we ignore the aspects from the subresource range of the image258* view for the depth/stencil attachment, but we still need to restrict259* the to aspects compatible with the render pass and the image.260*/261const uint32_t zs_buffer =262v3dv_zs_buffer(needs_depth_load, needs_stencil_load);263cmd_buffer_render_pass_emit_load(cmd_buffer, cl,264iview, layer, zs_buffer);265}266}267268cl_emit(cl, END_OF_LOADS, end);269}270271static void272cmd_buffer_render_pass_emit_store(struct v3dv_cmd_buffer *cmd_buffer,273struct v3dv_cl *cl,274uint32_t attachment_idx,275uint32_t layer,276uint32_t buffer,277bool clear,278bool is_multisample_resolve)279{280const struct v3dv_image_view *iview =281cmd_buffer->state.framebuffer->attachments[attachment_idx];282const struct v3dv_image *image = iview->image;283const struct v3d_resource_slice *slice = &image->slices[iview->base_level];284uint32_t layer_offset = v3dv_layer_offset(image,285iview->base_level,286iview->first_layer + layer);287288cl_emit(cl, STORE_TILE_BUFFER_GENERAL, store) {289store.buffer_to_store = buffer;290store.address = v3dv_cl_address(image->mem->bo, layer_offset);291store.clear_buffer_being_stored = clear;292293store.output_image_format = iview->format->rt_type;294store.r_b_swap = iview->swap_rb;295store.memory_format = slice->tiling;296297if (slice->tiling == V3D_TILING_UIF_NO_XOR ||298slice->tiling == V3D_TILING_UIF_XOR) {299store.height_in_ub_or_stride =300slice->padded_height_of_output_image_in_uif_blocks;301} else if (slice->tiling == V3D_TILING_RASTER) {302store.height_in_ub_or_stride = slice->stride;303}304305if (image->samples > VK_SAMPLE_COUNT_1_BIT)306store.decimate_mode = V3D_DECIMATE_MODE_ALL_SAMPLES;307else if (is_multisample_resolve)308store.decimate_mode = V3D_DECIMATE_MODE_4X;309else310store.decimate_mode = V3D_DECIMATE_MODE_SAMPLE_0;311}312}313314static bool315check_needs_clear(const struct v3dv_cmd_buffer_state *state,316VkImageAspectFlags aspect,317uint32_t att_first_subpass_idx,318VkAttachmentLoadOp load_op,319bool do_clear_with_draw)320{321/* We call this with image->aspects & aspect, so 0 means the aspect we are322* testing does not exist in the image.323*/324if (!aspect)325return false;326327/* If the aspect needs to be cleared with a draw call then we won't emit328* the clear here.329*/330if (do_clear_with_draw)331return false;332333/* If this is resuming a subpass started with another job, then attachment334* load operations don't apply.335*/336if (state->job->is_subpass_continue)337return false;338339/* If the render area is not aligned to tile boudaries we can't use the340* TLB for a clear.341*/342if (!state->tile_aligned_render_area)343return false;344345/* If this job is running in a subpass other than the first subpass in346* which this attachment is used then attachment load operations don't apply.347*/348if (state->job->first_subpass != att_first_subpass_idx)349return false;350351/* The attachment load operation must be CLEAR */352return load_op == VK_ATTACHMENT_LOAD_OP_CLEAR;353}354355static bool356check_needs_store(const struct v3dv_cmd_buffer_state *state,357VkImageAspectFlags aspect,358uint32_t att_last_subpass_idx,359VkAttachmentStoreOp store_op)360{361/* We call this with image->aspects & aspect, so 0 means the aspect we are362* testing does not exist in the image.363*/364if (!aspect)365return false;366367/* Attachment store operations only apply on the last subpass where the368* attachment is used, in other subpasses we always need to store.369*/370if (state->subpass_idx < att_last_subpass_idx)371return true;372373/* Attachment store operations only apply on the last job we emit on the the374* last subpass where the attachment is used, otherwise we always need to375* store.376*/377if (!state->job->is_subpass_finish)378return true;379380/* The attachment store operation must be STORE */381return store_op == VK_ATTACHMENT_STORE_OP_STORE;382}383384static void385cmd_buffer_render_pass_emit_stores(struct v3dv_cmd_buffer *cmd_buffer,386struct v3dv_cl *cl,387uint32_t layer)388{389struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;390const struct v3dv_subpass *subpass =391&state->pass->subpasses[state->subpass_idx];392393bool has_stores = false;394bool use_global_zs_clear = false;395bool use_global_rt_clear = false;396397/* FIXME: separate stencil */398uint32_t ds_attachment_idx = subpass->ds_attachment.attachment;399if (ds_attachment_idx != VK_ATTACHMENT_UNUSED) {400const struct v3dv_render_pass_attachment *ds_attachment =401&state->pass->attachments[ds_attachment_idx];402403assert(state->job->first_subpass >= ds_attachment->first_subpass);404assert(state->subpass_idx >= ds_attachment->first_subpass);405assert(state->subpass_idx <= ds_attachment->last_subpass);406407/* From the Vulkan spec, VkImageSubresourceRange:408*409* "When an image view of a depth/stencil image is used as a410* depth/stencil framebuffer attachment, the aspectMask is ignored411* and both depth and stencil image subresources are used."412*413* So we ignore the aspects from the subresource range of the image414* view for the depth/stencil attachment, but we still need to restrict415* the to aspects compatible with the render pass and the image.416*/417const VkImageAspectFlags aspects =418vk_format_aspects(ds_attachment->desc.format);419420/* Only clear once on the first subpass that uses the attachment */421bool needs_depth_clear =422check_needs_clear(state,423aspects & VK_IMAGE_ASPECT_DEPTH_BIT,424ds_attachment->first_subpass,425ds_attachment->desc.loadOp,426subpass->do_depth_clear_with_draw);427428bool needs_stencil_clear =429check_needs_clear(state,430aspects & VK_IMAGE_ASPECT_STENCIL_BIT,431ds_attachment->first_subpass,432ds_attachment->desc.stencilLoadOp,433subpass->do_stencil_clear_with_draw);434435/* Skip the last store if it is not required */436bool needs_depth_store =437check_needs_store(state,438aspects & VK_IMAGE_ASPECT_DEPTH_BIT,439ds_attachment->last_subpass,440ds_attachment->desc.storeOp);441442bool needs_stencil_store =443check_needs_store(state,444aspects & VK_IMAGE_ASPECT_STENCIL_BIT,445ds_attachment->last_subpass,446ds_attachment->desc.stencilStoreOp);447448/* GFXH-1689: The per-buffer store command's clear buffer bit is broken449* for depth/stencil.450*451* There used to be some confusion regarding the Clear Tile Buffers452* Z/S bit also being broken, but we confirmed with Broadcom that this453* is not the case, it was just that some other hardware bugs (that we454* need to work around, such as GFXH-1461) could cause this bit to behave455* incorrectly.456*457* There used to be another issue where the RTs bit in the Clear Tile458* Buffers packet also cleared Z/S, but Broadcom confirmed this is459* fixed since V3D 4.1.460*461* So if we have to emit a clear of depth or stencil we don't use462* the per-buffer store clear bit, even if we need to store the buffers,463* instead we always have to use the Clear Tile Buffers Z/S bit.464* If we have configured the job to do early Z/S clearing, then we465* don't want to emit any Clear Tile Buffers command at all here.466*467* Note that GFXH-1689 is not reproduced in the simulator, where468* using the clear buffer bit in depth/stencil stores works fine.469*/470use_global_zs_clear = !state->job->early_zs_clear &&471(needs_depth_clear || needs_stencil_clear);472if (needs_depth_store || needs_stencil_store) {473const uint32_t zs_buffer =474v3dv_zs_buffer(needs_depth_store, needs_stencil_store);475cmd_buffer_render_pass_emit_store(cmd_buffer, cl,476ds_attachment_idx, layer,477zs_buffer, false, false);478has_stores = true;479}480}481482for (uint32_t i = 0; i < subpass->color_count; i++) {483uint32_t attachment_idx = subpass->color_attachments[i].attachment;484485if (attachment_idx == VK_ATTACHMENT_UNUSED)486continue;487488const struct v3dv_render_pass_attachment *attachment =489&state->pass->attachments[attachment_idx];490491assert(state->job->first_subpass >= attachment->first_subpass);492assert(state->subpass_idx >= attachment->first_subpass);493assert(state->subpass_idx <= attachment->last_subpass);494495/* Only clear once on the first subpass that uses the attachment */496bool needs_clear =497check_needs_clear(state,498VK_IMAGE_ASPECT_COLOR_BIT,499attachment->first_subpass,500attachment->desc.loadOp,501false);502503/* Skip the last store if it is not required */504bool needs_store =505check_needs_store(state,506VK_IMAGE_ASPECT_COLOR_BIT,507attachment->last_subpass,508attachment->desc.storeOp);509510/* If we need to resolve this attachment emit that store first. Notice511* that we must not request a tile buffer clear here in that case, since512* that would clear the tile buffer before we get to emit the actual513* color attachment store below, since the clear happens after the514* store is completed.515*516* If the attachment doesn't support TLB resolves then we will have to517* fallback to doing the resolve in a shader separately after this518* job, so we will need to store the multisampled sttachment even if that519* wansn't requested by the client.520*/521const bool needs_resolve =522subpass->resolve_attachments &&523subpass->resolve_attachments[i].attachment != VK_ATTACHMENT_UNUSED;524if (needs_resolve && attachment->use_tlb_resolve) {525const uint32_t resolve_attachment_idx =526subpass->resolve_attachments[i].attachment;527cmd_buffer_render_pass_emit_store(cmd_buffer, cl,528resolve_attachment_idx, layer,529RENDER_TARGET_0 + i,530false, true);531has_stores = true;532} else if (needs_resolve) {533needs_store = true;534}535536/* Emit the color attachment store if needed */537if (needs_store) {538cmd_buffer_render_pass_emit_store(cmd_buffer, cl,539attachment_idx, layer,540RENDER_TARGET_0 + i,541needs_clear && !use_global_rt_clear,542false);543has_stores = true;544} else if (needs_clear) {545use_global_rt_clear = true;546}547}548549/* We always need to emit at least one dummy store */550if (!has_stores) {551cl_emit(cl, STORE_TILE_BUFFER_GENERAL, store) {552store.buffer_to_store = NONE;553}554}555556/* If we have any depth/stencil clears we can't use the per-buffer clear557* bit and instead we have to emit a single clear of all tile buffers.558*/559if (use_global_zs_clear || use_global_rt_clear) {560cl_emit(cl, CLEAR_TILE_BUFFERS, clear) {561clear.clear_z_stencil_buffer = use_global_zs_clear;562clear.clear_all_render_targets = use_global_rt_clear;563}564}565}566567static void568cmd_buffer_render_pass_emit_per_tile_rcl(struct v3dv_cmd_buffer *cmd_buffer,569uint32_t layer)570{571struct v3dv_job *job = cmd_buffer->state.job;572assert(job);573574/* Emit the generic list in our indirect state -- the rcl will just575* have pointers into it.576*/577struct v3dv_cl *cl = &job->indirect;578v3dv_cl_ensure_space(cl, 200, 1);579v3dv_return_if_oom(cmd_buffer, NULL);580581struct v3dv_cl_reloc tile_list_start = v3dv_cl_get_address(cl);582583cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords);584585cmd_buffer_render_pass_emit_loads(cmd_buffer, cl, layer);586587/* The binner starts out writing tiles assuming that the initial mode588* is triangles, so make sure that's the case.589*/590cl_emit(cl, PRIM_LIST_FORMAT, fmt) {591fmt.primitive_type = LIST_TRIANGLES;592}593594/* PTB assumes that value to be 0, but hw will not set it. */595cl_emit(cl, SET_INSTANCEID, set) {596set.instance_id = 0;597}598599cl_emit(cl, BRANCH_TO_IMPLICIT_TILE_LIST, branch);600601cmd_buffer_render_pass_emit_stores(cmd_buffer, cl, layer);602603cl_emit(cl, END_OF_TILE_MARKER, end);604605cl_emit(cl, RETURN_FROM_SUB_LIST, ret);606607cl_emit(&job->rcl, START_ADDRESS_OF_GENERIC_TILE_LIST, branch) {608branch.start = tile_list_start;609branch.end = v3dv_cl_get_address(cl);610}611}612613static void614cmd_buffer_emit_render_pass_layer_rcl(struct v3dv_cmd_buffer *cmd_buffer,615uint32_t layer)616{617const struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;618619struct v3dv_job *job = cmd_buffer->state.job;620struct v3dv_cl *rcl = &job->rcl;621622/* If doing multicore binning, we would need to initialize each623* core's tile list here.624*/625const struct v3dv_frame_tiling *tiling = &job->frame_tiling;626const uint32_t tile_alloc_offset =62764 * layer * tiling->draw_tiles_x * tiling->draw_tiles_y;628cl_emit(rcl, MULTICORE_RENDERING_TILE_LIST_SET_BASE, list) {629list.address = v3dv_cl_address(job->tile_alloc, tile_alloc_offset);630}631632cl_emit(rcl, MULTICORE_RENDERING_SUPERTILE_CFG, config) {633config.number_of_bin_tile_lists = 1;634config.total_frame_width_in_tiles = tiling->draw_tiles_x;635config.total_frame_height_in_tiles = tiling->draw_tiles_y;636637config.supertile_width_in_tiles = tiling->supertile_width;638config.supertile_height_in_tiles = tiling->supertile_height;639640config.total_frame_width_in_supertiles =641tiling->frame_width_in_supertiles;642config.total_frame_height_in_supertiles =643tiling->frame_height_in_supertiles;644}645646/* Start by clearing the tile buffer. */647cl_emit(rcl, TILE_COORDINATES, coords) {648coords.tile_column_number = 0;649coords.tile_row_number = 0;650}651652/* Emit an initial clear of the tile buffers. This is necessary653* for any buffers that should be cleared (since clearing654* normally happens at the *end* of the generic tile list), but655* it's also nice to clear everything so the first tile doesn't656* inherit any contents from some previous frame.657*658* Also, implement the GFXH-1742 workaround. There's a race in659* the HW between the RCL updating the TLB's internal type/size660* and the spawning of the QPU instances using the TLB's current661* internal type/size. To make sure the QPUs get the right662* state, we need 1 dummy store in between internal type/size663* changes on V3D 3.x, and 2 dummy stores on 4.x.664*/665for (int i = 0; i < 2; i++) {666if (i > 0)667cl_emit(rcl, TILE_COORDINATES, coords);668cl_emit(rcl, END_OF_LOADS, end);669cl_emit(rcl, STORE_TILE_BUFFER_GENERAL, store) {670store.buffer_to_store = NONE;671}672if (i == 0 && cmd_buffer->state.tile_aligned_render_area) {673cl_emit(rcl, CLEAR_TILE_BUFFERS, clear) {674clear.clear_z_stencil_buffer = !job->early_zs_clear;675clear.clear_all_render_targets = true;676}677}678cl_emit(rcl, END_OF_TILE_MARKER, end);679}680681cl_emit(rcl, FLUSH_VCD_CACHE, flush);682683cmd_buffer_render_pass_emit_per_tile_rcl(cmd_buffer, layer);684685uint32_t supertile_w_in_pixels =686tiling->tile_width * tiling->supertile_width;687uint32_t supertile_h_in_pixels =688tiling->tile_height * tiling->supertile_height;689const uint32_t min_x_supertile =690state->render_area.offset.x / supertile_w_in_pixels;691const uint32_t min_y_supertile =692state->render_area.offset.y / supertile_h_in_pixels;693694uint32_t max_render_x = state->render_area.offset.x;695if (state->render_area.extent.width > 0)696max_render_x += state->render_area.extent.width - 1;697uint32_t max_render_y = state->render_area.offset.y;698if (state->render_area.extent.height > 0)699max_render_y += state->render_area.extent.height - 1;700const uint32_t max_x_supertile = max_render_x / supertile_w_in_pixels;701const uint32_t max_y_supertile = max_render_y / supertile_h_in_pixels;702703for (int y = min_y_supertile; y <= max_y_supertile; y++) {704for (int x = min_x_supertile; x <= max_x_supertile; x++) {705cl_emit(rcl, SUPERTILE_COORDINATES, coords) {706coords.column_number_in_supertiles = x;707coords.row_number_in_supertiles = y;708}709}710}711}712713static void714set_rcl_early_z_config(struct v3dv_job *job,715bool *early_z_disable,716uint32_t *early_z_test_and_update_direction)717{718/* If this is true then we have not emitted any draw calls in this job719* and we don't get any benefits form early Z.720*/721if (!job->decided_global_ez_enable) {722assert(job->draw_count == 0);723*early_z_disable = true;724return;725}726727switch (job->first_ez_state) {728case V3D_EZ_UNDECIDED:729case V3D_EZ_LT_LE:730*early_z_disable = false;731*early_z_test_and_update_direction = EARLY_Z_DIRECTION_LT_LE;732break;733case V3D_EZ_GT_GE:734*early_z_disable = false;735*early_z_test_and_update_direction = EARLY_Z_DIRECTION_GT_GE;736break;737case V3D_EZ_DISABLED:738*early_z_disable = true;739break;740}741}742743void744v3dX(cmd_buffer_emit_render_pass_rcl)(struct v3dv_cmd_buffer *cmd_buffer)745{746struct v3dv_job *job = cmd_buffer->state.job;747assert(job);748749const struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;750const struct v3dv_framebuffer *framebuffer = state->framebuffer;751752/* We can't emit the RCL until we have a framebuffer, which we may not have753* if we are recording a secondary command buffer. In that case, we will754* have to wait until vkCmdExecuteCommands is called from a primary command755* buffer.756*/757if (!framebuffer) {758assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY);759return;760}761762const struct v3dv_frame_tiling *tiling = &job->frame_tiling;763764const uint32_t fb_layers = framebuffer->layers;765v3dv_cl_ensure_space_with_branch(&job->rcl, 200 +766MAX2(fb_layers, 1) * 256 *767cl_packet_length(SUPERTILE_COORDINATES));768v3dv_return_if_oom(cmd_buffer, NULL);769770assert(state->subpass_idx < state->pass->subpass_count);771const struct v3dv_render_pass *pass = state->pass;772const struct v3dv_subpass *subpass = &pass->subpasses[state->subpass_idx];773struct v3dv_cl *rcl = &job->rcl;774775/* Comon config must be the first TILE_RENDERING_MODE_CFG and776* Z_STENCIL_CLEAR_VALUES must be last. The ones in between are optional777* updates to the previous HW state.778*/779bool do_early_zs_clear = false;780const uint32_t ds_attachment_idx = subpass->ds_attachment.attachment;781cl_emit(rcl, TILE_RENDERING_MODE_CFG_COMMON, config) {782config.image_width_pixels = framebuffer->width;783config.image_height_pixels = framebuffer->height;784config.number_of_render_targets = MAX2(subpass->color_count, 1);785config.multisample_mode_4x = tiling->msaa;786config.maximum_bpp_of_all_render_targets = tiling->internal_bpp;787788if (ds_attachment_idx != VK_ATTACHMENT_UNUSED) {789const struct v3dv_image_view *iview =790framebuffer->attachments[ds_attachment_idx];791config.internal_depth_type = iview->internal_type;792793set_rcl_early_z_config(job,794&config.early_z_disable,795&config.early_z_test_and_update_direction);796797/* Early-Z/S clear can be enabled if the job is clearing and not798* storing (or loading) depth. If a stencil aspect is also present799* we have the same requirements for it, however, in this case we800* can accept stencil loadOp DONT_CARE as well, so instead of801* checking that stencil is cleared we check that is not loaded.802*803* Early-Z/S clearing is independent of Early Z/S testing, so it is804* possible to enable one but not the other so long as their805* respective requirements are met.806*/807struct v3dv_render_pass_attachment *ds_attachment =808&pass->attachments[ds_attachment_idx];809810const VkImageAspectFlags ds_aspects =811vk_format_aspects(ds_attachment->desc.format);812813bool needs_depth_clear =814check_needs_clear(state,815ds_aspects & VK_IMAGE_ASPECT_DEPTH_BIT,816ds_attachment->first_subpass,817ds_attachment->desc.loadOp,818subpass->do_depth_clear_with_draw);819820bool needs_depth_store =821check_needs_store(state,822ds_aspects & VK_IMAGE_ASPECT_DEPTH_BIT,823ds_attachment->last_subpass,824ds_attachment->desc.storeOp);825826do_early_zs_clear = needs_depth_clear && !needs_depth_store;827if (do_early_zs_clear &&828vk_format_has_stencil(ds_attachment->desc.format)) {829bool needs_stencil_load =830check_needs_load(state,831ds_aspects & VK_IMAGE_ASPECT_STENCIL_BIT,832ds_attachment->first_subpass,833ds_attachment->desc.stencilLoadOp);834835bool needs_stencil_store =836check_needs_store(state,837ds_aspects & VK_IMAGE_ASPECT_STENCIL_BIT,838ds_attachment->last_subpass,839ds_attachment->desc.stencilStoreOp);840841do_early_zs_clear = !needs_stencil_load && !needs_stencil_store;842}843844config.early_depth_stencil_clear = do_early_zs_clear;845} else {846config.early_z_disable = true;847}848}849850/* If we enabled early Z/S clear, then we can't emit any "Clear Tile Buffers"851* commands with the Z/S bit set, so keep track of whether we enabled this852* in the job so we can skip these later.853*/854job->early_zs_clear = do_early_zs_clear;855856for (uint32_t i = 0; i < subpass->color_count; i++) {857uint32_t attachment_idx = subpass->color_attachments[i].attachment;858if (attachment_idx == VK_ATTACHMENT_UNUSED)859continue;860861struct v3dv_image_view *iview =862state->framebuffer->attachments[attachment_idx];863864const struct v3dv_image *image = iview->image;865const struct v3d_resource_slice *slice = &image->slices[iview->base_level];866867const uint32_t *clear_color =868&state->attachments[attachment_idx].clear_value.color[0];869870uint32_t clear_pad = 0;871if (slice->tiling == V3D_TILING_UIF_NO_XOR ||872slice->tiling == V3D_TILING_UIF_XOR) {873int uif_block_height = v3d_utile_height(image->cpp) * 2;874875uint32_t implicit_padded_height =876align(framebuffer->height, uif_block_height) / uif_block_height;877878if (slice->padded_height_of_output_image_in_uif_blocks -879implicit_padded_height >= 15) {880clear_pad = slice->padded_height_of_output_image_in_uif_blocks;881}882}883884cl_emit(rcl, TILE_RENDERING_MODE_CFG_CLEAR_COLORS_PART1, clear) {885clear.clear_color_low_32_bits = clear_color[0];886clear.clear_color_next_24_bits = clear_color[1] & 0xffffff;887clear.render_target_number = i;888};889890if (iview->internal_bpp >= V3D_INTERNAL_BPP_64) {891cl_emit(rcl, TILE_RENDERING_MODE_CFG_CLEAR_COLORS_PART2, clear) {892clear.clear_color_mid_low_32_bits =893((clear_color[1] >> 24) | (clear_color[2] << 8));894clear.clear_color_mid_high_24_bits =895((clear_color[2] >> 24) | ((clear_color[3] & 0xffff) << 8));896clear.render_target_number = i;897};898}899900if (iview->internal_bpp >= V3D_INTERNAL_BPP_128 || clear_pad) {901cl_emit(rcl, TILE_RENDERING_MODE_CFG_CLEAR_COLORS_PART3, clear) {902clear.uif_padded_height_in_uif_blocks = clear_pad;903clear.clear_color_high_16_bits = clear_color[3] >> 16;904clear.render_target_number = i;905};906}907}908909cl_emit(rcl, TILE_RENDERING_MODE_CFG_COLOR, rt) {910v3dX(cmd_buffer_render_pass_setup_render_target)911(cmd_buffer, 0, &rt.render_target_0_internal_bpp,912&rt.render_target_0_internal_type, &rt.render_target_0_clamp);913v3dX(cmd_buffer_render_pass_setup_render_target)914(cmd_buffer, 1, &rt.render_target_1_internal_bpp,915&rt.render_target_1_internal_type, &rt.render_target_1_clamp);916v3dX(cmd_buffer_render_pass_setup_render_target)917(cmd_buffer, 2, &rt.render_target_2_internal_bpp,918&rt.render_target_2_internal_type, &rt.render_target_2_clamp);919v3dX(cmd_buffer_render_pass_setup_render_target)920(cmd_buffer, 3, &rt.render_target_3_internal_bpp,921&rt.render_target_3_internal_type, &rt.render_target_3_clamp);922}923924/* Ends rendering mode config. */925if (ds_attachment_idx != VK_ATTACHMENT_UNUSED) {926cl_emit(rcl, TILE_RENDERING_MODE_CFG_ZS_CLEAR_VALUES, clear) {927clear.z_clear_value =928state->attachments[ds_attachment_idx].clear_value.z;929clear.stencil_clear_value =930state->attachments[ds_attachment_idx].clear_value.s;931};932} else {933cl_emit(rcl, TILE_RENDERING_MODE_CFG_ZS_CLEAR_VALUES, clear) {934clear.z_clear_value = 1.0f;935clear.stencil_clear_value = 0;936};937}938939/* Always set initial block size before the first branch, which needs940* to match the value from binning mode config.941*/942cl_emit(rcl, TILE_LIST_INITIAL_BLOCK_SIZE, init) {943init.use_auto_chained_tile_lists = true;944init.size_of_first_block_in_chained_tile_lists =945TILE_ALLOCATION_BLOCK_SIZE_64B;946}947948for (int layer = 0; layer < MAX2(1, fb_layers); layer++)949cmd_buffer_emit_render_pass_layer_rcl(cmd_buffer, layer);950951cl_emit(rcl, END_OF_RENDERING, end);952}953954void955v3dX(cmd_buffer_emit_viewport)(struct v3dv_cmd_buffer *cmd_buffer)956{957struct v3dv_dynamic_state *dynamic = &cmd_buffer->state.dynamic;958/* FIXME: right now we only support one viewport. viewporst[0] would work959* now, would need to change if we allow multiple viewports960*/961float *vptranslate = dynamic->viewport.translate[0];962float *vpscale = dynamic->viewport.scale[0];963964struct v3dv_job *job = cmd_buffer->state.job;965assert(job);966967const uint32_t required_cl_size =968cl_packet_length(CLIPPER_XY_SCALING) +969cl_packet_length(CLIPPER_Z_SCALE_AND_OFFSET) +970cl_packet_length(CLIPPER_Z_MIN_MAX_CLIPPING_PLANES) +971cl_packet_length(VIEWPORT_OFFSET);972v3dv_cl_ensure_space_with_branch(&job->bcl, required_cl_size);973v3dv_return_if_oom(cmd_buffer, NULL);974975cl_emit(&job->bcl, CLIPPER_XY_SCALING, clip) {976clip.viewport_half_width_in_1_256th_of_pixel = vpscale[0] * 256.0f;977clip.viewport_half_height_in_1_256th_of_pixel = vpscale[1] * 256.0f;978}979980cl_emit(&job->bcl, CLIPPER_Z_SCALE_AND_OFFSET, clip) {981clip.viewport_z_offset_zc_to_zs = vptranslate[2];982clip.viewport_z_scale_zc_to_zs = vpscale[2];983}984cl_emit(&job->bcl, CLIPPER_Z_MIN_MAX_CLIPPING_PLANES, clip) {985/* Vulkan's Z NDC is [0..1], unlile OpenGL which is [-1, 1] */986float z1 = vptranslate[2];987float z2 = vptranslate[2] + vpscale[2];988clip.minimum_zw = MIN2(z1, z2);989clip.maximum_zw = MAX2(z1, z2);990}991992cl_emit(&job->bcl, VIEWPORT_OFFSET, vp) {993vp.viewport_centre_x_coordinate = vptranslate[0];994vp.viewport_centre_y_coordinate = vptranslate[1];995}996997cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_VIEWPORT;998}9991000void1001v3dX(cmd_buffer_emit_stencil)(struct v3dv_cmd_buffer *cmd_buffer)1002{1003struct v3dv_job *job = cmd_buffer->state.job;1004assert(job);10051006struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;1007struct v3dv_dynamic_state *dynamic_state = &cmd_buffer->state.dynamic;10081009const uint32_t dynamic_stencil_states = V3DV_DYNAMIC_STENCIL_COMPARE_MASK |1010V3DV_DYNAMIC_STENCIL_WRITE_MASK |1011V3DV_DYNAMIC_STENCIL_REFERENCE;10121013v3dv_cl_ensure_space_with_branch(&job->bcl,10142 * cl_packet_length(STENCIL_CFG));1015v3dv_return_if_oom(cmd_buffer, NULL);10161017bool emitted_stencil = false;1018for (uint32_t i = 0; i < 2; i++) {1019if (pipeline->emit_stencil_cfg[i]) {1020if (dynamic_state->mask & dynamic_stencil_states) {1021cl_emit_with_prepacked(&job->bcl, STENCIL_CFG,1022pipeline->stencil_cfg[i], config) {1023if (dynamic_state->mask & V3DV_DYNAMIC_STENCIL_COMPARE_MASK) {1024config.stencil_test_mask =1025i == 0 ? dynamic_state->stencil_compare_mask.front :1026dynamic_state->stencil_compare_mask.back;1027}1028if (dynamic_state->mask & V3DV_DYNAMIC_STENCIL_WRITE_MASK) {1029config.stencil_write_mask =1030i == 0 ? dynamic_state->stencil_write_mask.front :1031dynamic_state->stencil_write_mask.back;1032}1033if (dynamic_state->mask & V3DV_DYNAMIC_STENCIL_REFERENCE) {1034config.stencil_ref_value =1035i == 0 ? dynamic_state->stencil_reference.front :1036dynamic_state->stencil_reference.back;1037}1038}1039} else {1040cl_emit_prepacked(&job->bcl, &pipeline->stencil_cfg[i]);1041}10421043emitted_stencil = true;1044}1045}10461047if (emitted_stencil) {1048const uint32_t dynamic_stencil_dirty_flags =1049V3DV_CMD_DIRTY_STENCIL_COMPARE_MASK |1050V3DV_CMD_DIRTY_STENCIL_WRITE_MASK |1051V3DV_CMD_DIRTY_STENCIL_REFERENCE;1052cmd_buffer->state.dirty &= ~dynamic_stencil_dirty_flags;1053}1054}10551056void1057v3dX(cmd_buffer_emit_depth_bias)(struct v3dv_cmd_buffer *cmd_buffer)1058{1059struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;1060assert(pipeline);10611062if (!pipeline->depth_bias.enabled)1063return;10641065struct v3dv_job *job = cmd_buffer->state.job;1066assert(job);10671068v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(DEPTH_OFFSET));1069v3dv_return_if_oom(cmd_buffer, NULL);10701071struct v3dv_dynamic_state *dynamic = &cmd_buffer->state.dynamic;1072cl_emit(&job->bcl, DEPTH_OFFSET, bias) {1073bias.depth_offset_factor = dynamic->depth_bias.slope_factor;1074bias.depth_offset_units = dynamic->depth_bias.constant_factor;1075if (pipeline->depth_bias.is_z16)1076bias.depth_offset_units *= 256.0f;1077bias.limit = dynamic->depth_bias.depth_bias_clamp;1078}10791080cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_DEPTH_BIAS;1081}10821083void1084v3dX(cmd_buffer_emit_line_width)(struct v3dv_cmd_buffer *cmd_buffer)1085{1086struct v3dv_job *job = cmd_buffer->state.job;1087assert(job);10881089v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(LINE_WIDTH));1090v3dv_return_if_oom(cmd_buffer, NULL);10911092cl_emit(&job->bcl, LINE_WIDTH, line) {1093line.line_width = cmd_buffer->state.dynamic.line_width;1094}10951096cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_LINE_WIDTH;1097}10981099void1100v3dX(cmd_buffer_emit_sample_state)(struct v3dv_cmd_buffer *cmd_buffer)1101{1102struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;1103assert(pipeline);11041105struct v3dv_job *job = cmd_buffer->state.job;1106assert(job);11071108v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(SAMPLE_STATE));1109v3dv_return_if_oom(cmd_buffer, NULL);11101111cl_emit(&job->bcl, SAMPLE_STATE, state) {1112state.coverage = 1.0f;1113state.mask = pipeline->sample_mask;1114}1115}11161117void1118v3dX(cmd_buffer_emit_blend)(struct v3dv_cmd_buffer *cmd_buffer)1119{1120struct v3dv_job *job = cmd_buffer->state.job;1121assert(job);11221123struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;1124assert(pipeline);11251126const uint32_t blend_packets_size =1127cl_packet_length(BLEND_ENABLES) +1128cl_packet_length(BLEND_CONSTANT_COLOR) +1129cl_packet_length(BLEND_CFG) * V3D_MAX_DRAW_BUFFERS +1130cl_packet_length(COLOR_WRITE_MASKS);11311132v3dv_cl_ensure_space_with_branch(&job->bcl, blend_packets_size);1133v3dv_return_if_oom(cmd_buffer, NULL);11341135if (cmd_buffer->state.dirty & V3DV_CMD_DIRTY_PIPELINE) {1136if (pipeline->blend.enables) {1137cl_emit(&job->bcl, BLEND_ENABLES, enables) {1138enables.mask = pipeline->blend.enables;1139}1140}11411142for (uint32_t i = 0; i < V3D_MAX_DRAW_BUFFERS; i++) {1143if (pipeline->blend.enables & (1 << i))1144cl_emit_prepacked(&job->bcl, &pipeline->blend.cfg[i]);1145}11461147cl_emit(&job->bcl, COLOR_WRITE_MASKS, mask) {1148mask.mask = pipeline->blend.color_write_masks;1149}1150}11511152if (pipeline->blend.needs_color_constants &&1153cmd_buffer->state.dirty & V3DV_CMD_DIRTY_BLEND_CONSTANTS) {1154struct v3dv_dynamic_state *dynamic = &cmd_buffer->state.dynamic;1155cl_emit(&job->bcl, BLEND_CONSTANT_COLOR, color) {1156color.red_f16 = _mesa_float_to_half(dynamic->blend_constants[0]);1157color.green_f16 = _mesa_float_to_half(dynamic->blend_constants[1]);1158color.blue_f16 = _mesa_float_to_half(dynamic->blend_constants[2]);1159color.alpha_f16 = _mesa_float_to_half(dynamic->blend_constants[3]);1160}1161cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_BLEND_CONSTANTS;1162}1163}11641165static void1166emit_flat_shade_flags(struct v3dv_job *job,1167int varying_offset,1168uint32_t varyings,1169enum V3DX(Varying_Flags_Action) lower,1170enum V3DX(Varying_Flags_Action) higher)1171{1172v3dv_cl_ensure_space_with_branch(&job->bcl,1173cl_packet_length(FLAT_SHADE_FLAGS));1174v3dv_return_if_oom(NULL, job);11751176cl_emit(&job->bcl, FLAT_SHADE_FLAGS, flags) {1177flags.varying_offset_v0 = varying_offset;1178flags.flat_shade_flags_for_varyings_v024 = varyings;1179flags.action_for_flat_shade_flags_of_lower_numbered_varyings = lower;1180flags.action_for_flat_shade_flags_of_higher_numbered_varyings = higher;1181}1182}11831184static void1185emit_noperspective_flags(struct v3dv_job *job,1186int varying_offset,1187uint32_t varyings,1188enum V3DX(Varying_Flags_Action) lower,1189enum V3DX(Varying_Flags_Action) higher)1190{1191v3dv_cl_ensure_space_with_branch(&job->bcl,1192cl_packet_length(NON_PERSPECTIVE_FLAGS));1193v3dv_return_if_oom(NULL, job);11941195cl_emit(&job->bcl, NON_PERSPECTIVE_FLAGS, flags) {1196flags.varying_offset_v0 = varying_offset;1197flags.non_perspective_flags_for_varyings_v024 = varyings;1198flags.action_for_non_perspective_flags_of_lower_numbered_varyings = lower;1199flags.action_for_non_perspective_flags_of_higher_numbered_varyings = higher;1200}1201}12021203static void1204emit_centroid_flags(struct v3dv_job *job,1205int varying_offset,1206uint32_t varyings,1207enum V3DX(Varying_Flags_Action) lower,1208enum V3DX(Varying_Flags_Action) higher)1209{1210v3dv_cl_ensure_space_with_branch(&job->bcl,1211cl_packet_length(CENTROID_FLAGS));1212v3dv_return_if_oom(NULL, job);12131214cl_emit(&job->bcl, CENTROID_FLAGS, flags) {1215flags.varying_offset_v0 = varying_offset;1216flags.centroid_flags_for_varyings_v024 = varyings;1217flags.action_for_centroid_flags_of_lower_numbered_varyings = lower;1218flags.action_for_centroid_flags_of_higher_numbered_varyings = higher;1219}1220}12211222static bool1223emit_varying_flags(struct v3dv_job *job,1224uint32_t num_flags,1225const uint32_t *flags,1226void (*flag_emit_callback)(struct v3dv_job *job,1227int varying_offset,1228uint32_t flags,1229enum V3DX(Varying_Flags_Action) lower,1230enum V3DX(Varying_Flags_Action) higher))1231{1232bool emitted_any = false;1233for (int i = 0; i < num_flags; i++) {1234if (!flags[i])1235continue;12361237if (emitted_any) {1238flag_emit_callback(job, i, flags[i],1239V3D_VARYING_FLAGS_ACTION_UNCHANGED,1240V3D_VARYING_FLAGS_ACTION_UNCHANGED);1241} else if (i == 0) {1242flag_emit_callback(job, i, flags[i],1243V3D_VARYING_FLAGS_ACTION_UNCHANGED,1244V3D_VARYING_FLAGS_ACTION_ZEROED);1245} else {1246flag_emit_callback(job, i, flags[i],1247V3D_VARYING_FLAGS_ACTION_ZEROED,1248V3D_VARYING_FLAGS_ACTION_ZEROED);1249}12501251emitted_any = true;1252}12531254return emitted_any;1255}12561257void1258v3dX(cmd_buffer_emit_varyings_state)(struct v3dv_cmd_buffer *cmd_buffer)1259{1260struct v3dv_job *job = cmd_buffer->state.job;1261struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;12621263struct v3d_fs_prog_data *prog_data_fs =1264pipeline->shared_data->variants[BROADCOM_SHADER_FRAGMENT]->prog_data.fs;12651266const uint32_t num_flags =1267ARRAY_SIZE(prog_data_fs->flat_shade_flags);1268const uint32_t *flat_shade_flags = prog_data_fs->flat_shade_flags;1269const uint32_t *noperspective_flags = prog_data_fs->noperspective_flags;1270const uint32_t *centroid_flags = prog_data_fs->centroid_flags;12711272if (!emit_varying_flags(job, num_flags, flat_shade_flags,1273emit_flat_shade_flags)) {1274v3dv_cl_ensure_space_with_branch(1275&job->bcl, cl_packet_length(ZERO_ALL_FLAT_SHADE_FLAGS));1276v3dv_return_if_oom(cmd_buffer, NULL);12771278cl_emit(&job->bcl, ZERO_ALL_FLAT_SHADE_FLAGS, flags);1279}12801281if (!emit_varying_flags(job, num_flags, noperspective_flags,1282emit_noperspective_flags)) {1283v3dv_cl_ensure_space_with_branch(1284&job->bcl, cl_packet_length(ZERO_ALL_NON_PERSPECTIVE_FLAGS));1285v3dv_return_if_oom(cmd_buffer, NULL);12861287cl_emit(&job->bcl, ZERO_ALL_NON_PERSPECTIVE_FLAGS, flags);1288}12891290if (!emit_varying_flags(job, num_flags, centroid_flags,1291emit_centroid_flags)) {1292v3dv_cl_ensure_space_with_branch(1293&job->bcl, cl_packet_length(ZERO_ALL_CENTROID_FLAGS));1294v3dv_return_if_oom(cmd_buffer, NULL);12951296cl_emit(&job->bcl, ZERO_ALL_CENTROID_FLAGS, flags);1297}1298}12991300static void1301job_update_ez_state(struct v3dv_job *job,1302struct v3dv_pipeline *pipeline,1303struct v3dv_cmd_buffer *cmd_buffer)1304{1305/* If first_ez_state is V3D_EZ_DISABLED it means that we have already1306* determined that we should disable EZ completely for all draw calls in1307* this job. This will cause us to disable EZ for the entire job in the1308* Tile Rendering Mode RCL packet and when we do that we need to make sure1309* we never emit a draw call in the job with EZ enabled in the CFG_BITS1310* packet, so ez_state must also be V3D_EZ_DISABLED;1311*/1312if (job->first_ez_state == V3D_EZ_DISABLED) {1313assert(job->ez_state == V3D_EZ_DISABLED);1314return;1315}13161317/* This is part of the pre draw call handling, so we should be inside a1318* render pass.1319*/1320assert(cmd_buffer->state.pass);13211322/* If this is the first time we update EZ state for this job we first check1323* if there is anything that requires disabling it completely for the entire1324* job (based on state that is not related to the current draw call and1325* pipeline state).1326*/1327if (!job->decided_global_ez_enable) {1328job->decided_global_ez_enable = true;13291330struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;1331assert(state->subpass_idx < state->pass->subpass_count);1332struct v3dv_subpass *subpass = &state->pass->subpasses[state->subpass_idx];1333if (subpass->ds_attachment.attachment == VK_ATTACHMENT_UNUSED) {1334job->first_ez_state = V3D_EZ_DISABLED;1335job->ez_state = V3D_EZ_DISABLED;1336return;1337}13381339/* GFXH-1918: the early-z buffer may load incorrect depth values1340* if the frame has odd width or height.1341*1342* So we need to disable EZ in this case.1343*/1344const struct v3dv_render_pass_attachment *ds_attachment =1345&state->pass->attachments[subpass->ds_attachment.attachment];13461347const VkImageAspectFlags ds_aspects =1348vk_format_aspects(ds_attachment->desc.format);13491350bool needs_depth_load =1351check_needs_load(state,1352ds_aspects & VK_IMAGE_ASPECT_DEPTH_BIT,1353ds_attachment->first_subpass,1354ds_attachment->desc.loadOp);13551356if (needs_depth_load) {1357struct v3dv_framebuffer *fb = state->framebuffer;13581359if (!fb) {1360assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY);1361perf_debug("Loading depth aspect in a secondary command buffer "1362"without framebuffer info disables early-z tests.\n");1363job->first_ez_state = V3D_EZ_DISABLED;1364job->ez_state = V3D_EZ_DISABLED;1365return;1366}13671368if (((fb->width % 2) != 0 || (fb->height % 2) != 0)) {1369perf_debug("Loading depth aspect for framebuffer with odd width "1370"or height disables early-Z tests.\n");1371job->first_ez_state = V3D_EZ_DISABLED;1372job->ez_state = V3D_EZ_DISABLED;1373return;1374}1375}1376}13771378/* Otherwise, we can decide to selectively enable or disable EZ for draw1379* calls using the CFG_BITS packet based on the bound pipeline state.1380*/13811382/* If the FS writes Z, then it may update against the chosen EZ direction */1383struct v3dv_shader_variant *fs_variant =1384pipeline->shared_data->variants[BROADCOM_SHADER_FRAGMENT];1385if (fs_variant->prog_data.fs->writes_z) {1386job->ez_state = V3D_EZ_DISABLED;1387return;1388}13891390switch (pipeline->ez_state) {1391case V3D_EZ_UNDECIDED:1392/* If the pipeline didn't pick a direction but didn't disable, then go1393* along with the current EZ state. This allows EZ optimization for Z1394* func == EQUAL or NEVER.1395*/1396break;13971398case V3D_EZ_LT_LE:1399case V3D_EZ_GT_GE:1400/* If the pipeline picked a direction, then it needs to match the current1401* direction if we've decided on one.1402*/1403if (job->ez_state == V3D_EZ_UNDECIDED)1404job->ez_state = pipeline->ez_state;1405else if (job->ez_state != pipeline->ez_state)1406job->ez_state = V3D_EZ_DISABLED;1407break;14081409case V3D_EZ_DISABLED:1410/* If the pipeline disables EZ because of a bad Z func or stencil1411* operation, then we can't do any more EZ in this frame.1412*/1413job->ez_state = V3D_EZ_DISABLED;1414break;1415}14161417if (job->first_ez_state == V3D_EZ_UNDECIDED &&1418job->ez_state != V3D_EZ_DISABLED) {1419job->first_ez_state = job->ez_state;1420}1421}14221423void1424v3dX(cmd_buffer_emit_configuration_bits)(struct v3dv_cmd_buffer *cmd_buffer)1425{1426struct v3dv_job *job = cmd_buffer->state.job;1427assert(job);14281429struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;1430assert(pipeline);14311432job_update_ez_state(job, pipeline, cmd_buffer);14331434v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(CFG_BITS));1435v3dv_return_if_oom(cmd_buffer, NULL);14361437cl_emit_with_prepacked(&job->bcl, CFG_BITS, pipeline->cfg_bits, config) {1438config.early_z_enable = job->ez_state != V3D_EZ_DISABLED;1439config.early_z_updates_enable = config.early_z_enable &&1440pipeline->z_updates_enable;1441}1442}14431444void1445v3dX(cmd_buffer_emit_occlusion_query)(struct v3dv_cmd_buffer *cmd_buffer)1446{1447struct v3dv_job *job = cmd_buffer->state.job;1448assert(job);14491450v3dv_cl_ensure_space_with_branch(&job->bcl,1451cl_packet_length(OCCLUSION_QUERY_COUNTER));1452v3dv_return_if_oom(cmd_buffer, NULL);14531454cl_emit(&job->bcl, OCCLUSION_QUERY_COUNTER, counter) {1455if (cmd_buffer->state.query.active_query.bo) {1456counter.address =1457v3dv_cl_address(cmd_buffer->state.query.active_query.bo,1458cmd_buffer->state.query.active_query.offset);1459}1460}14611462cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_OCCLUSION_QUERY;1463}14641465static struct v3dv_job *1466cmd_buffer_subpass_split_for_barrier(struct v3dv_cmd_buffer *cmd_buffer,1467bool is_bcl_barrier)1468{1469assert(cmd_buffer->state.subpass_idx != -1);1470v3dv_cmd_buffer_finish_job(cmd_buffer);1471struct v3dv_job *job =1472v3dv_cmd_buffer_subpass_resume(cmd_buffer,1473cmd_buffer->state.subpass_idx);1474if (!job)1475return NULL;14761477job->serialize = true;1478job->needs_bcl_sync = is_bcl_barrier;1479return job;1480}14811482static void1483cmd_buffer_copy_secondary_end_query_state(struct v3dv_cmd_buffer *primary,1484struct v3dv_cmd_buffer *secondary)1485{1486struct v3dv_cmd_buffer_state *p_state = &primary->state;1487struct v3dv_cmd_buffer_state *s_state = &secondary->state;14881489const uint32_t total_state_count =1490p_state->query.end.used_count + s_state->query.end.used_count;1491v3dv_cmd_buffer_ensure_array_state(primary,1492sizeof(struct v3dv_end_query_cpu_job_info),1493total_state_count,1494&p_state->query.end.alloc_count,1495(void **) &p_state->query.end.states);1496v3dv_return_if_oom(primary, NULL);14971498for (uint32_t i = 0; i < s_state->query.end.used_count; i++) {1499const struct v3dv_end_query_cpu_job_info *s_qstate =1500&secondary->state.query.end.states[i];15011502struct v3dv_end_query_cpu_job_info *p_qstate =1503&p_state->query.end.states[p_state->query.end.used_count++];15041505p_qstate->pool = s_qstate->pool;1506p_qstate->query = s_qstate->query;1507}1508}15091510void1511v3dX(cmd_buffer_execute_inside_pass)(struct v3dv_cmd_buffer *primary,1512uint32_t cmd_buffer_count,1513const VkCommandBuffer *cmd_buffers)1514{1515assert(primary->state.job);15161517/* Emit occlusion query state if needed so the draw calls inside our1518* secondaries update the counters.1519*/1520bool has_occlusion_query =1521primary->state.dirty & V3DV_CMD_DIRTY_OCCLUSION_QUERY;1522if (has_occlusion_query)1523v3dX(cmd_buffer_emit_occlusion_query)(primary);15241525/* FIXME: if our primary job tiling doesn't enable MSSA but any of the1526* pipelines used by the secondaries do, we need to re-start the primary1527* job to enable MSAA. See cmd_buffer_restart_job_for_msaa_if_needed.1528*/1529bool pending_barrier = false;1530bool pending_bcl_barrier = false;1531for (uint32_t i = 0; i < cmd_buffer_count; i++) {1532V3DV_FROM_HANDLE(v3dv_cmd_buffer, secondary, cmd_buffers[i]);15331534assert(secondary->usage_flags &1535VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT);15361537list_for_each_entry(struct v3dv_job, secondary_job,1538&secondary->jobs, list_link) {1539if (secondary_job->type == V3DV_JOB_TYPE_GPU_CL_SECONDARY) {1540/* If the job is a CL, then we branch to it from the primary BCL.1541* In this case the secondary's BCL is finished with a1542* RETURN_FROM_SUB_LIST command to return back to the primary BCL1543* once we are done executing it.1544*/1545assert(v3dv_cl_offset(&secondary_job->rcl) == 0);1546assert(secondary_job->bcl.bo);15471548/* Sanity check that secondary BCL ends with RETURN_FROM_SUB_LIST */1549STATIC_ASSERT(cl_packet_length(RETURN_FROM_SUB_LIST) == 1);1550assert(v3dv_cl_offset(&secondary_job->bcl) >= 1);1551assert(*(((uint8_t *)secondary_job->bcl.next) - 1) ==1552V3DX(RETURN_FROM_SUB_LIST_opcode));15531554/* If this secondary has any barriers (or we had any pending barrier1555* to apply), then we can't just branch to it from the primary, we1556* need to split the primary to create a new job that can consume1557* the barriers first.1558*1559* FIXME: in this case, maybe just copy the secondary BCL without1560* the RETURN_FROM_SUB_LIST into the primary job to skip the1561* branch?1562*/1563struct v3dv_job *primary_job = primary->state.job;1564if (!primary_job || secondary_job->serialize || pending_barrier) {1565const bool needs_bcl_barrier =1566secondary_job->needs_bcl_sync || pending_bcl_barrier;1567primary_job =1568cmd_buffer_subpass_split_for_barrier(primary,1569needs_bcl_barrier);1570v3dv_return_if_oom(primary, NULL);15711572/* Since we have created a new primary we need to re-emit1573* occlusion query state.1574*/1575if (has_occlusion_query)1576v3dX(cmd_buffer_emit_occlusion_query)(primary);1577}15781579/* Make sure our primary job has all required BO references */1580set_foreach(secondary_job->bos, entry) {1581struct v3dv_bo *bo = (struct v3dv_bo *)entry->key;1582v3dv_job_add_bo(primary_job, bo);1583}15841585/* Emit required branch instructions. We expect each of these1586* to end with a corresponding 'return from sub list' item.1587*/1588list_for_each_entry(struct v3dv_bo, bcl_bo,1589&secondary_job->bcl.bo_list, list_link) {1590v3dv_cl_ensure_space_with_branch(&primary_job->bcl,1591cl_packet_length(BRANCH_TO_SUB_LIST));1592v3dv_return_if_oom(primary, NULL);1593cl_emit(&primary_job->bcl, BRANCH_TO_SUB_LIST, branch) {1594branch.address = v3dv_cl_address(bcl_bo, 0);1595}1596}15971598primary_job->tmu_dirty_rcl |= secondary_job->tmu_dirty_rcl;1599} else {1600/* This is a regular job (CPU or GPU), so just finish the current1601* primary job (if any) and then add the secondary job to the1602* primary's job list right after it.1603*/1604v3dv_cmd_buffer_finish_job(primary);1605v3dv_job_clone_in_cmd_buffer(secondary_job, primary);1606if (pending_barrier) {1607secondary_job->serialize = true;1608if (pending_bcl_barrier)1609secondary_job->needs_bcl_sync = true;1610}1611}16121613pending_barrier = false;1614pending_bcl_barrier = false;1615}16161617/* If the secondary has recorded any vkCmdEndQuery commands, we need to1618* copy this state to the primary so it is processed properly when the1619* current primary job is finished.1620*/1621cmd_buffer_copy_secondary_end_query_state(primary, secondary);16221623/* If this secondary had any pending barrier state we will need that1624* barrier state consumed with whatever comes next in the primary.1625*/1626assert(secondary->state.has_barrier || !secondary->state.has_bcl_barrier);1627pending_barrier = secondary->state.has_barrier;1628pending_bcl_barrier = secondary->state.has_bcl_barrier;1629}16301631if (pending_barrier) {1632primary->state.has_barrier = true;1633primary->state.has_bcl_barrier |= pending_bcl_barrier;1634}1635}16361637static void1638emit_gs_shader_state_record(struct v3dv_job *job,1639struct v3dv_bo *assembly_bo,1640struct v3dv_shader_variant *gs_bin,1641struct v3dv_cl_reloc gs_bin_uniforms,1642struct v3dv_shader_variant *gs,1643struct v3dv_cl_reloc gs_render_uniforms)1644{1645cl_emit(&job->indirect, GEOMETRY_SHADER_STATE_RECORD, shader) {1646shader.geometry_bin_mode_shader_code_address =1647v3dv_cl_address(assembly_bo, gs_bin->assembly_offset);1648shader.geometry_bin_mode_shader_4_way_threadable =1649gs_bin->prog_data.gs->base.threads == 4;1650shader.geometry_bin_mode_shader_start_in_final_thread_section =1651gs_bin->prog_data.gs->base.single_seg;1652shader.geometry_bin_mode_shader_propagate_nans = true;1653shader.geometry_bin_mode_shader_uniforms_address =1654gs_bin_uniforms;16551656shader.geometry_render_mode_shader_code_address =1657v3dv_cl_address(assembly_bo, gs->assembly_offset);1658shader.geometry_render_mode_shader_4_way_threadable =1659gs->prog_data.gs->base.threads == 4;1660shader.geometry_render_mode_shader_start_in_final_thread_section =1661gs->prog_data.gs->base.single_seg;1662shader.geometry_render_mode_shader_propagate_nans = true;1663shader.geometry_render_mode_shader_uniforms_address =1664gs_render_uniforms;1665}1666}16671668static uint8_t1669v3d_gs_output_primitive(uint32_t prim_type)1670{1671switch (prim_type) {1672case GL_POINTS:1673return GEOMETRY_SHADER_POINTS;1674case GL_LINE_STRIP:1675return GEOMETRY_SHADER_LINE_STRIP;1676case GL_TRIANGLE_STRIP:1677return GEOMETRY_SHADER_TRI_STRIP;1678default:1679unreachable("Unsupported primitive type");1680}1681}16821683static void1684emit_tes_gs_common_params(struct v3dv_job *job,1685uint8_t gs_out_prim_type,1686uint8_t gs_num_invocations)1687{1688cl_emit(&job->indirect, TESSELLATION_GEOMETRY_COMMON_PARAMS, shader) {1689shader.tessellation_type = TESSELLATION_TYPE_TRIANGLE;1690shader.tessellation_point_mode = false;1691shader.tessellation_edge_spacing = TESSELLATION_EDGE_SPACING_EVEN;1692shader.tessellation_clockwise = true;1693shader.tessellation_invocations = 1;16941695shader.geometry_shader_output_format =1696v3d_gs_output_primitive(gs_out_prim_type);1697shader.geometry_shader_instances = gs_num_invocations & 0x1F;1698}1699}17001701static uint8_t1702simd_width_to_gs_pack_mode(uint32_t width)1703{1704switch (width) {1705case 16:1706return V3D_PACK_MODE_16_WAY;1707case 8:1708return V3D_PACK_MODE_8_WAY;1709case 4:1710return V3D_PACK_MODE_4_WAY;1711case 1:1712return V3D_PACK_MODE_1_WAY;1713default:1714unreachable("Invalid SIMD width");1715};1716}17171718static void1719emit_tes_gs_shader_params(struct v3dv_job *job,1720uint32_t gs_simd,1721uint32_t gs_vpm_output_size,1722uint32_t gs_max_vpm_input_size_per_batch)1723{1724cl_emit(&job->indirect, TESSELLATION_GEOMETRY_SHADER_PARAMS, shader) {1725shader.tcs_batch_flush_mode = V3D_TCS_FLUSH_MODE_FULLY_PACKED;1726shader.per_patch_data_column_depth = 1;1727shader.tcs_output_segment_size_in_sectors = 1;1728shader.tcs_output_segment_pack_mode = V3D_PACK_MODE_16_WAY;1729shader.tes_output_segment_size_in_sectors = 1;1730shader.tes_output_segment_pack_mode = V3D_PACK_MODE_16_WAY;1731shader.gs_output_segment_size_in_sectors = gs_vpm_output_size;1732shader.gs_output_segment_pack_mode =1733simd_width_to_gs_pack_mode(gs_simd);1734shader.tbg_max_patches_per_tcs_batch = 1;1735shader.tbg_max_extra_vertex_segs_for_patches_after_first = 0;1736shader.tbg_min_tcs_output_segments_required_in_play = 1;1737shader.tbg_min_per_patch_data_segments_required_in_play = 1;1738shader.tpg_max_patches_per_tes_batch = 1;1739shader.tpg_max_vertex_segments_per_tes_batch = 0;1740shader.tpg_max_tcs_output_segments_per_tes_batch = 1;1741shader.tpg_min_tes_output_segments_required_in_play = 1;1742shader.gbg_max_tes_output_vertex_segments_per_gs_batch =1743gs_max_vpm_input_size_per_batch;1744shader.gbg_min_gs_output_segments_required_in_play = 1;1745}1746}17471748void1749v3dX(cmd_buffer_emit_gl_shader_state)(struct v3dv_cmd_buffer *cmd_buffer)1750{1751struct v3dv_job *job = cmd_buffer->state.job;1752assert(job);17531754struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;1755struct v3dv_pipeline *pipeline = state->gfx.pipeline;1756assert(pipeline);17571758struct v3dv_shader_variant *vs_variant =1759pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX];1760struct v3d_vs_prog_data *prog_data_vs = vs_variant->prog_data.vs;17611762struct v3dv_shader_variant *vs_bin_variant =1763pipeline->shared_data->variants[BROADCOM_SHADER_VERTEX_BIN];1764struct v3d_vs_prog_data *prog_data_vs_bin = vs_bin_variant->prog_data.vs;17651766struct v3dv_shader_variant *fs_variant =1767pipeline->shared_data->variants[BROADCOM_SHADER_FRAGMENT];1768struct v3d_fs_prog_data *prog_data_fs = fs_variant->prog_data.fs;17691770struct v3dv_shader_variant *gs_variant = NULL;1771struct v3dv_shader_variant *gs_bin_variant = NULL;1772struct v3d_gs_prog_data *prog_data_gs = NULL;1773struct v3d_gs_prog_data *prog_data_gs_bin = NULL;1774if (pipeline->has_gs) {1775gs_variant =1776pipeline->shared_data->variants[BROADCOM_SHADER_GEOMETRY];1777prog_data_gs = gs_variant->prog_data.gs;17781779gs_bin_variant =1780pipeline->shared_data->variants[BROADCOM_SHADER_GEOMETRY_BIN];1781prog_data_gs_bin = gs_bin_variant->prog_data.gs;1782}17831784/* Update the cache dirty flag based on the shader progs data */1785job->tmu_dirty_rcl |= prog_data_vs_bin->base.tmu_dirty_rcl;1786job->tmu_dirty_rcl |= prog_data_vs->base.tmu_dirty_rcl;1787job->tmu_dirty_rcl |= prog_data_fs->base.tmu_dirty_rcl;1788if (pipeline->has_gs) {1789job->tmu_dirty_rcl |= prog_data_gs_bin->base.tmu_dirty_rcl;1790job->tmu_dirty_rcl |= prog_data_gs->base.tmu_dirty_rcl;1791}17921793/* See GFXH-930 workaround below */1794uint32_t num_elements_to_emit = MAX2(pipeline->va_count, 1);17951796uint32_t shader_state_record_length =1797cl_packet_length(GL_SHADER_STATE_RECORD);1798if (pipeline->has_gs) {1799shader_state_record_length +=1800cl_packet_length(GEOMETRY_SHADER_STATE_RECORD) +1801cl_packet_length(TESSELLATION_GEOMETRY_COMMON_PARAMS) +18022 * cl_packet_length(TESSELLATION_GEOMETRY_SHADER_PARAMS);1803}18041805uint32_t shader_rec_offset =1806v3dv_cl_ensure_space(&job->indirect,1807shader_state_record_length +1808num_elements_to_emit *1809cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD),181032);1811v3dv_return_if_oom(cmd_buffer, NULL);18121813struct v3dv_bo *assembly_bo = pipeline->shared_data->assembly_bo;18141815if (pipeline->has_gs) {1816emit_gs_shader_state_record(job,1817assembly_bo,1818gs_bin_variant,1819cmd_buffer->state.uniforms.gs_bin,1820gs_variant,1821cmd_buffer->state.uniforms.gs);18221823emit_tes_gs_common_params(job,1824prog_data_gs->out_prim_type,1825prog_data_gs->num_invocations);18261827emit_tes_gs_shader_params(job,1828pipeline->vpm_cfg_bin.gs_width,1829pipeline->vpm_cfg_bin.Gd,1830pipeline->vpm_cfg_bin.Gv);18311832emit_tes_gs_shader_params(job,1833pipeline->vpm_cfg.gs_width,1834pipeline->vpm_cfg.Gd,1835pipeline->vpm_cfg.Gv);1836}18371838struct v3dv_bo *default_attribute_values =1839pipeline->default_attribute_values != NULL ?1840pipeline->default_attribute_values :1841pipeline->device->default_attribute_float;18421843cl_emit_with_prepacked(&job->indirect, GL_SHADER_STATE_RECORD,1844pipeline->shader_state_record, shader) {18451846/* FIXME: we are setting this values here and during the1847* prepacking. This is because both cl_emit_with_prepacked and v3dvx_pack1848* asserts for minimum values of these. It would be good to get1849* v3dvx_pack to assert on the final value if possible1850*/1851shader.min_coord_shader_input_segments_required_in_play =1852pipeline->vpm_cfg_bin.As;1853shader.min_vertex_shader_input_segments_required_in_play =1854pipeline->vpm_cfg.As;18551856shader.coordinate_shader_code_address =1857v3dv_cl_address(assembly_bo, vs_bin_variant->assembly_offset);1858shader.vertex_shader_code_address =1859v3dv_cl_address(assembly_bo, vs_variant->assembly_offset);1860shader.fragment_shader_code_address =1861v3dv_cl_address(assembly_bo, fs_variant->assembly_offset);18621863shader.coordinate_shader_uniforms_address = cmd_buffer->state.uniforms.vs_bin;1864shader.vertex_shader_uniforms_address = cmd_buffer->state.uniforms.vs;1865shader.fragment_shader_uniforms_address = cmd_buffer->state.uniforms.fs;18661867shader.address_of_default_attribute_values =1868v3dv_cl_address(default_attribute_values, 0);18691870shader.any_shader_reads_hardware_written_primitive_id =1871(pipeline->has_gs && prog_data_gs->uses_pid) || prog_data_fs->uses_pid;1872shader.insert_primitive_id_as_first_varying_to_fragment_shader =1873!pipeline->has_gs && prog_data_fs->uses_pid;1874}18751876/* Upload vertex element attributes (SHADER_STATE_ATTRIBUTE_RECORD) */1877bool cs_loaded_any = false;1878const bool cs_uses_builtins = prog_data_vs_bin->uses_iid ||1879prog_data_vs_bin->uses_biid ||1880prog_data_vs_bin->uses_vid;1881const uint32_t packet_length =1882cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD);18831884uint32_t emitted_va_count = 0;1885for (uint32_t i = 0; emitted_va_count < pipeline->va_count; i++) {1886assert(i < MAX_VERTEX_ATTRIBS);18871888if (pipeline->va[i].vk_format == VK_FORMAT_UNDEFINED)1889continue;18901891const uint32_t binding = pipeline->va[i].binding;18921893/* We store each vertex attribute in the array using its driver location1894* as index.1895*/1896const uint32_t location = i;18971898struct v3dv_vertex_binding *c_vb = &cmd_buffer->state.vertex_bindings[binding];18991900cl_emit_with_prepacked(&job->indirect, GL_SHADER_STATE_ATTRIBUTE_RECORD,1901&pipeline->vertex_attrs[i * packet_length], attr) {19021903assert(c_vb->buffer->mem->bo);1904attr.address = v3dv_cl_address(c_vb->buffer->mem->bo,1905c_vb->buffer->mem_offset +1906pipeline->va[i].offset +1907c_vb->offset);19081909attr.number_of_values_read_by_coordinate_shader =1910prog_data_vs_bin->vattr_sizes[location];1911attr.number_of_values_read_by_vertex_shader =1912prog_data_vs->vattr_sizes[location];19131914/* GFXH-930: At least one attribute must be enabled and read by CS1915* and VS. If we have attributes being consumed by the VS but not1916* the CS, then set up a dummy load of the last attribute into the1917* CS's VPM inputs. (Since CS is just dead-code-elimination compared1918* to VS, we can't have CS loading but not VS).1919*1920* GFXH-1602: first attribute must be active if using builtins.1921*/1922if (prog_data_vs_bin->vattr_sizes[location])1923cs_loaded_any = true;19241925if (i == 0 && cs_uses_builtins && !cs_loaded_any) {1926attr.number_of_values_read_by_coordinate_shader = 1;1927cs_loaded_any = true;1928} else if (i == pipeline->va_count - 1 && !cs_loaded_any) {1929attr.number_of_values_read_by_coordinate_shader = 1;1930cs_loaded_any = true;1931}19321933attr.maximum_index = 0xffffff;1934}19351936emitted_va_count++;1937}19381939if (pipeline->va_count == 0) {1940/* GFXH-930: At least one attribute must be enabled and read1941* by CS and VS. If we have no attributes being consumed by1942* the shader, set up a dummy to be loaded into the VPM.1943*/1944cl_emit(&job->indirect, GL_SHADER_STATE_ATTRIBUTE_RECORD, attr) {1945/* Valid address of data whose value will be unused. */1946attr.address = v3dv_cl_address(job->indirect.bo, 0);19471948attr.type = ATTRIBUTE_FLOAT;1949attr.stride = 0;1950attr.vec_size = 1;19511952attr.number_of_values_read_by_coordinate_shader = 1;1953attr.number_of_values_read_by_vertex_shader = 1;1954}1955}19561957if (cmd_buffer->state.dirty & V3DV_CMD_DIRTY_PIPELINE) {1958v3dv_cl_ensure_space_with_branch(&job->bcl,1959sizeof(pipeline->vcm_cache_size));1960v3dv_return_if_oom(cmd_buffer, NULL);19611962cl_emit_prepacked(&job->bcl, &pipeline->vcm_cache_size);1963}19641965v3dv_cl_ensure_space_with_branch(&job->bcl,1966cl_packet_length(GL_SHADER_STATE));1967v3dv_return_if_oom(cmd_buffer, NULL);19681969if (pipeline->has_gs) {1970cl_emit(&job->bcl, GL_SHADER_STATE_INCLUDING_GS, state) {1971state.address = v3dv_cl_address(job->indirect.bo, shader_rec_offset);1972state.number_of_attribute_arrays = num_elements_to_emit;1973}1974} else {1975cl_emit(&job->bcl, GL_SHADER_STATE, state) {1976state.address = v3dv_cl_address(job->indirect.bo, shader_rec_offset);1977state.number_of_attribute_arrays = num_elements_to_emit;1978}1979}19801981cmd_buffer->state.dirty &= ~(V3DV_CMD_DIRTY_VERTEX_BUFFER |1982V3DV_CMD_DIRTY_DESCRIPTOR_SETS |1983V3DV_CMD_DIRTY_PUSH_CONSTANTS);1984cmd_buffer->state.dirty_descriptor_stages &= ~VK_SHADER_STAGE_ALL_GRAPHICS;1985cmd_buffer->state.dirty_push_constants_stages &= ~VK_SHADER_STAGE_ALL_GRAPHICS;1986}19871988/* FIXME: C&P from v3dx_draw. Refactor to common place? */1989static uint32_t1990v3d_hw_prim_type(enum pipe_prim_type prim_type)1991{1992switch (prim_type) {1993case PIPE_PRIM_POINTS:1994case PIPE_PRIM_LINES:1995case PIPE_PRIM_LINE_LOOP:1996case PIPE_PRIM_LINE_STRIP:1997case PIPE_PRIM_TRIANGLES:1998case PIPE_PRIM_TRIANGLE_STRIP:1999case PIPE_PRIM_TRIANGLE_FAN:2000return prim_type;20012002case PIPE_PRIM_LINES_ADJACENCY:2003case PIPE_PRIM_LINE_STRIP_ADJACENCY:2004case PIPE_PRIM_TRIANGLES_ADJACENCY:2005case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:2006return 8 + (prim_type - PIPE_PRIM_LINES_ADJACENCY);20072008default:2009unreachable("Unsupported primitive type");2010}2011}20122013void2014v3dX(cmd_buffer_emit_draw)(struct v3dv_cmd_buffer *cmd_buffer,2015struct v3dv_draw_info *info)2016{2017struct v3dv_job *job = cmd_buffer->state.job;2018assert(job);20192020struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;2021struct v3dv_pipeline *pipeline = state->gfx.pipeline;20222023assert(pipeline);20242025uint32_t hw_prim_type = v3d_hw_prim_type(pipeline->topology);20262027if (info->first_instance > 0) {2028v3dv_cl_ensure_space_with_branch(2029&job->bcl, cl_packet_length(BASE_VERTEX_BASE_INSTANCE));2030v3dv_return_if_oom(cmd_buffer, NULL);20312032cl_emit(&job->bcl, BASE_VERTEX_BASE_INSTANCE, base) {2033base.base_instance = info->first_instance;2034base.base_vertex = 0;2035}2036}20372038if (info->instance_count > 1) {2039v3dv_cl_ensure_space_with_branch(2040&job->bcl, cl_packet_length(VERTEX_ARRAY_INSTANCED_PRIMS));2041v3dv_return_if_oom(cmd_buffer, NULL);20422043cl_emit(&job->bcl, VERTEX_ARRAY_INSTANCED_PRIMS, prim) {2044prim.mode = hw_prim_type;2045prim.index_of_first_vertex = info->first_vertex;2046prim.number_of_instances = info->instance_count;2047prim.instance_length = info->vertex_count;2048}2049} else {2050v3dv_cl_ensure_space_with_branch(2051&job->bcl, cl_packet_length(VERTEX_ARRAY_PRIMS));2052v3dv_return_if_oom(cmd_buffer, NULL);2053cl_emit(&job->bcl, VERTEX_ARRAY_PRIMS, prim) {2054prim.mode = hw_prim_type;2055prim.length = info->vertex_count;2056prim.index_of_first_vertex = info->first_vertex;2057}2058}2059}20602061void2062v3dX(cmd_buffer_emit_index_buffer)(struct v3dv_cmd_buffer *cmd_buffer)2063{2064struct v3dv_job *job = cmd_buffer->state.job;2065assert(job);20662067/* We flag all state as dirty when we create a new job so make sure we2068* have a valid index buffer before attempting to emit state for it.2069*/2070struct v3dv_buffer *ibuffer =2071v3dv_buffer_from_handle(cmd_buffer->state.index_buffer.buffer);2072if (ibuffer) {2073v3dv_cl_ensure_space_with_branch(2074&job->bcl, cl_packet_length(INDEX_BUFFER_SETUP));2075v3dv_return_if_oom(cmd_buffer, NULL);20762077const uint32_t offset = cmd_buffer->state.index_buffer.offset;2078cl_emit(&job->bcl, INDEX_BUFFER_SETUP, ib) {2079ib.address = v3dv_cl_address(ibuffer->mem->bo,2080ibuffer->mem_offset + offset);2081ib.size = ibuffer->mem->bo->size;2082}2083}20842085cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_INDEX_BUFFER;2086}20872088void2089v3dX(cmd_buffer_emit_draw_indexed)(struct v3dv_cmd_buffer *cmd_buffer,2090uint32_t indexCount,2091uint32_t instanceCount,2092uint32_t firstIndex,2093int32_t vertexOffset,2094uint32_t firstInstance)2095{2096v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);20972098struct v3dv_job *job = cmd_buffer->state.job;2099assert(job);21002101const struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;2102uint32_t hw_prim_type = v3d_hw_prim_type(pipeline->topology);2103uint8_t index_type = ffs(cmd_buffer->state.index_buffer.index_size) - 1;2104uint32_t index_offset = firstIndex * cmd_buffer->state.index_buffer.index_size;21052106if (vertexOffset != 0 || firstInstance != 0) {2107v3dv_cl_ensure_space_with_branch(2108&job->bcl, cl_packet_length(BASE_VERTEX_BASE_INSTANCE));2109v3dv_return_if_oom(cmd_buffer, NULL);21102111cl_emit(&job->bcl, BASE_VERTEX_BASE_INSTANCE, base) {2112base.base_instance = firstInstance;2113base.base_vertex = vertexOffset;2114}2115}21162117if (instanceCount == 1) {2118v3dv_cl_ensure_space_with_branch(2119&job->bcl, cl_packet_length(INDEXED_PRIM_LIST));2120v3dv_return_if_oom(cmd_buffer, NULL);21212122cl_emit(&job->bcl, INDEXED_PRIM_LIST, prim) {2123prim.index_type = index_type;2124prim.length = indexCount;2125prim.index_offset = index_offset;2126prim.mode = hw_prim_type;2127prim.enable_primitive_restarts = pipeline->primitive_restart;2128}2129} else if (instanceCount > 1) {2130v3dv_cl_ensure_space_with_branch(2131&job->bcl, cl_packet_length(INDEXED_INSTANCED_PRIM_LIST));2132v3dv_return_if_oom(cmd_buffer, NULL);21332134cl_emit(&job->bcl, INDEXED_INSTANCED_PRIM_LIST, prim) {2135prim.index_type = index_type;2136prim.index_offset = index_offset;2137prim.mode = hw_prim_type;2138prim.enable_primitive_restarts = pipeline->primitive_restart;2139prim.number_of_instances = instanceCount;2140prim.instance_length = indexCount;2141}2142}2143}21442145void2146v3dX(cmd_buffer_emit_draw_indirect)(struct v3dv_cmd_buffer *cmd_buffer,2147struct v3dv_buffer *buffer,2148VkDeviceSize offset,2149uint32_t drawCount,2150uint32_t stride)2151{2152v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);21532154struct v3dv_job *job = cmd_buffer->state.job;2155assert(job);21562157const struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;2158uint32_t hw_prim_type = v3d_hw_prim_type(pipeline->topology);21592160v3dv_cl_ensure_space_with_branch(2161&job->bcl, cl_packet_length(INDIRECT_VERTEX_ARRAY_INSTANCED_PRIMS));2162v3dv_return_if_oom(cmd_buffer, NULL);21632164cl_emit(&job->bcl, INDIRECT_VERTEX_ARRAY_INSTANCED_PRIMS, prim) {2165prim.mode = hw_prim_type;2166prim.number_of_draw_indirect_array_records = drawCount;2167prim.stride_in_multiples_of_4_bytes = stride >> 2;2168prim.address = v3dv_cl_address(buffer->mem->bo,2169buffer->mem_offset + offset);2170}2171}21722173void2174v3dX(cmd_buffer_emit_indexed_indirect)(struct v3dv_cmd_buffer *cmd_buffer,2175struct v3dv_buffer *buffer,2176VkDeviceSize offset,2177uint32_t drawCount,2178uint32_t stride)2179{2180v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);21812182struct v3dv_job *job = cmd_buffer->state.job;2183assert(job);21842185const struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;2186uint32_t hw_prim_type = v3d_hw_prim_type(pipeline->topology);2187uint8_t index_type = ffs(cmd_buffer->state.index_buffer.index_size) - 1;21882189v3dv_cl_ensure_space_with_branch(2190&job->bcl, cl_packet_length(INDIRECT_INDEXED_INSTANCED_PRIM_LIST));2191v3dv_return_if_oom(cmd_buffer, NULL);21922193cl_emit(&job->bcl, INDIRECT_INDEXED_INSTANCED_PRIM_LIST, prim) {2194prim.index_type = index_type;2195prim.mode = hw_prim_type;2196prim.enable_primitive_restarts = pipeline->primitive_restart;2197prim.number_of_draw_indirect_indexed_records = drawCount;2198prim.stride_in_multiples_of_4_bytes = stride >> 2;2199prim.address = v3dv_cl_address(buffer->mem->bo,2200buffer->mem_offset + offset);2201}2202}22032204void2205v3dX(cmd_buffer_render_pass_setup_render_target)(struct v3dv_cmd_buffer *cmd_buffer,2206int rt,2207uint32_t *rt_bpp,2208uint32_t *rt_type,2209uint32_t *rt_clamp)2210{2211const struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;22122213assert(state->subpass_idx < state->pass->subpass_count);2214const struct v3dv_subpass *subpass =2215&state->pass->subpasses[state->subpass_idx];22162217if (rt >= subpass->color_count)2218return;22192220struct v3dv_subpass_attachment *attachment = &subpass->color_attachments[rt];2221const uint32_t attachment_idx = attachment->attachment;2222if (attachment_idx == VK_ATTACHMENT_UNUSED)2223return;22242225const struct v3dv_framebuffer *framebuffer = state->framebuffer;2226assert(attachment_idx < framebuffer->attachment_count);2227struct v3dv_image_view *iview = framebuffer->attachments[attachment_idx];2228assert(iview->aspects & VK_IMAGE_ASPECT_COLOR_BIT);22292230*rt_bpp = iview->internal_bpp;2231*rt_type = iview->internal_type;2232if (vk_format_is_int(iview->vk_format))2233*rt_clamp = V3D_RENDER_TARGET_CLAMP_INT;2234else if (vk_format_is_srgb(iview->vk_format))2235*rt_clamp = V3D_RENDER_TARGET_CLAMP_NORM;2236else2237*rt_clamp = V3D_RENDER_TARGET_CLAMP_NONE;2238}223922402241