From 0799312b9975f2019f254c9803eb75c4692223f4 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 5 Mar 2021 15:14:16 +1000 Subject: lavapipe: add support for KHR_imageless_framebuffer Reviewed-By: Mike Blumenkrantz Part-of: --- docs/features.txt | 2 +- src/gallium/frontends/lavapipe/lvp_cmd_buffer.c | 14 +++++++++++ src/gallium/frontends/lavapipe/lvp_device.c | 28 +++++++++++++++++----- src/gallium/frontends/lavapipe/lvp_execute.c | 31 +++++++++++++++++-------- src/gallium/frontends/lavapipe/lvp_private.h | 2 ++ 5 files changed, 60 insertions(+), 17 deletions(-) diff --git a/docs/features.txt b/docs/features.txt index 05cdfdb1e11..1c3c7126101 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -454,7 +454,7 @@ Vulkan 1.2 -- all DONE: anv VK_KHR_draw_indirect_count DONE (anv, lvp, radv, tu) VK_KHR_driver_properties DONE (anv, lvp, radv) VK_KHR_image_format_list DONE (anv, lvp, radv, tu) - VK_KHR_imageless_framebuffer DONE (anv, radv) + VK_KHR_imageless_framebuffer DONE (anv, lvp, radv) VK_KHR_sampler_mirror_clamp_to_edge DONE (anv, lvp, radv, tu) VK_KHR_separate_depth_stencil_layouts DONE (anv, radv) VK_KHR_shader_atomic_int64 DONE (anv/gen9+, lvp, radv) diff --git a/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c b/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c index d5775c0abe7..3f29b76cfc7 100644 --- a/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c +++ b/src/gallium/frontends/lavapipe/lvp_cmd_buffer.c @@ -23,6 +23,7 @@ #include "lvp_private.h" #include "pipe/p_context.h" +#include "vk_util.h" static VkResult lvp_create_cmd_buffer( struct lvp_device * device, @@ -352,9 +353,15 @@ VKAPI_ATTR void VKAPI_CALL lvp_CmdBeginRenderPass2( LVP_FROM_HANDLE(lvp_cmd_buffer, cmd_buffer, commandBuffer); LVP_FROM_HANDLE(lvp_render_pass, pass, pRenderPassBeginInfo->renderPass); LVP_FROM_HANDLE(lvp_framebuffer, framebuffer, pRenderPassBeginInfo->framebuffer); + const struct VkRenderPassAttachmentBeginInfo *attachment_info = + vk_find_struct_const(pRenderPassBeginInfo->pNext, + RENDER_PASS_ATTACHMENT_BEGIN_INFO); struct lvp_cmd_buffer_entry *cmd; uint32_t cmd_size = pass->attachment_count * sizeof(struct lvp_attachment_state); + if (attachment_info) + cmd_size += attachment_info->attachmentCount * sizeof(struct lvp_image_view *); + cmd = cmd_buf_entry_alloc_size(cmd_buffer, cmd_size, LVP_CMD_BEGIN_RENDER_PASS); if (!cmd) return; @@ -364,6 +371,13 @@ VKAPI_ATTR void VKAPI_CALL lvp_CmdBeginRenderPass2( cmd->u.begin_render_pass.render_area = pRenderPassBeginInfo->renderArea; cmd->u.begin_render_pass.attachments = (struct lvp_attachment_state *)(cmd + 1); + cmd->u.begin_render_pass.imageless_views = NULL; + if (attachment_info) { + cmd->u.begin_render_pass.imageless_views = (struct lvp_image_view **)(cmd->u.begin_render_pass.attachments + pass->attachment_count); + for (unsigned i = 0; i < attachment_info->attachmentCount; i++) + cmd->u.begin_render_pass.imageless_views[i] = lvp_image_view_from_handle(attachment_info->pAttachments[i]); + } + state_setup_attachments(cmd->u.begin_render_pass.attachments, pass, pRenderPassBeginInfo->pClearValues); cmd_buf_queue(cmd_buffer, cmd); diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index 9ddd4ada750..49b047f7e92 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -107,6 +107,7 @@ static const struct vk_device_extension_table lvp_device_extensions_supported = .KHR_incremental_present = true, #endif .KHR_image_format_list = true, + .KHR_imageless_framebuffer = true, .KHR_maintenance1 = true, .KHR_maintenance2 = true, .KHR_maintenance3 = true, @@ -549,6 +550,12 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFeatures2( features->shaderSharedInt64Atomics = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES: { + VkPhysicalDeviceImagelessFramebufferFeatures *features = + (VkPhysicalDeviceImagelessFramebufferFeatures*)ext; + features->imagelessFramebuffer = true; + break; + } default: break; } @@ -1540,11 +1547,16 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateFramebuffer( { LVP_FROM_HANDLE(lvp_device, device, _device); struct lvp_framebuffer *framebuffer; + const VkFramebufferAttachmentsCreateInfo *imageless_create_info = + vk_find_struct_const(pCreateInfo->pNext, + FRAMEBUFFER_ATTACHMENTS_CREATE_INFO); assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO); - size_t size = sizeof(*framebuffer) + - sizeof(struct lvp_image_view *) * pCreateInfo->attachmentCount; + size_t size = sizeof(*framebuffer); + + if (!imageless_create_info) + size += sizeof(struct lvp_image_view *) * pCreateInfo->attachmentCount; framebuffer = vk_alloc2(&device->vk.alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (framebuffer == NULL) @@ -1552,15 +1564,19 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateFramebuffer( vk_object_base_init(&device->vk, &framebuffer->base, VK_OBJECT_TYPE_FRAMEBUFFER); - framebuffer->attachment_count = pCreateInfo->attachmentCount; - for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { - VkImageView _iview = pCreateInfo->pAttachments[i]; - framebuffer->attachments[i] = lvp_image_view_from_handle(_iview); + + if (!imageless_create_info) { + framebuffer->attachment_count = pCreateInfo->attachmentCount; + for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { + VkImageView _iview = pCreateInfo->pAttachments[i]; + framebuffer->attachments[i] = lvp_image_view_from_handle(_iview); + } } framebuffer->width = pCreateInfo->width; framebuffer->height = pCreateInfo->height; framebuffer->layers = pCreateInfo->layers; + framebuffer->imageless = !!imageless_create_info; *pFramebuffer = lvp_framebuffer_to_handle(framebuffer); diff --git a/src/gallium/frontends/lavapipe/lvp_execute.c b/src/gallium/frontends/lavapipe/lvp_execute.c index 874a1353c0a..77922707363 100644 --- a/src/gallium/frontends/lavapipe/lvp_execute.c +++ b/src/gallium/frontends/lavapipe/lvp_execute.c @@ -122,6 +122,7 @@ struct rendering_state { uint32_t sample_mask; unsigned min_samples; + struct lvp_image_view **imageless_views; const struct lvp_attachment_state *attachments; VkImageAspectFlags *pending_clear_aspects; uint32_t *cleared_views; @@ -1269,6 +1270,16 @@ static void clear_attachment_layers(struct rendering_state *state, state->pctx->surface_destroy(state->pctx, clear_surf); } +static struct lvp_image_view * +get_attachment(struct rendering_state *state, + unsigned idx) +{ + if (state->imageless_views) + return state->imageless_views[idx]; + else + return state->vk_framebuffer->attachments[idx]; +} + static void render_subpass_clear(struct rendering_state *state) { const struct lvp_subpass *subpass = &state->pass->subpasses[state->subpass]; @@ -1286,7 +1297,7 @@ static void render_subpass_clear(struct rendering_state *state) color_clear_val.ui[2] = value.color.uint32[2]; color_clear_val.ui[3] = value.color.uint32[3]; - struct lvp_image_view *imgv = state->vk_framebuffer->attachments[a]; + struct lvp_image_view *imgv = get_attachment(state, a); assert(imgv->surface); @@ -1313,7 +1324,7 @@ static void render_subpass_clear(struct rendering_state *state) return; struct lvp_render_pass_attachment *att = &state->pass->attachments[ds]; - struct lvp_image_view *imgv = state->vk_framebuffer->attachments[ds]; + struct lvp_image_view *imgv = get_attachment(state, ds); assert (util_format_is_depth_or_stencil(imgv->surface->format)); @@ -1411,7 +1422,7 @@ static void render_subpass_clear_fast(struct rendering_state *state) uint32_t ds = subpass->depth_stencil_attachment->attachment; struct lvp_render_pass_attachment *att = &state->pass->attachments[ds]; - struct lvp_image_view *imgv = state->vk_framebuffer->attachments[ds]; + struct lvp_image_view *imgv = get_attachment(state, ds); const struct util_format_description *desc = util_format_description(imgv->surface->format); /* also clear stencil for don't care to avoid RMW */ @@ -1450,8 +1461,8 @@ static void render_pass_resolve(struct rendering_state *state) if (dst_att.attachment == VK_ATTACHMENT_UNUSED) continue; - struct lvp_image_view *src_imgv = state->vk_framebuffer->attachments[src_att.attachment]; - struct lvp_image_view *dst_imgv = state->vk_framebuffer->attachments[dst_att.attachment]; + struct lvp_image_view *src_imgv = get_attachment(state, src_att.attachment); + struct lvp_image_view *dst_imgv = get_attachment(state, dst_att.attachment); struct pipe_blit_info info; memset(&info, 0, sizeof(info)); @@ -1485,8 +1496,7 @@ static void begin_render_subpass(struct rendering_state *state, for (unsigned i = 0; i < subpass->color_count; i++) { struct lvp_subpass_attachment *color_att = &subpass->color_attachments[i]; if (color_att->attachment != VK_ATTACHMENT_UNUSED) { - struct lvp_image_view *imgv = state->vk_framebuffer->attachments[color_att->attachment]; - + struct lvp_image_view *imgv = get_attachment(state, color_att->attachment); add_img_view_surface(state, imgv, state->pass->attachments[color_att->attachment].format, state->framebuffer.width, state->framebuffer.height); state->framebuffer.cbufs[state->framebuffer.nr_cbufs] = imgv->surface; } else @@ -1498,7 +1508,7 @@ static void begin_render_subpass(struct rendering_state *state, struct lvp_subpass_attachment *ds_att = subpass->depth_stencil_attachment; if (ds_att->attachment != VK_ATTACHMENT_UNUSED) { - struct lvp_image_view *imgv = state->vk_framebuffer->attachments[ds_att->attachment]; + struct lvp_image_view *imgv = get_attachment(state, ds_att->attachment); add_img_view_surface(state, imgv, state->pass->attachments[ds_att->attachment].format, state->framebuffer.width, state->framebuffer.height); state->framebuffer.zsbuf = imgv->surface; } @@ -1520,6 +1530,7 @@ static void handle_begin_render_pass(struct lvp_cmd_buffer_entry *cmd, state->attachments = cmd->u.begin_render_pass.attachments; + state->imageless_views = cmd->u.begin_render_pass.imageless_views; state->framebuffer.width = state->vk_framebuffer->width; state->framebuffer.height = state->vk_framebuffer->height; state->framebuffer.layers = state->vk_framebuffer->layers; @@ -2522,12 +2533,12 @@ static void handle_clear_attachments(struct lvp_cmd_buffer_entry *cmd, struct lvp_subpass_attachment *color_att = &subpass->color_attachments[att->colorAttachment]; if (!color_att || color_att->attachment == VK_ATTACHMENT_UNUSED) continue; - imgv = state->vk_framebuffer->attachments[color_att->attachment]; + imgv = get_attachment(state, color_att->attachment); } else { struct lvp_subpass_attachment *ds_att = subpass->depth_stencil_attachment; if (!ds_att || ds_att->attachment == VK_ATTACHMENT_UNUSED) continue; - imgv = state->vk_framebuffer->attachments[ds_att->attachment]; + imgv = get_attachment(state, ds_att->attachment); } union pipe_color_union col_val; double dclear_val = 0; diff --git a/src/gallium/frontends/lavapipe/lvp_private.h b/src/gallium/frontends/lavapipe/lvp_private.h index 1b9aca1d03f..3733f6974c7 100644 --- a/src/gallium/frontends/lavapipe/lvp_private.h +++ b/src/gallium/frontends/lavapipe/lvp_private.h @@ -317,6 +317,7 @@ struct lvp_framebuffer { uint32_t height; uint32_t layers; + bool imageless; uint32_t attachment_count; struct lvp_image_view * attachments[0]; }; @@ -925,6 +926,7 @@ struct lvp_cmd_begin_render_pass { struct lvp_render_pass *render_pass; VkRect2D render_area; struct lvp_attachment_state *attachments; + struct lvp_image_view **imageless_views; }; struct lvp_cmd_next_subpass { -- cgit v1.2.3