diff --git a/docs/features.txt b/docs/features.txt index aa226428bb2..469bba9dc31 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -452,7 +452,7 @@ Vulkan 1.2 -- all DONE: anv, vn VK_KHR_draw_indirect_count DONE (anv, lvp, radv, tu, vn) VK_KHR_driver_properties DONE (anv, lvp, radv, v3dv, vn) VK_KHR_image_format_list DONE (anv, lvp, radv, tu, v3dv, vn) - VK_KHR_imageless_framebuffer DONE (anv, lvp, radv, tu, vn) + VK_KHR_imageless_framebuffer DONE (anv, lvp, radv, tu, v3dv, vn) VK_KHR_sampler_mirror_clamp_to_edge DONE (anv, lvp, radv, tu, v3dv, vn) VK_KHR_separate_depth_stencil_layouts DONE (anv, lvp, radv, vn, tu) VK_KHR_shader_atomic_int64 DONE (anv/gen9+, lvp, radv, vn) diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index fa6b85b244a..2c18fe2ac9c 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -941,8 +941,6 @@ cmd_buffer_subpass_handle_pending_resolves(struct v3dv_cmd_buffer *cmd_buffer) if (!subpass->resolve_attachments) return; - struct v3dv_framebuffer *fb = cmd_buffer->state.framebuffer; - /* At this point we have already ended the current subpass and now we are * about to emit vkCmdResolveImage calls to get the resolves we can't handle * handle in the subpass RCL. @@ -977,8 +975,10 @@ cmd_buffer_subpass_handle_pending_resolves(struct v3dv_cmd_buffer *cmd_buffer) if (dst_attachment_idx == VK_ATTACHMENT_UNUSED) continue; - struct v3dv_image_view *src_iview = fb->attachments[src_attachment_idx]; - struct v3dv_image_view *dst_iview = fb->attachments[dst_attachment_idx]; + struct v3dv_image_view *src_iview = + cmd_buffer->state.attachments[src_attachment_idx].image_view; + struct v3dv_image_view *dst_iview = + cmd_buffer->state.attachments[dst_attachment_idx].image_view; VkImageResolve2KHR region = { .sType = VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR, @@ -1241,6 +1241,31 @@ cmd_buffer_state_set_clear_values(struct v3dv_cmd_buffer *cmd_buffer, } } +static void +cmd_buffer_state_set_attachments(struct v3dv_cmd_buffer *cmd_buffer, + const VkRenderPassBeginInfo *pRenderPassBegin) +{ + V3DV_FROM_HANDLE(v3dv_render_pass, pass, pRenderPassBegin->renderPass); + V3DV_FROM_HANDLE(v3dv_framebuffer, framebuffer, pRenderPassBegin->framebuffer); + + const VkRenderPassAttachmentBeginInfoKHR *attach_begin = + vk_find_struct_const(pRenderPassBegin, RENDER_PASS_ATTACHMENT_BEGIN_INFO_KHR); + + struct v3dv_cmd_buffer_state *state = &cmd_buffer->state; + + for (uint32_t i = 0; i < pass->attachment_count; i++) { + if (attach_begin && attach_begin->attachmentCount != 0) { + state->attachments[i].image_view = + v3dv_image_view_from_handle(attach_begin->pAttachments[i]); + } else if (framebuffer) { + state->attachments[i].image_view = framebuffer->attachments[i]; + } else { + assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY); + state->attachments[i].image_view = NULL; + } + } +} + static void cmd_buffer_init_render_pass_attachment_state(struct v3dv_cmd_buffer *cmd_buffer, const VkRenderPassBeginInfo *pRenderPassBegin) @@ -1248,6 +1273,8 @@ cmd_buffer_init_render_pass_attachment_state(struct v3dv_cmd_buffer *cmd_buffer, cmd_buffer_state_set_clear_values(cmd_buffer, pRenderPassBegin->clearValueCount, pRenderPassBegin->pClearValues); + + cmd_buffer_state_set_attachments(cmd_buffer, pRenderPassBegin); } static void @@ -1476,7 +1503,7 @@ cmd_buffer_subpass_create_job(struct v3dv_cmd_buffer *cmd_buffer, uint8_t internal_bpp; bool msaa; v3dv_X(job->device, framebuffer_compute_internal_bpp_msaa) - (framebuffer, subpass, &internal_bpp, &msaa); + (framebuffer, state->attachments, subpass, &internal_bpp, &msaa); /* From the Vulkan spec: * diff --git a/src/broadcom/vulkan/v3dv_device.c b/src/broadcom/vulkan/v3dv_device.c index 00bcbf4d3bf..9444dac0f9c 100644 --- a/src/broadcom/vulkan/v3dv_device.c +++ b/src/broadcom/vulkan/v3dv_device.c @@ -133,6 +133,7 @@ get_device_extensions(const struct v3dv_physical_device *device, .KHR_external_semaphore_fd = true, .KHR_get_memory_requirements2 = true, .KHR_image_format_list = true, + .KHR_imageless_framebuffer = true, .KHR_relaxed_block_layout = true, .KHR_maintenance1 = true, .KHR_maintenance2 = true, @@ -1123,6 +1124,13 @@ v3dv_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES_KHR: { + VkPhysicalDeviceImagelessFramebufferFeatures *features = + (VkPhysicalDeviceImagelessFramebufferFeatures *)ext; + features->imagelessFramebuffer = true; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR: { VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR *features = (VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR *)ext; @@ -2503,13 +2511,25 @@ v3dv_CreateFramebuffer(VkDevice _device, framebuffer->layers = pCreateInfo->layers; framebuffer->has_edge_padding = true; + const VkFramebufferAttachmentsCreateInfo *imageless = + vk_find_struct_const(pCreateInfo->pNext, + FRAMEBUFFER_ATTACHMENTS_CREATE_INFO); + framebuffer->attachment_count = pCreateInfo->attachmentCount; framebuffer->color_attachment_count = 0; - for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { - framebuffer->attachments[i] = - v3dv_image_view_from_handle(pCreateInfo->pAttachments[i]); - if (framebuffer->attachments[i]->vk.aspects & VK_IMAGE_ASPECT_COLOR_BIT) - framebuffer->color_attachment_count++; + for (uint32_t i = 0; i < framebuffer->attachment_count; i++) { + if (!imageless) { + framebuffer->attachments[i] = + v3dv_image_view_from_handle(pCreateInfo->pAttachments[i]); + if (framebuffer->attachments[i]->vk.aspects & VK_IMAGE_ASPECT_COLOR_BIT) + framebuffer->color_attachment_count++; + } else { + assert(i < imageless->attachmentImageInfoCount); + if (imageless->pAttachmentImageInfos[i].usage & + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { + framebuffer->color_attachment_count++; + } + } } *pFramebuffer = v3dv_framebuffer_to_handle(framebuffer); diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index 06cc9bb716f..ad3d466b7b6 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -765,6 +765,11 @@ struct v3dv_framebuffer { uint32_t attachment_count; uint32_t color_attachment_count; + + /* Notice that elements in 'attachments' will be NULL if the framebuffer + * was created imageless. The driver is expected to access attachment info + * from the command buffer state instead. + */ struct v3dv_image_view *attachments[0]; }; @@ -835,6 +840,11 @@ struct v3dv_cmd_buffer_attachment_state { /* The hardware clear value */ union v3dv_clear_value clear_value; + + /* The underlying image view (from the framebuffer or, if imageless + * framebuffer is used, from VkRenderPassAttachmentBeginInfo. + */ + struct v3dv_image_view *image_view; }; struct v3dv_viewport_state { diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c b/src/broadcom/vulkan/v3dvx_cmd_buffer.c index 12e7385fdf3..a1a36cf9349 100644 --- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c @@ -200,7 +200,6 @@ cmd_buffer_render_pass_emit_loads(struct v3dv_cmd_buffer *cmd_buffer, uint32_t layer) { const struct v3dv_cmd_buffer_state *state = &cmd_buffer->state; - const struct v3dv_framebuffer *framebuffer = state->framebuffer; const struct v3dv_render_pass *pass = state->pass; const struct v3dv_subpass *subpass = &pass->subpasses[state->subpass_idx]; @@ -242,7 +241,8 @@ cmd_buffer_render_pass_emit_loads(struct v3dv_cmd_buffer *cmd_buffer, first_subpass, attachment->desc.loadOp); if (needs_load) { - struct v3dv_image_view *iview = framebuffer->attachments[attachment_idx]; + struct v3dv_image_view *iview = + state->attachments[attachment_idx].image_view; cmd_buffer_render_pass_emit_load(cmd_buffer, cl, iview, layer, RENDER_TARGET_0 + i); } @@ -274,7 +274,7 @@ cmd_buffer_render_pass_emit_loads(struct v3dv_cmd_buffer *cmd_buffer, if (needs_depth_load || needs_stencil_load) { struct v3dv_image_view *iview = - framebuffer->attachments[ds_attachment_idx]; + state->attachments[ds_attachment_idx].image_view; /* From the Vulkan spec: * * "When an image view of a depth/stencil image is used as a @@ -305,7 +305,7 @@ cmd_buffer_render_pass_emit_store(struct v3dv_cmd_buffer *cmd_buffer, bool is_multisample_resolve) { const struct v3dv_image_view *iview = - cmd_buffer->state.framebuffer->attachments[attachment_idx]; + cmd_buffer->state.attachments[attachment_idx].image_view; const struct v3dv_image *image = (struct v3dv_image *) iview->vk.image; const struct v3d_resource_slice *slice = &image->slices[iview->vk.base_mip_level]; @@ -803,7 +803,7 @@ v3dX(cmd_buffer_emit_render_pass_rcl)(struct v3dv_cmd_buffer *cmd_buffer) if (ds_attachment_idx != VK_ATTACHMENT_UNUSED) { const struct v3dv_image_view *iview = - framebuffer->attachments[ds_attachment_idx]; + state->attachments[ds_attachment_idx].image_view; config.internal_depth_type = iview->internal_type; set_rcl_early_z_config(job, @@ -875,7 +875,7 @@ v3dX(cmd_buffer_emit_render_pass_rcl)(struct v3dv_cmd_buffer *cmd_buffer) continue; struct v3dv_image_view *iview = - state->framebuffer->attachments[attachment_idx]; + state->attachments[attachment_idx].image_view; const struct v3dv_image *image = (struct v3dv_image *) iview->vk.image; const struct v3d_resource_slice *slice = @@ -2292,9 +2292,9 @@ v3dX(cmd_buffer_render_pass_setup_render_target)(struct v3dv_cmd_buffer *cmd_buf if (attachment_idx == VK_ATTACHMENT_UNUSED) return; - const struct v3dv_framebuffer *framebuffer = state->framebuffer; - assert(attachment_idx < framebuffer->attachment_count); - struct v3dv_image_view *iview = framebuffer->attachments[attachment_idx]; + assert(attachment_idx < state->framebuffer->attachment_count && + attachment_idx < state->attachment_alloc_count); + struct v3dv_image_view *iview = state->attachments[attachment_idx].image_view; assert(iview->vk.aspects & VK_IMAGE_ASPECT_COLOR_BIT); *rt_bpp = iview->internal_bpp; diff --git a/src/broadcom/vulkan/v3dvx_device.c b/src/broadcom/vulkan/v3dvx_device.c index 0bea6211d76..25517bedeea 100644 --- a/src/broadcom/vulkan/v3dvx_device.c +++ b/src/broadcom/vulkan/v3dvx_device.c @@ -257,6 +257,7 @@ v3dX(pack_sampler_state)(struct v3dv_sampler *sampler, void v3dX(framebuffer_compute_internal_bpp_msaa)( const struct v3dv_framebuffer *framebuffer, + const struct v3dv_cmd_buffer_attachment_state *attachments, const struct v3dv_subpass *subpass, uint8_t *max_bpp, bool *msaa) @@ -271,7 +272,7 @@ v3dX(framebuffer_compute_internal_bpp_msaa)( if (att_idx == VK_ATTACHMENT_UNUSED) continue; - const struct v3dv_image_view *att = framebuffer->attachments[att_idx]; + const struct v3dv_image_view *att = attachments[att_idx].image_view; assert(att); if (att->vk.aspects & VK_IMAGE_ASPECT_COLOR_BIT) @@ -283,7 +284,7 @@ v3dX(framebuffer_compute_internal_bpp_msaa)( if (!*msaa && subpass->ds_attachment.attachment != VK_ATTACHMENT_UNUSED) { const struct v3dv_image_view *att = - framebuffer->attachments[subpass->ds_attachment.attachment]; + attachments[subpass->ds_attachment.attachment].image_view; assert(att); if (att->vk.image->samples > VK_SAMPLE_COUNT_1_BIT) @@ -295,7 +296,7 @@ v3dX(framebuffer_compute_internal_bpp_msaa)( assert(framebuffer->attachment_count <= 4); for (uint32_t i = 0; i < framebuffer->attachment_count; i++) { - const struct v3dv_image_view *att = framebuffer->attachments[i]; + const struct v3dv_image_view *att = attachments[i].image_view; assert(att); if (att->vk.aspects & VK_IMAGE_ASPECT_COLOR_BIT) diff --git a/src/broadcom/vulkan/v3dvx_private.h b/src/broadcom/vulkan/v3dvx_private.h index 86add82c062..d2135fea2ca 100644 --- a/src/broadcom/vulkan/v3dvx_private.h +++ b/src/broadcom/vulkan/v3dvx_private.h @@ -138,6 +138,7 @@ v3dX(pack_sampler_state)(struct v3dv_sampler *sampler, void v3dX(framebuffer_compute_internal_bpp_msaa)(const struct v3dv_framebuffer *framebuffer, + const struct v3dv_cmd_buffer_attachment_state *attachments, const struct v3dv_subpass *subpass, uint8_t *max_bpp, bool *msaa);