Mesa (main): lavapipe: VK_EXT_multisampled_render_to_single_sampled
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Jul 26 00:44:18 UTC 2022
Module: Mesa
Branch: main
Commit: f2d5ff1c3a89c2ded0fcffc014d4c579f72b945a
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=f2d5ff1c3a89c2ded0fcffc014d4c579f72b945a
Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date: Fri Jul 22 01:04:41 2022 -0400
lavapipe: VK_EXT_multisampled_render_to_single_sampled
this works by doing a replicate at renderpass start and an in-place
resolve on renderpass end
Reviewed-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17705>
---
src/gallium/frontends/lavapipe/lvp_execute.c | 152 ++++++++++++++++++++++++---
src/gallium/frontends/lavapipe/lvp_formats.c | 3 +
src/gallium/frontends/lavapipe/lvp_private.h | 1 +
3 files changed, 141 insertions(+), 15 deletions(-)
diff --git a/src/gallium/frontends/lavapipe/lvp_execute.c b/src/gallium/frontends/lavapipe/lvp_execute.c
index 5de46236e1a..aff07c86f08 100644
--- a/src/gallium/frontends/lavapipe/lvp_execute.c
+++ b/src/gallium/frontends/lavapipe/lvp_execute.c
@@ -39,6 +39,7 @@
#include "util/u_sampler.h"
#include "util/u_box.h"
#include "util/u_inlines.h"
+#include "util/u_memory.h"
#include "util/u_prim.h"
#include "util/u_prim_restart.h"
#include "util/format/u_format_zs.h"
@@ -171,6 +172,9 @@ struct rendering_state {
struct lvp_render_attachment stencil_att;
struct lvp_image_view *ds_imgv;
struct lvp_image_view *ds_resolve_imgv;
+ uint32_t forced_sample_count;
+ VkResolveModeFlagBits forced_depth_resolve_mode;
+ VkResolveModeFlagBits forced_stencil_resolve_mode;
uint32_t sample_mask;
unsigned min_samples;
@@ -1861,30 +1865,50 @@ slow_clear:
render_clear(state);
}
+static struct lvp_image_view *
+destroy_multisample_surface(struct rendering_state *state, struct lvp_image_view *imgv)
+{
+ assert(imgv->image->vk.samples > 1);
+ struct lvp_image_view *base = imgv->multisample;
+ base->multisample = NULL;
+ free((void*)imgv->image);
+ pipe_surface_reference(&imgv->surface, NULL);
+ free(imgv);
+ return base;
+}
+
static void
-resolve_ds(struct rendering_state *state)
+resolve_ds(struct rendering_state *state, bool multi)
{
- if (!state->depth_att.resolve_mode && !state->stencil_att.resolve_mode)
+ VkResolveModeFlagBits depth_resolve_mode = multi ? state->forced_depth_resolve_mode : state->depth_att.resolve_mode;
+ VkResolveModeFlagBits stencil_resolve_mode = multi ? state->forced_stencil_resolve_mode : state->stencil_att.resolve_mode;
+ if (!depth_resolve_mode && !stencil_resolve_mode)
return;
struct lvp_image_view *src_imgv = state->ds_imgv;
+ if (multi && !src_imgv->multisample)
+ return;
+ if (!multi && src_imgv->image->vk.samples == 1)
+ return;
assert(state->depth_att.resolve_imgv == NULL ||
state->stencil_att.resolve_imgv == NULL ||
- state->depth_att.resolve_imgv == state->stencil_att.resolve_imgv);
+ state->depth_att.resolve_imgv == state->stencil_att.resolve_imgv ||
+ multi);
struct lvp_image_view *dst_imgv =
+ multi ? src_imgv->multisample :
state->depth_att.resolve_imgv ? state->depth_att.resolve_imgv :
state->stencil_att.resolve_imgv;
int num_blits = 1;
- if (state->depth_att.resolve_mode != state->stencil_att.resolve_mode)
+ if (depth_resolve_mode != stencil_resolve_mode)
num_blits = 2;
for (unsigned i = 0; i < num_blits; i++) {
- if (i == 0 && state->depth_att.resolve_mode == VK_RESOLVE_MODE_NONE)
+ if (i == 0 && depth_resolve_mode == VK_RESOLVE_MODE_NONE)
continue;
- if (i == 1 && state->stencil_att.resolve_mode == VK_RESOLVE_MODE_NONE)
+ if (i == 1 && stencil_resolve_mode == VK_RESOLVE_MODE_NONE)
continue;
struct pipe_blit_info info;
@@ -1903,9 +1927,9 @@ resolve_ds(struct rendering_state *state)
else
info.mask = PIPE_MASK_S;
- if (i == 0 && state->depth_att.resolve_mode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
+ if (i == 0 && depth_resolve_mode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
info.sample0_only = true;
- if (i == 1 && state->stencil_att.resolve_mode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
+ if (i == 1 && stencil_resolve_mode == VK_RESOLVE_MODE_SAMPLE_ZERO_BIT)
info.sample0_only = true;
info.src.box.x = state->render_area.offset.x;
@@ -1918,17 +1942,23 @@ resolve_ds(struct rendering_state *state)
state->pctx->blit(state->pctx, &info);
}
+ if (multi)
+ state->ds_imgv = destroy_multisample_surface(state, state->ds_imgv);
}
static void
-resolve_color(struct rendering_state *state)
+resolve_color(struct rendering_state *state, bool multi)
{
for (uint32_t i = 0; i < state->color_att_count; i++) {
- if (!state->color_att[i].resolve_mode)
+ if (!state->color_att[i].resolve_mode &&
+ !(multi && state->forced_sample_count && state->color_att[i].imgv))
continue;
struct lvp_image_view *src_imgv = state->color_att[i].imgv;
- struct lvp_image_view *dst_imgv = state->color_att[i].resolve_imgv;
+ /* skip non-msrtss resolves during msrtss resolve */
+ if (multi && !src_imgv->multisample)
+ continue;
+ struct lvp_image_view *dst_imgv = multi ? src_imgv->multisample : state->color_att[i].resolve_imgv;
struct pipe_blit_info info;
memset(&info, 0, sizeof(info));
@@ -1952,12 +1982,74 @@ resolve_color(struct rendering_state *state)
state->pctx->blit(state->pctx, &info);
}
+
+ if (!multi)
+ return;
+ for (uint32_t i = 0; i < state->color_att_count; i++) {
+ struct lvp_image_view *src_imgv = state->color_att[i].imgv;
+ if (src_imgv && src_imgv->multisample) //check if it has a msrtss view
+ state->color_att[i].imgv = destroy_multisample_surface(state, src_imgv);
+ }
}
static void render_resolve(struct rendering_state *state)
{
- resolve_ds(state);
- resolve_color(state);
+ if (state->forced_sample_count) {
+ resolve_ds(state, true);
+ resolve_color(state, true);
+ }
+ resolve_ds(state, false);
+ resolve_color(state, false);
+}
+
+static void
+replicate_attachment(struct rendering_state *state, struct lvp_image_view *src, struct lvp_image_view *dst)
+{
+ unsigned level = dst->surface->u.tex.level;
+ struct pipe_box box;
+ u_box_3d(0, 0, 0,
+ u_minify(dst->image->bo->width0, level),
+ u_minify(dst->image->bo->height0, level),
+ u_minify(dst->image->bo->depth0, level),
+ &box);
+ state->pctx->resource_copy_region(state->pctx, dst->image->bo, level, 0, 0, 0, src->image->bo, level, &box);
+}
+
+static struct lvp_image_view *
+create_multisample_surface(struct rendering_state *state, struct lvp_image_view *imgv, uint32_t samples, bool replicate)
+{
+ assert(!imgv->multisample);
+
+ struct pipe_resource templ = *imgv->surface->texture;
+ templ.nr_samples = samples;
+ struct lvp_image *image = mem_dup(imgv->image, sizeof(struct lvp_image));
+ image->vk.samples = samples;
+ image->pmem = NULL;
+ image->bo = state->pctx->screen->resource_create(state->pctx->screen, &templ);
+
+ struct lvp_image_view *multi = mem_dup(imgv, sizeof(struct lvp_image_view));
+ multi->image = image;
+ multi->surface = state->pctx->create_surface(state->pctx, image->bo, imgv->surface);
+ struct pipe_resource *ref = image->bo;
+ pipe_resource_reference(&ref, NULL);
+ imgv->multisample = multi;
+ multi->multisample = imgv;
+ if (replicate)
+ replicate_attachment(state, imgv, multi);
+ return multi;
+}
+
+static bool
+att_needs_replicate(const struct rendering_state *state, const struct lvp_image_view *imgv, VkAttachmentLoadOp load_op)
+{
+ if (load_op == VK_ATTACHMENT_LOAD_OP_LOAD || load_op == VK_ATTACHMENT_LOAD_OP_CLEAR)
+ return true;
+ if (state->render_area.offset.x || state->render_area.offset.y)
+ return true;
+ if (state->render_area.extent.width < imgv->image->vk.extent.width ||
+ state->render_area.extent.height < imgv->image->vk.extent.height)
+ return true;
+ return false;
}
static void render_att_init(struct lvp_render_attachment* att,
@@ -1989,6 +2081,18 @@ static void handle_begin_rendering(struct vk_cmd_queue_entry *cmd,
bool resuming = (info->flags & VK_RENDERING_RESUMING_BIT) == VK_RENDERING_RESUMING_BIT;
bool suspending = (info->flags & VK_RENDERING_SUSPENDING_BIT) == VK_RENDERING_SUSPENDING_BIT;
+ const VkMultisampledRenderToSingleSampledInfoEXT *ssi =
+ vk_find_struct_const(info->pNext, MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT);
+ if (ssi && ssi->multisampledRenderToSingleSampledEnable) {
+ state->forced_sample_count = ssi->rasterizationSamples;
+ state->forced_depth_resolve_mode = info->pDepthAttachment ? info->pDepthAttachment->resolveMode : 0;
+ state->forced_stencil_resolve_mode = info->pStencilAttachment ? info->pStencilAttachment->resolveMode : 0;
+ } else {
+ state->forced_sample_count = 0;
+ state->forced_depth_resolve_mode = 0;
+ state->forced_stencil_resolve_mode = 0;
+ }
+
state->info.view_mask = info->viewMask;
state->render_area = info->renderArea;
state->suspending = suspending;
@@ -2004,8 +2108,12 @@ static void handle_begin_rendering(struct vk_cmd_queue_entry *cmd,
for (unsigned i = 0; i < info->colorAttachmentCount; i++) {
render_att_init(&state->color_att[i], &info->pColorAttachments[i]);
if (state->color_att[i].imgv) {
- add_img_view_surface(state, state->color_att[i].imgv,
+ struct lvp_image_view *imgv = state->color_att[i].imgv;
+ add_img_view_surface(state, imgv,
state->framebuffer.width, state->framebuffer.height);
+ if (state->forced_sample_count && imgv->image->vk.samples == 1)
+ state->color_att[i].imgv = create_multisample_surface(state, imgv, state->forced_sample_count,
+ att_needs_replicate(state, imgv, state->color_att[i].load_op));
state->framebuffer.cbufs[i] = state->color_att[i].imgv->surface;
} else {
state->framebuffer.cbufs[i] = NULL;
@@ -2020,8 +2128,22 @@ static void handle_begin_rendering(struct vk_cmd_queue_entry *cmd,
state->depth_att.imgv == state->stencil_att.imgv);
state->ds_imgv = state->depth_att.imgv ? state->depth_att.imgv :
state->stencil_att.imgv;
- add_img_view_surface(state, state->ds_imgv,
+ struct lvp_image_view *imgv = state->ds_imgv;
+ add_img_view_surface(state, imgv,
state->framebuffer.width, state->framebuffer.height);
+ if (state->forced_sample_count && imgv->image->vk.samples == 1) {
+ VkAttachmentLoadOp load_op;
+ if (state->depth_att.load_op == VK_ATTACHMENT_LOAD_OP_CLEAR ||
+ state->stencil_att.load_op == VK_ATTACHMENT_LOAD_OP_CLEAR)
+ load_op = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ else if (state->depth_att.load_op == VK_ATTACHMENT_LOAD_OP_LOAD ||
+ state->stencil_att.load_op == VK_ATTACHMENT_LOAD_OP_LOAD)
+ load_op = VK_ATTACHMENT_LOAD_OP_LOAD;
+ else
+ load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ state->ds_imgv = create_multisample_surface(state, imgv, state->forced_sample_count,
+ att_needs_replicate(state, imgv, load_op));
+ }
state->framebuffer.zsbuf = state->ds_imgv->surface;
} else {
state->ds_imgv = NULL;
diff --git a/src/gallium/frontends/lavapipe/lvp_formats.c b/src/gallium/frontends/lavapipe/lvp_formats.c
index 475a3f22870..ed040107377 100644
--- a/src/gallium/frontends/lavapipe/lvp_formats.c
+++ b/src/gallium/frontends/lavapipe/lvp_formats.c
@@ -192,6 +192,9 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFormatProperties2(
prop3->optimalTilingFeatures = format_props.optimalTilingFeatures;
prop3->bufferFeatures = format_props.bufferFeatures;
}
+ VkSubpassResolvePerformanceQueryEXT *perf = (void*)vk_find_struct_const(pFormatProperties->pNext, SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT);
+ if (perf)
+ perf->optimal = VK_FALSE;
}
static VkResult lvp_get_image_format_properties(struct lvp_physical_device *physical_device,
const VkPhysicalDeviceImageFormatInfo2 *info,
diff --git a/src/gallium/frontends/lavapipe/lvp_private.h b/src/gallium/frontends/lavapipe/lvp_private.h
index ed6b1636ddd..24f6df0ff48 100644
--- a/src/gallium/frontends/lavapipe/lvp_private.h
+++ b/src/gallium/frontends/lavapipe/lvp_private.h
@@ -255,6 +255,7 @@ struct lvp_image_view {
enum pipe_format pformat;
struct pipe_surface *surface; /* have we created a pipe surface for this? */
+ struct lvp_image_view *multisample; //VK_EXT_multisampled_render_to_single_sampled
};
struct lvp_sampler {
More information about the mesa-commit
mailing list