diff --git a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c index 7e53d0486f0..68ce794e0ad 100644 --- a/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/csf/panvk_vX_cmd_draw.c @@ -835,6 +835,10 @@ get_tiler_desc(struct panvk_cmd_buffer *cmdbuf) const struct pan_fb_info *fbinfo = &cmdbuf->state.gfx.render.fb.info; + /* At this point, we should know sample count and the tile size should have + * been calculated */ + assert(fbinfo->nr_samples > 0 && fbinfo->tile_size > 0); + pan_pack(&tiler_tmpl, TILER_CONTEXT, cfg) { unsigned max_levels = tiler_features.max_levels; assert(max_levels >= 2); @@ -1119,6 +1123,11 @@ get_fb_descs(struct panvk_cmd_buffer *cmdbuf) struct panvk_device *dev = to_panvk_device(cmdbuf->vk.base.device); struct pan_fb_info *fbinfo = &cmdbuf->state.gfx.render.fb.info; + + /* At this point, we should know sample count and the tile size should have + * been calculated */ + assert(fbinfo->nr_samples > 0 && fbinfo->tile_size > 0); + bool simul_use = cmdbuf->flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; @@ -1305,6 +1314,8 @@ set_provoking_vertex_mode(struct panvk_cmd_buffer *cmdbuf) static VkResult get_render_ctx(struct panvk_cmd_buffer *cmdbuf) { + panvk_per_arch(cmd_select_tile_size)(cmdbuf); + VkResult result = get_tiler_desc(cmdbuf); if (result != VK_SUCCESS) return result; @@ -1889,6 +1900,31 @@ prepare_draw(struct panvk_cmd_buffer *cmdbuf, struct panvk_draw_info *draw) if (result != VK_SUCCESS) return result; + if (!cmdbuf->vk.dynamic_graphics_state.rs.rasterizer_discard_enable) { + const struct pan_fb_info *fbinfo = &cmdbuf->state.gfx.render.fb.info; + uint32_t *nr_samples = &cmdbuf->state.gfx.render.fb.nr_samples; + uint32_t rasterization_samples = + cmdbuf->vk.dynamic_graphics_state.ms.rasterization_samples; + + /* If there's no attachment, we patch nr_samples to match + * rasterization_samples, otherwise, we make sure those two numbers match. + */ + if (!cmdbuf->state.gfx.render.bound_attachments) { + assert(rasterization_samples > 0); + *nr_samples = rasterization_samples; + } else { + assert(rasterization_samples == *nr_samples); + } + + /* In case we already emitted tiler/framebuffer descriptors, we ensure + * that the sample count didn't change + * XXX: This currently can happen in case we resume a render pass with no + * attachements and without any draw as the FBD is emitted when suspending. + */ + assert(fbinfo->nr_samples == 0 || + fbinfo->nr_samples == cmdbuf->state.gfx.render.fb.nr_samples); + } + if (!inherits_render_ctx(cmdbuf)) { result = get_render_ctx(cmdbuf); if (result != VK_SUCCESS) @@ -1984,22 +2020,6 @@ panvk_cmd_draw(struct panvk_cmd_buffer *cmdbuf, struct panvk_draw_info *draw) cmdbuf->state.gfx.fs.required = fs_required(&cmdbuf->state.gfx, &cmdbuf->vk.dynamic_graphics_state); - if (!cmdbuf->vk.dynamic_graphics_state.rs.rasterizer_discard_enable) { - struct pan_fb_info *fbinfo = &cmdbuf->state.gfx.render.fb.info; - uint32_t rasterization_samples = - cmdbuf->vk.dynamic_graphics_state.ms.rasterization_samples; - - /* If there's no attachment, we patch nr_samples to match - * rasterization_samples, otherwise, we make sure those two numbers match. - */ - if (!cmdbuf->state.gfx.render.bound_attachments) { - assert(rasterization_samples > 0); - fbinfo->nr_samples = rasterization_samples; - } else { - assert(rasterization_samples == fbinfo->nr_samples); - } - } - result = prepare_draw(cmdbuf, draw); if (result != VK_SUCCESS) return; @@ -2162,22 +2182,6 @@ panvk_cmd_draw_indirect(struct panvk_cmd_buffer *cmdbuf, cmdbuf->state.gfx.fs.required = fs_required(&cmdbuf->state.gfx, &cmdbuf->vk.dynamic_graphics_state); - if (!cmdbuf->vk.dynamic_graphics_state.rs.rasterizer_discard_enable) { - struct pan_fb_info *fbinfo = &cmdbuf->state.gfx.render.fb.info; - uint32_t rasterization_samples = - cmdbuf->vk.dynamic_graphics_state.ms.rasterization_samples; - - /* If there's no attachment, we patch nr_samples to match - * rasterization_samples, otherwise, we make sure those two numbers match. - */ - if (!cmdbuf->state.gfx.render.bound_attachments) { - assert(rasterization_samples > 0); - fbinfo->nr_samples = rasterization_samples; - } else { - assert(rasterization_samples == fbinfo->nr_samples); - } - } - /* Layered indirect draw (VK_EXT_shader_viewport_index_layer) needs * additional changes. We allow layer_count == 0 because that happens * when mixing dynamic rendering and secondary command buffers. Once @@ -2409,12 +2413,18 @@ panvk_per_arch(cmd_inherit_render_state)( cmdbuf->state.gfx.render.layer_count = inheritance_info->viewMask ? util_last_bit(inheritance_info->viewMask) : 0; + + /* If a draw was performed, the inherited sample count should match our current sample count */ + assert(fbinfo->nr_samples == 0 || inheritance_info->rasterizationSamples == fbinfo->nr_samples); *fbinfo = (struct pan_fb_info){ .tile_buf_budget = panfrost_query_optimal_tib_size(phys_dev->model), .z_tile_buf_budget = panfrost_query_optimal_z_tib_size(phys_dev->model), + .tile_size = fbinfo->tile_size, + .cbuf_allocation = fbinfo->cbuf_allocation, .nr_samples = inheritance_info->rasterizationSamples, .rt_count = inheritance_info->colorAttachmentCount, }; + cmdbuf->state.gfx.render.fb.nr_samples = inheritance_info->rasterizationSamples; assert(inheritance_info->colorAttachmentCount <= ARRAY_SIZE(fbinfo->rts)); @@ -2890,6 +2900,10 @@ panvk_per_arch(CmdEndRendering)(VkCommandBuffer commandBuffer) if (!suspending) { struct pan_fb_info *fbinfo = &cmdbuf->state.gfx.render.fb.info; + + /* If no draw was performed, we should ensure sample count is valid and that we emit tile size */ + panvk_per_arch(cmd_select_tile_size)(cmdbuf); + bool clear = fbinfo->zs.clear.z | fbinfo->zs.clear.s; for (unsigned i = 0; i < fbinfo->rt_count; i++) clear |= fbinfo->rts[i].clear; diff --git a/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c b/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c index d521f88d79a..c6338d29f2f 100644 --- a/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c +++ b/src/panfrost/vulkan/jm/panvk_vX_cmd_buffer.c @@ -137,6 +137,12 @@ panvk_per_arch(cmd_close_batch)(struct panvk_cmd_buffer *cmdbuf) GENX(pan_emit_tls)(&batch->tlsinfo, batch->tls.cpu); if (batch->fb.desc.cpu) { + panvk_per_arch(cmd_select_tile_size)(cmdbuf); + + /* At this point, we should know sample count and the tile size should have + * been calculated */ + assert(fbinfo->nr_samples > 0 && fbinfo->tile_size > 0); + fbinfo->sample_positions = dev->sample_positions->addr.dev + panfrost_sample_positions_offset( pan_sample_pattern(fbinfo->nr_samples)); diff --git a/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c index df8a52f0ed5..6db9f2381ed 100644 --- a/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/jm/panvk_vX_cmd_draw.c @@ -15,6 +15,7 @@ #include "panvk_cmd_alloc.h" #include "panvk_cmd_buffer.h" #include "panvk_cmd_desc_state.h" +#include "panvk_cmd_draw.h" #include "panvk_cmd_meta.h" #include "panvk_device.h" #include "panvk_entrypoints.h" @@ -1181,7 +1182,8 @@ panvk_cmd_draw(struct panvk_cmd_buffer *cmdbuf, struct panvk_draw_data *draw) set_provoking_vertex_mode(cmdbuf); if (!rs->rasterizer_discard_enable) { - struct pan_fb_info *fbinfo = &cmdbuf->state.gfx.render.fb.info; + const struct pan_fb_info *fbinfo = &cmdbuf->state.gfx.render.fb.info; + uint32_t *nr_samples = &cmdbuf->state.gfx.render.fb.nr_samples; uint32_t rasterization_samples = cmdbuf->vk.dynamic_graphics_state.ms.rasterization_samples; @@ -1190,16 +1192,26 @@ panvk_cmd_draw(struct panvk_cmd_buffer *cmdbuf, struct panvk_draw_data *draw) * make sure those two numbers match. */ if (!batch->fb.desc.gpu && !cmdbuf->state.gfx.render.bound_attachments) { assert(rasterization_samples > 0); - fbinfo->nr_samples = rasterization_samples; + *nr_samples = rasterization_samples; } else { - assert(rasterization_samples == fbinfo->nr_samples); + assert(rasterization_samples == *nr_samples); } + /* In case we already emitted tiler/framebuffer descriptors, we ensure + * that the sample count didn't change + * XXX: This currently can happen in case we resume a render pass with no + * attachements and without any draw as the FBD is emitted when suspending. + */ + assert(fbinfo->nr_samples == 0 || + fbinfo->nr_samples == cmdbuf->state.gfx.render.fb.nr_samples); + result = panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf); if (result != VK_SUCCESS) return; } + panvk_per_arch(cmd_select_tile_size)(cmdbuf); + result = panvk_per_arch(cmd_alloc_tls_desc)(cmdbuf, true); if (result != VK_SUCCESS) return; diff --git a/src/panfrost/vulkan/panvk_cmd_draw.h b/src/panfrost/vulkan/panvk_cmd_draw.h index b25af9145e5..6ef5ee4ead4 100644 --- a/src/panfrost/vulkan/panvk_cmd_draw.h +++ b/src/panfrost/vulkan/panvk_cmd_draw.h @@ -64,6 +64,9 @@ struct panvk_rendering_state { struct pan_fb_info info; bool crc_valid[MAX_RTS]; + /* nr_samples to be used before framebuffer / tiler descriptor are emitted */ + uint32_t nr_samples; + #if PAN_ARCH <= 7 uint32_t bo_count; struct pan_kmod_bo *bos[MAX_RTS + 2]; @@ -326,6 +329,7 @@ panvk_per_arch(cmd_preload_render_area_border)(struct panvk_cmd_buffer *cmdbuf, const VkRenderingInfo *render_info); void panvk_per_arch(cmd_resolve_attachments)(struct panvk_cmd_buffer *cmdbuf); +void panvk_per_arch(cmd_select_tile_size)(struct panvk_cmd_buffer *cmdbuf); struct panvk_draw_info { struct { diff --git a/src/panfrost/vulkan/panvk_vX_cmd_draw.c b/src/panfrost/vulkan/panvk_vX_cmd_draw.c index 125b42e2879..d2b7b1aaa59 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_draw.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_draw.c @@ -36,8 +36,9 @@ render_state_set_color_attachment(struct panvk_cmd_buffer *cmdbuf, fbinfo->rts[index].view = &iview->pview; fbinfo->rts[index].crc_valid = &state->render.fb.crc_valid[index]; - fbinfo->nr_samples = - MAX2(fbinfo->nr_samples, pan_image_view_get_nr_samples(&iview->pview)); + state->render.fb.nr_samples = + MAX2(state->render.fb.nr_samples, + pan_image_view_get_nr_samples(&iview->pview)); if (att->loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR) { enum pipe_format fmt = vk_format_to_pipe_format(iview->vk.format); @@ -89,8 +90,9 @@ render_state_set_z_attachment(struct panvk_cmd_buffer *cmdbuf, state->render.zs_pview.planes[0] = &img->planes[0]; state->render.zs_pview.planes[1] = NULL; - fbinfo->nr_samples = - MAX2(fbinfo->nr_samples, pan_image_view_get_nr_samples(&iview->pview)); + state->render.fb.nr_samples = + MAX2(state->render.fb.nr_samples, + pan_image_view_get_nr_samples(&iview->pview)); state->render.z_attachment.iview = iview; /* D24S8 is a single plane format where the depth/stencil are interleaved. @@ -157,8 +159,9 @@ render_state_set_s_attachment(struct panvk_cmd_buffer *cmdbuf, state->render.s_pview.planes[1] = NULL; } - fbinfo->nr_samples = - MAX2(fbinfo->nr_samples, pan_image_view_get_nr_samples(&iview->pview)); + state->render.fb.nr_samples = + MAX2(state->render.fb.nr_samples, + pan_image_view_get_nr_samples(&iview->pview)); state->render.s_attachment.iview = iview; /* If the depth and stencil attachments point to the same image, @@ -234,9 +237,10 @@ panvk_per_arch(cmd_init_render_state)(struct panvk_cmd_buffer *cmdbuf, *fbinfo = (struct pan_fb_info){ .tile_buf_budget = panfrost_query_optimal_tib_size(phys_dev->model), .z_tile_buf_budget = panfrost_query_optimal_z_tib_size(phys_dev->model), - .nr_samples = 1, + .nr_samples = 0, .rt_count = pRenderingInfo->colorAttachmentCount, }; + cmdbuf->state.gfx.render.fb.nr_samples = 1; assert(pRenderingInfo->colorAttachmentCount <= ARRAY_SIZE(fbinfo->rts)); @@ -295,15 +299,30 @@ panvk_per_arch(cmd_init_render_state)(struct panvk_cmd_buffer *cmdbuf, } assert(fbinfo->width && fbinfo->height); +} - GENX(pan_select_tile_size)(fbinfo); +void +panvk_per_arch(cmd_select_tile_size)(struct panvk_cmd_buffer *cmdbuf) +{ + struct pan_fb_info *fbinfo = &cmdbuf->state.gfx.render.fb.info; + + /* In case we never emitted tiler/framebuffer descriptors, we emit the + * current sample count and compute tile size */ + if (fbinfo->nr_samples == 0) { + fbinfo->nr_samples = cmdbuf->state.gfx.render.fb.nr_samples; + GENX(pan_select_tile_size)(fbinfo); #if PAN_ARCH != 6 - if (fbinfo->cbuf_allocation > fbinfo->tile_buf_budget) { - vk_perf(VK_LOG_OBJS(&cmdbuf->vk.base), - "Using too much tile-memory, disabling pipelining"); - } + if (fbinfo->cbuf_allocation > fbinfo->tile_buf_budget) { + vk_perf(VK_LOG_OBJS(&cmdbuf->vk.base), + "Using too much tile-memory, disabling pipelining"); + } #endif + } else { + /* In case we already emitted tiler/framebuffer descriptors, we ensure + * that the sample count didn't change (this should never happen) */ + assert(fbinfo->nr_samples == cmdbuf->state.gfx.render.fb.nr_samples); + } } void diff --git a/src/panfrost/vulkan/panvk_vX_cmd_meta.c b/src/panfrost/vulkan/panvk_vX_cmd_meta.c index 25bb84d707e..6e5cc6c7cfe 100644 --- a/src/panfrost/vulkan/panvk_vX_cmd_meta.c +++ b/src/panfrost/vulkan/panvk_vX_cmd_meta.c @@ -192,13 +192,12 @@ panvk_per_arch(CmdClearAttachments)(VkCommandBuffer commandBuffer, const VkClearRect *pRects) { VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); - const struct pan_fb_info *fbinfo = &cmdbuf->state.gfx.render.fb.info; struct panvk_device *dev = to_panvk_device(cmdbuf->vk.base.device); struct panvk_cmd_meta_graphics_save_ctx save = {0}; struct vk_meta_rendering_info render = { .view_mask = cmdbuf->state.gfx.render.view_mask, - .samples = fbinfo->nr_samples, - .color_attachment_count = fbinfo->rt_count, + .samples = cmdbuf->state.gfx.render.fb.nr_samples, + .color_attachment_count = cmdbuf->state.gfx.render.fb.info.rt_count, .depth_attachment_format = cmdbuf->state.gfx.render.z_attachment.fmt, .stencil_attachment_format = cmdbuf->state.gfx.render.s_attachment.fmt, };