From ed125e6cca188275631641784fcf3ddcbcfef193 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Tue, 28 Jun 2022 10:33:01 +0200 Subject: [PATCH] tu: Initial support for dynamic rendering Support for suspend/resume will be added later. This just sets up the internal render pass, and adds support to pipeline creation and secondary inheritance. Part-of: --- src/freedreno/vulkan/tu_cmd_buffer.c | 147 +++++++++++++-- src/freedreno/vulkan/tu_device.c | 17 ++ src/freedreno/vulkan/tu_image.c | 1 + src/freedreno/vulkan/tu_pass.c | 259 ++++++++++++++++++++++++--- src/freedreno/vulkan/tu_pipeline.c | 109 +++++++---- src/freedreno/vulkan/tu_private.h | 20 +++ 6 files changed, 477 insertions(+), 76 deletions(-) diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c index c246d90293b..cd43c8fb53d 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.c +++ b/src/freedreno/vulkan/tu_cmd_buffer.c @@ -269,8 +269,22 @@ tu6_emit_mrt(struct tu_cmd_buffer *cmd, for (uint32_t i = 0; i < subpass->color_count; ++i) { uint32_t a = subpass->color_attachments[i].attachment; - if (a == VK_ATTACHMENT_UNUSED) + if (a == VK_ATTACHMENT_UNUSED) { + /* From the VkPipelineRenderingCreateInfo definition: + * + * Valid formats indicate that an attachment can be used - but it + * is still valid to set the attachment to NULL when beginning + * rendering. + * + * This means that with dynamic rendering, pipelines may write to + * some attachments that are UNUSED here. Setting the format to 0 + * here should prevent them from writing to anything. + */ + tu_cs_emit_pkt4(cs, REG_A6XX_RB_MRT_BUF_INFO(i), 6); + for (unsigned i = 0; i < 6; i++) + tu_cs_emit(cs, 0); continue; + } const struct tu_image_view *iview = cmd->state.attachments[a]; @@ -1770,10 +1784,18 @@ tu_BeginCommandBuffer(VkCommandBuffer commandBuffer, } if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) { - cmd_buffer->state.pass = tu_render_pass_from_handle(pBeginInfo->pInheritanceInfo->renderPass); - cmd_buffer->state.subpass = - &cmd_buffer->state.pass->subpasses[pBeginInfo->pInheritanceInfo->subpass]; - + if (pBeginInfo->pInheritanceInfo->renderPass) { + cmd_buffer->state.pass = tu_render_pass_from_handle(pBeginInfo->pInheritanceInfo->renderPass); + cmd_buffer->state.subpass = + &cmd_buffer->state.pass->subpasses[pBeginInfo->pInheritanceInfo->subpass]; + } else { + const VkCommandBufferInheritanceRenderingInfo *rendering_info = + vk_find_struct_const(pBeginInfo->pInheritanceInfo->pNext, + COMMAND_BUFFER_INHERITANCE_RENDERING_INFO); + tu_setup_dynamic_inheritance(cmd_buffer, rendering_info); + cmd_buffer->state.pass = &cmd_buffer->dynamic_pass; + cmd_buffer->state.subpass = &cmd_buffer->dynamic_subpass; + } tu_lrz_begin_secondary_cmdbuf(cmd_buffer); } else { /* When executing in the middle of another command buffer, the CCU @@ -3590,6 +3612,85 @@ tu_CmdBeginRenderPass2(VkCommandBuffer commandBuffer, tu_emit_subpass_begin(cmd); } +VKAPI_ATTR void VKAPI_CALL +tu_CmdBeginRendering(VkCommandBuffer commandBuffer, + const VkRenderingInfo *pRenderingInfo) +{ + TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer); + VkClearValue clear_values[2 * (MAX_RTS + 1)]; + + tu_setup_dynamic_render_pass(cmd, pRenderingInfo); + tu_setup_dynamic_framebuffer(cmd, pRenderingInfo); + + cmd->state.pass = &cmd->dynamic_pass; + cmd->state.subpass = &cmd->dynamic_subpass; + cmd->state.framebuffer = &cmd->dynamic_framebuffer; + cmd->state.render_area = pRenderingInfo->renderArea; + + cmd->state.attachments = cmd->dynamic_attachments; + + cmd->state.draw_cs_writes_to_cond_pred = false; + + for (unsigned i = 0; i < pRenderingInfo->colorAttachmentCount; i++) { + uint32_t a = cmd->dynamic_subpass.color_attachments[i].attachment; + if (!pRenderingInfo->pColorAttachments[i].imageView) + continue; + + TU_FROM_HANDLE(tu_image_view, view, + pRenderingInfo->pColorAttachments[i].imageView); + cmd->state.attachments[a] = view; + clear_values[a] = pRenderingInfo->pColorAttachments[i].clearValue; + + a = cmd->dynamic_subpass.resolve_attachments[i].attachment; + if (a != VK_ATTACHMENT_UNUSED) { + TU_FROM_HANDLE(tu_image_view, resolve_view, + pRenderingInfo->pColorAttachments[i].resolveImageView); + cmd->state.attachments[a] = resolve_view; + } + } + + uint32_t a = cmd->dynamic_subpass.depth_stencil_attachment.attachment; + if (pRenderingInfo->pDepthAttachment || pRenderingInfo->pStencilAttachment) { + const struct VkRenderingAttachmentInfo *common_info = + (pRenderingInfo->pDepthAttachment && + pRenderingInfo->pDepthAttachment->imageView != VK_NULL_HANDLE) ? + pRenderingInfo->pDepthAttachment : + pRenderingInfo->pStencilAttachment; + if (common_info && common_info->imageView != VK_NULL_HANDLE) { + TU_FROM_HANDLE(tu_image_view, view, common_info->imageView); + cmd->state.attachments[a] = view; + if (pRenderingInfo->pDepthAttachment) { + clear_values[a].depthStencil.depth = + pRenderingInfo->pDepthAttachment->clearValue.depthStencil.depth; + } + + if (pRenderingInfo->pStencilAttachment) { + clear_values[a].depthStencil.stencil = + pRenderingInfo->pStencilAttachment->clearValue.depthStencil.stencil; + } + + if (cmd->dynamic_subpass.resolve_count > + cmd->dynamic_subpass.color_count) { + TU_FROM_HANDLE(tu_image_view, resolve_view, + common_info->resolveImageView); + a = cmd->dynamic_subpass.resolve_attachments[cmd->dynamic_subpass.color_count].attachment; + cmd->state.attachments[a] = resolve_view; + } + } + } + + cmd->state.renderpass_cache.pending_flush_bits = + cmd->state.cache.pending_flush_bits; + cmd->state.renderpass_cache.flush_bits = 0; + + trace_start_render_pass(&cmd->trace, &cmd->cs); + + cmd->trace_renderpass_start = u_trace_end_iterator(&cmd->trace); + + tu_emit_renderpass_begin(cmd, clear_values); + tu_emit_subpass_begin(cmd); +} + VKAPI_ATTR void VKAPI_CALL tu_CmdNextSubpass2(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo *pSubpassBeginInfo, @@ -4698,12 +4799,9 @@ tu_CmdDispatchIndirect(VkCommandBuffer commandBuffer, tu_dispatch(cmd_buffer, &info); } -VKAPI_ATTR void VKAPI_CALL -tu_CmdEndRenderPass2(VkCommandBuffer commandBuffer, - const VkSubpassEndInfo *pSubpassEndInfo) +static void +tu_end_rendering(struct tu_cmd_buffer *cmd_buffer) { - TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer); - tu_cs_end(&cmd_buffer->draw_cs); tu_cs_end(&cmd_buffer->draw_epilogue_cs); @@ -4731,12 +4829,6 @@ tu_CmdEndRenderPass2(VkCommandBuffer commandBuffer, tu_cs_discard_entries(&cmd_buffer->draw_epilogue_cs); tu_cs_begin(&cmd_buffer->draw_epilogue_cs); - cmd_buffer->state.cache.pending_flush_bits |= - cmd_buffer->state.renderpass_cache.pending_flush_bits; - tu_subpass_barrier(cmd_buffer, &cmd_buffer->state.pass->end_barrier, true); - - vk_free(&cmd_buffer->pool->vk.alloc, cmd_buffer->state.attachments); - cmd_buffer->state.pass = NULL; cmd_buffer->state.subpass = NULL; cmd_buffer->state.framebuffer = NULL; @@ -4754,6 +4846,29 @@ tu_CmdEndRenderPass2(VkCommandBuffer commandBuffer, cmd_buffer->state.dirty |= TU_CMD_DIRTY_LRZ; } +VKAPI_ATTR void VKAPI_CALL +tu_CmdEndRenderPass2(VkCommandBuffer commandBuffer, + const VkSubpassEndInfo *pSubpassEndInfo) +{ + TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer); + + tu_end_rendering(cmd_buffer); + + cmd_buffer->state.cache.pending_flush_bits |= + cmd_buffer->state.renderpass_cache.pending_flush_bits; + tu_subpass_barrier(cmd_buffer, &cmd_buffer->state.pass->end_barrier, true); + + vk_free(&cmd_buffer->pool->vk.alloc, cmd_buffer->state.attachments); +} + +VKAPI_ATTR void VKAPI_CALL +tu_CmdEndRendering(VkCommandBuffer commandBuffer) +{ + TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer); + + tu_end_rendering(cmd_buffer); +} + static void tu_barrier(struct tu_cmd_buffer *cmd, const VkDependencyInfo *dep_info) diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c index 4dccc2f033e..1986701c796 100644 --- a/src/freedreno/vulkan/tu_device.c +++ b/src/freedreno/vulkan/tu_device.c @@ -2628,6 +2628,23 @@ tu_CreateFramebuffer(VkDevice _device, return VK_SUCCESS; } +void +tu_setup_dynamic_framebuffer(struct tu_cmd_buffer *cmd_buffer, + const VkRenderingInfo *pRenderingInfo) +{ + struct tu_render_pass *pass = &cmd_buffer->dynamic_pass; + struct tu_framebuffer *framebuffer = &cmd_buffer->dynamic_framebuffer; + + framebuffer->attachment_count = pass->attachment_count; + framebuffer->width = pRenderingInfo->renderArea.offset.x + + pRenderingInfo->renderArea.extent.width; + framebuffer->height = pRenderingInfo->renderArea.offset.y + + pRenderingInfo->renderArea.extent.height; + framebuffer->layers = pRenderingInfo->layerCount; + + tu_framebuffer_tiling_config(framebuffer, cmd_buffer->device, pass); +} + VKAPI_ATTR void VKAPI_CALL tu_DestroyFramebuffer(VkDevice _device, VkFramebuffer _fb, diff --git a/src/freedreno/vulkan/tu_image.c b/src/freedreno/vulkan/tu_image.c index bf892ccbdf8..d04b4860ebf 100644 --- a/src/freedreno/vulkan/tu_image.c +++ b/src/freedreno/vulkan/tu_image.c @@ -180,6 +180,7 @@ tu_image_view_init(struct tu_image_view *iview, vk_find_struct_const(pCreateInfo->pNext, IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT); iview->image = image; + iview->format = pCreateInfo->format; const struct fdl_layout *layouts[3]; diff --git a/src/freedreno/vulkan/tu_pass.c b/src/freedreno/vulkan/tu_pass.c index 7eab7ad4a5c..97838d639af 100644 --- a/src/freedreno/vulkan/tu_pass.c +++ b/src/freedreno/vulkan/tu_pass.c @@ -523,6 +523,19 @@ static void update_samples(struct tu_subpass *subpass, subpass->samples = samples; } +static void +tu_render_pass_cond_config(struct tu_render_pass *pass) +{ + for (uint32_t i = 0; i < pass->attachment_count; i++) { + struct tu_render_pass_attachment *att = &pass->attachments[i]; + + att->cond_load_allowed = + (att->load || att->load_stencil) && !att->clear_mask && !att->will_be_resolved; + att->cond_store_allowed = + (att->store || att->store_stencil) && !att->clear_mask; + } +} + static void tu_render_pass_gmem_config(struct tu_render_pass *pass, const struct tu_physical_device *phys_dev) @@ -626,6 +639,32 @@ tu_render_pass_gmem_config(struct tu_render_pass *pass, pass->gmem_pixels = pixels; } +static void +tu_render_pass_bandwidth_config(struct tu_render_pass *pass) +{ + for (uint32_t i = 0; i < pass->attachment_count; i++) { + const struct tu_render_pass_attachment *att = &pass->attachments[i]; + + /* approximate tu_load_gmem_attachment */ + if (att->load) + pass->gmem_bandwidth_per_pixel += att->cpp; + + /* approximate tu_store_gmem_attachment */ + if (att->store) + pass->gmem_bandwidth_per_pixel += att->cpp; + + /* approximate tu_clear_sysmem_attachment */ + if (att->clear_mask) + pass->sysmem_bandwidth_per_pixel += att->cpp; + + /* approximate tu6_emit_sysmem_resolves */ + if (att->will_be_resolved) { + pass->sysmem_bandwidth_per_pixel += + att->cpp + att->cpp / att->samples; + } + } +} + static void attachment_set_ops(struct tu_device *device, struct tu_render_pass_attachment *att, @@ -876,36 +915,11 @@ tu_CreateRenderPass2(VkDevice _device, att->clear_mask = 0; att->load = false; } - - att->cond_load_allowed = - (att->load || att->load_stencil) && !att->clear_mask && !att->will_be_resolved; - att->cond_store_allowed = - (att->store || att->store_stencil) && !att->clear_mask; } + tu_render_pass_cond_config(pass); tu_render_pass_gmem_config(pass, device->physical_device); - - for (uint32_t i = 0; i < pass->attachment_count; i++) { - const struct tu_render_pass_attachment *att = &pass->attachments[i]; - - /* approximate tu_load_gmem_attachment */ - if (att->load) - pass->gmem_bandwidth_per_pixel += att->cpp; - - /* approximate tu_store_gmem_attachment */ - if (att->store) - pass->gmem_bandwidth_per_pixel += att->cpp; - - /* approximate tu_clear_sysmem_attachment */ - if (att->clear_mask) - pass->sysmem_bandwidth_per_pixel += att->cpp; - - /* approximate tu6_emit_sysmem_resolves */ - if (att->will_be_resolved) { - pass->sysmem_bandwidth_per_pixel += - att->cpp + att->cpp / att->samples; - } - } + tu_render_pass_bandwidth_config(pass); for (unsigned i = 0; i < pCreateInfo->dependencyCount; ++i) { tu_render_pass_add_subpass_dep(pass, &pCreateInfo->pDependencies[i]); @@ -933,6 +947,197 @@ tu_DestroyRenderPass(VkDevice _device, vk_object_free(&device->vk, pAllocator, pass); } +static void +tu_setup_dynamic_attachment(struct tu_render_pass_attachment *att, + struct tu_image_view *view) +{ + att->format = view->format; + att->samples = view->image->layout->nr_samples; + + /* for d32s8, cpp is for the depth image, and + * att->samples will be used as the cpp for the stencil image + */ + if (att->format == VK_FORMAT_D32_SFLOAT_S8_UINT) + att->cpp = 4 * att->samples; + else + att->cpp = vk_format_get_blocksize(att->format) * att->samples; +} + +void +tu_setup_dynamic_render_pass(struct tu_cmd_buffer *cmd_buffer, + const VkRenderingInfo *info) +{ + struct tu_device *device = cmd_buffer->device; + struct tu_render_pass *pass = &cmd_buffer->dynamic_pass; + struct tu_subpass *subpass = &cmd_buffer->dynamic_subpass; + + pass->subpass_count = 1; + pass->attachments = cmd_buffer->dynamic_rp_attachments; + + subpass->color_count = subpass->resolve_count = info->colorAttachmentCount; + subpass->color_attachments = cmd_buffer->dynamic_color_attachments; + subpass->resolve_attachments = cmd_buffer->dynamic_resolve_attachments; + subpass->feedback_invalidate = false; + subpass->feedback_loop_ds = subpass->feedback_loop_color = false; + subpass->input_count = 0; + subpass->samples = 0; + subpass->srgb_cntl = 0; + subpass->raster_order_attachment_access = false; + subpass->multiview_mask = info->viewMask; + + uint32_t a = 0; + for (uint32_t i = 0; i < info->colorAttachmentCount; i++) { + struct tu_render_pass_attachment *att = &pass->attachments[a]; + const VkRenderingAttachmentInfo *att_info = &info->pColorAttachments[i]; + + if (att_info->imageView == VK_NULL_HANDLE) { + subpass->color_attachments[i].attachment = VK_ATTACHMENT_UNUSED; + subpass->resolve_attachments[i].attachment = VK_ATTACHMENT_UNUSED; + continue; + } + + TU_FROM_HANDLE(tu_image_view, view, att_info->imageView); + tu_setup_dynamic_attachment(att, view); + att->gmem_offset = 0; + att->clear_views = info->viewMask; + attachment_set_ops(device, att, att_info->loadOp, 0, + att_info->storeOp, 0); + subpass->color_attachments[i].attachment = a++; + + subpass->samples = view->image->layout->nr_samples; + + if (vk_format_is_srgb(view->format)) + subpass->srgb_cntl |= 1 << i; + + if (att_info->resolveMode != VK_RESOLVE_MODE_NONE) { + struct tu_render_pass_attachment *resolve_att = &pass->attachments[a]; + TU_FROM_HANDLE(tu_image_view, resolve_view, att_info->resolveImageView); + tu_setup_dynamic_attachment(resolve_att, resolve_view); + resolve_att->gmem_offset = -1; + attachment_set_ops(device, resolve_att, + VK_ATTACHMENT_LOAD_OP_DONT_CARE, 0, + VK_ATTACHMENT_STORE_OP_STORE, 0); + subpass->resolve_attachments[i].attachment = a++; + att->will_be_resolved = true; + } else { + subpass->resolve_attachments[i].attachment = VK_ATTACHMENT_UNUSED; + att->will_be_resolved = false; + } + } + + if (info->pDepthAttachment || info->pStencilAttachment) { + const struct VkRenderingAttachmentInfo *common_info = + (info->pDepthAttachment && + info->pDepthAttachment->imageView != VK_NULL_HANDLE) ? + info->pDepthAttachment : + info->pStencilAttachment; + + if (common_info && common_info->imageView != VK_NULL_HANDLE) { + TU_FROM_HANDLE(tu_image_view, view, common_info->imageView); + + struct tu_render_pass_attachment *att = &pass->attachments[a]; + tu_setup_dynamic_attachment(att, view); + att->gmem_offset = 0; + att->clear_views = info->viewMask; + subpass->depth_stencil_attachment.attachment = a++; + + attachment_set_ops(device, att, + info->pDepthAttachment ? info->pDepthAttachment->loadOp : 0, + info->pStencilAttachment ? info->pStencilAttachment->loadOp : 0, + info->pDepthAttachment ? info->pDepthAttachment->storeOp : 0, + info->pStencilAttachment ? info->pStencilAttachment->storeOp : 0); + + subpass->samples = view->image->layout->nr_samples; + + if (common_info->resolveMode != VK_RESOLVE_MODE_NONE) { + unsigned i = subpass->resolve_count++; + struct tu_render_pass_attachment *resolve_att = &pass->attachments[a]; + TU_FROM_HANDLE(tu_image_view, resolve_view, + common_info->resolveImageView); + tu_setup_dynamic_attachment(resolve_att, resolve_view); + resolve_att->gmem_offset = -1; + attachment_set_ops(device, resolve_att, + VK_ATTACHMENT_LOAD_OP_DONT_CARE, + VK_ATTACHMENT_LOAD_OP_DONT_CARE, + VK_ATTACHMENT_STORE_OP_STORE, + VK_ATTACHMENT_STORE_OP_STORE); + subpass->resolve_attachments[i].attachment = a++; + att->will_be_resolved = true; + subpass->resolve_depth_stencil = true; + } else { + att->will_be_resolved = false; + } + } else { + subpass->depth_stencil_attachment.attachment = VK_ATTACHMENT_UNUSED; + } + } else { + subpass->depth_stencil_attachment.attachment = VK_ATTACHMENT_UNUSED; + } + + pass->attachment_count = a; + + tu_render_pass_cond_config(pass); + tu_render_pass_gmem_config(pass, device->physical_device); + tu_render_pass_bandwidth_config(pass); +} + +void +tu_setup_dynamic_inheritance(struct tu_cmd_buffer *cmd_buffer, + const VkCommandBufferInheritanceRenderingInfo *info) +{ + struct tu_render_pass *pass = &cmd_buffer->dynamic_pass; + struct tu_subpass *subpass = &cmd_buffer->dynamic_subpass; + + pass->subpass_count = 1; + pass->attachments = cmd_buffer->dynamic_rp_attachments; + + subpass->color_count = info->colorAttachmentCount; + subpass->resolve_count = 0; + subpass->color_attachments = cmd_buffer->dynamic_color_attachments; + subpass->resolve_attachments = NULL; + subpass->feedback_invalidate = false; + subpass->feedback_loop_ds = subpass->feedback_loop_color = false; + subpass->input_count = 0; + subpass->samples = 0; + subpass->srgb_cntl = 0; + subpass->raster_order_attachment_access = false; + subpass->multiview_mask = info->viewMask; + subpass->samples = info->rasterizationSamples; + + unsigned a = 0; + for (unsigned i = 0; i < info->colorAttachmentCount; i++) { + struct tu_render_pass_attachment *att = &pass->attachments[a]; + VkFormat format = info->pColorAttachmentFormats[i]; + + if (format == VK_FORMAT_UNDEFINED) { + subpass->color_attachments[i].attachment = VK_ATTACHMENT_UNUSED; + continue; + } + + att->format = format; + att->samples = info->rasterizationSamples; + subpass->samples = info->rasterizationSamples; + subpass->color_attachments[i].attachment = a++; + + /* conservatively assume that the attachment may be conditionally + * loaded/stored. + */ + att->cond_load_allowed = att->cond_store_allowed = true; + } + + if (info->depthAttachmentFormat != VK_FORMAT_UNDEFINED || + info->stencilAttachmentFormat != VK_FORMAT_UNDEFINED) { + struct tu_render_pass_attachment *att = &pass->attachments[a]; + att->format = info->depthAttachmentFormat != VK_FORMAT_UNDEFINED ? + info->depthAttachmentFormat : info->stencilAttachmentFormat; + att->samples = info->rasterizationSamples; + subpass->depth_stencil_attachment.attachment = a++; + att->cond_load_allowed = att->cond_store_allowed = true; + } else { + subpass->depth_stencil_attachment.attachment = VK_ATTACHMENT_UNUSED; + } +} + VKAPI_ATTR void VKAPI_CALL tu_GetRenderAreaGranularity(VkDevice _device, VkRenderPass renderPass, diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c index bdda536fbb8..90acc12a3f2 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -3890,24 +3890,85 @@ tu_pipeline_builder_init_graphics( } } - const struct tu_render_pass *pass = - tu_render_pass_from_handle(create_info->renderPass); - const struct tu_subpass *subpass = - &pass->subpasses[create_info->subpass]; - - builder->subpass_raster_order_attachment_access = - subpass->raster_order_attachment_access; - builder->subpass_feedback_loop_color = subpass->feedback_loop_color; - builder->subpass_feedback_loop_ds = subpass->feedback_loop_ds; - - builder->multiview_mask = subpass->multiview_mask; - builder->rasterizer_discard = builder->create_info->pRasterizationState->rasterizerDiscardEnable && !rasterizer_discard_dynamic; - /* variableMultisampleRate support */ - builder->emit_msaa_state = (subpass->samples == 0) && !builder->rasterizer_discard; + const VkPipelineRenderingCreateInfo *rendering_info = + vk_find_struct_const(create_info->pNext, PIPELINE_RENDERING_CREATE_INFO); + + if (rendering_info) { + builder->subpass_raster_order_attachment_access = false; + builder->subpass_feedback_loop_ds = false; + builder->subpass_feedback_loop_color = false; + + builder->multiview_mask = rendering_info->viewMask; + + /* We don't know with dynamic rendering whether the pipeline will be + * used in a render pass with none of attachments enabled, so we have to + * dynamically emit MSAA state. + * + * TODO: Move MSAA state to a separate draw state and emit it + * dynamically only when the sample count is different from the + * subpass's sample count. + */ + builder->emit_msaa_state = !builder->rasterizer_discard; + + if (!builder->rasterizer_discard) { + builder->depth_attachment_format = + rendering_info->depthAttachmentFormat == VK_FORMAT_UNDEFINED ? + rendering_info->stencilAttachmentFormat : + rendering_info->depthAttachmentFormat; + + builder->color_attachment_count = + rendering_info->colorAttachmentCount; + + for (unsigned i = 0; i < rendering_info->colorAttachmentCount; i++) { + builder->color_attachment_formats[i] = + rendering_info->pColorAttachmentFormats[i]; + if (builder->color_attachment_formats[i] != VK_FORMAT_UNDEFINED) { + builder->use_color_attachments = true; + builder->render_components |= 0xf << (i * 4); + } + } + } + } else { + const struct tu_render_pass *pass = + tu_render_pass_from_handle(create_info->renderPass); + const struct tu_subpass *subpass = + &pass->subpasses[create_info->subpass]; + + builder->subpass_raster_order_attachment_access = + subpass->raster_order_attachment_access; + builder->subpass_feedback_loop_color = subpass->feedback_loop_color; + builder->subpass_feedback_loop_ds = subpass->feedback_loop_ds; + + builder->multiview_mask = subpass->multiview_mask; + + /* variableMultisampleRate support */ + builder->emit_msaa_state = (subpass->samples == 0) && !builder->rasterizer_discard; + + if (!builder->rasterizer_discard) { + const uint32_t a = subpass->depth_stencil_attachment.attachment; + builder->depth_attachment_format = (a != VK_ATTACHMENT_UNUSED) ? + pass->attachments[a].format : VK_FORMAT_UNDEFINED; + + assert(subpass->color_count == 0 || + !create_info->pColorBlendState || + subpass->color_count == create_info->pColorBlendState->attachmentCount); + builder->color_attachment_count = subpass->color_count; + for (uint32_t i = 0; i < subpass->color_count; i++) { + const uint32_t a = subpass->color_attachments[i].attachment; + if (a == VK_ATTACHMENT_UNUSED) + continue; + + builder->color_attachment_formats[i] = pass->attachments[a].format; + builder->use_color_attachments = true; + builder->render_components |= 0xf << (i * 4); + } + } + } + if (builder->rasterizer_discard) { builder->samples = VK_SAMPLE_COUNT_1_BIT; @@ -3915,29 +3976,11 @@ tu_pipeline_builder_init_graphics( builder->samples = create_info->pMultisampleState->rasterizationSamples; builder->alpha_to_coverage = create_info->pMultisampleState->alphaToCoverageEnable; - const uint32_t a = subpass->depth_stencil_attachment.attachment; - builder->depth_attachment_format = (a != VK_ATTACHMENT_UNUSED) ? - pass->attachments[a].format : VK_FORMAT_UNDEFINED; - - assert(subpass->color_count == 0 || - !create_info->pColorBlendState || - subpass->color_count == create_info->pColorBlendState->attachmentCount); - builder->color_attachment_count = subpass->color_count; - for (uint32_t i = 0; i < subpass->color_count; i++) { - const uint32_t a = subpass->color_attachments[i].attachment; - if (a == VK_ATTACHMENT_UNUSED) - continue; - - builder->color_attachment_formats[i] = pass->attachments[a].format; - builder->use_color_attachments = true; - builder->render_components |= 0xf << (i * 4); - } - if (tu_blend_state_is_dual_src(create_info->pColorBlendState)) { builder->color_attachment_count++; builder->use_dual_src_blend = true; /* dual source blending has an extra fs output in the 2nd slot */ - if (subpass->color_attachments[0].attachment != VK_ATTACHMENT_UNUSED) + if (builder->color_attachment_formats[0] != VK_FORMAT_UNDEFINED) builder->render_components |= 0xf << 4; } } diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h index 7eeef5c0f2f..f835874bcf7 100644 --- a/src/freedreno/vulkan/tu_private.h +++ b/src/freedreno/vulkan/tu_private.h @@ -1459,6 +1459,15 @@ struct tu_cmd_buffer struct tu_descriptor_state descriptors[MAX_BIND_POINTS]; + struct tu_render_pass_attachment dynamic_rp_attachments[2 * (MAX_RTS + 1)]; + struct tu_subpass_attachment dynamic_color_attachments[MAX_RTS]; + struct tu_subpass_attachment dynamic_resolve_attachments[MAX_RTS + 1]; + const struct tu_image_view *dynamic_attachments[2 * (MAX_RTS + 1)]; + + struct tu_render_pass dynamic_pass; + struct tu_subpass dynamic_subpass; + struct tu_framebuffer dynamic_framebuffer; + VkResult record_result; struct tu_cs cs; @@ -1492,6 +1501,15 @@ void tu_emit_cache_flush_ccu(struct tu_cmd_buffer *cmd_buffer, struct tu_cs *cs, enum tu_cmd_ccu_state ccu_state); +void tu_setup_dynamic_render_pass(struct tu_cmd_buffer *cmd_buffer, + const VkRenderingInfo *pRenderingInfo); + +void tu_setup_dynamic_inheritance(struct tu_cmd_buffer *cmd_buffer, + const VkCommandBufferInheritanceRenderingInfo *info); + +void tu_setup_dynamic_framebuffer(struct tu_cmd_buffer *cmd_buffer, + const VkRenderingInfo *pRenderingInfo); + void tu6_emit_event_write(struct tu_cmd_buffer *cmd, struct tu_cs *cs, @@ -1936,6 +1954,8 @@ struct tu_image_view struct tu_image *image; /**< VkImageViewCreateInfo::image */ + VkFormat format; + struct fdl6_view view; /* for d32s8 separate depth */