panvk: Emit sample count and tile size when emitting framebuffer/tiler descriptors

This move the logic around tile size budget to be able to handle
rasterization_samples properly in case no render target is defined.

We now select the tile size right before emitting the tiler and framebuffer
descriptors.

This fixes "dEQP-VK.pipeline.monolithic.multisample.mixed_count.*" on
v12 when 64x64 tile size is allowed.

Signed-off-by: Mary Guillemard <mary.guillemard@collabora.com>
Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34674>
This commit is contained in:
Mary Guillemard 2025-04-23 14:15:17 +02:00 committed by Marge Bot
parent c7f2bc6bed
commit 943a59c8f9
6 changed files with 104 additions and 50 deletions

View file

@ -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;

View file

@ -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));

View file

@ -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;

View file

@ -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 {

View file

@ -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

View file

@ -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,
};