diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index bfc07ba84eb..6c763c62c29 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -92,6 +92,7 @@ static const struct vk_device_extension_table lvp_device_extensions_supported = .KHR_device_group = true, .KHR_draw_indirect_count = true, .KHR_driver_properties = true, + .KHR_dynamic_rendering = true, .KHR_external_fence = true, .KHR_external_memory = true, #ifdef PIPE_MEMORY_FD @@ -666,6 +667,11 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFeatures2( features->primitiveTopologyPatchListRestart = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR: { + VkPhysicalDeviceDynamicRenderingFeaturesKHR *features = (VkPhysicalDeviceDynamicRenderingFeaturesKHR *)ext; + features->dynamicRendering = VK_TRUE; + break; + } default: break; } diff --git a/src/gallium/frontends/lavapipe/lvp_execute.c b/src/gallium/frontends/lavapipe/lvp_execute.c index 3f53e822428..1e4422203cd 100644 --- a/src/gallium/frontends/lavapipe/lvp_execute.c +++ b/src/gallium/frontends/lavapipe/lvp_execute.c @@ -1805,8 +1805,171 @@ static void handle_begin_render_pass2(struct vk_cmd_queue_entry *cmd, begin_render_pass(cmd->u.begin_render_pass2.render_pass_begin, state); } -static void handle_end_render_pass2(struct vk_cmd_queue_entry *cmd, - struct rendering_state *state) +static VkAttachmentLoadOp +get_load_op(VkAttachmentLoadOp op, bool resuming) +{ + if (!resuming) + return op; + if (op == VK_ATTACHMENT_LOAD_OP_CLEAR) + return VK_ATTACHMENT_LOAD_OP_LOAD; + return op; +} + +static void handle_begin_rendering(struct vk_cmd_queue_entry *cmd, + struct rendering_state *state) +{ + const VkRenderingInfoKHR *info = cmd->u.begin_rendering_khr.rendering_info; + bool resuming = (info->flags & VK_RENDERING_RESUMING_BIT_KHR) == VK_RENDERING_RESUMING_BIT_KHR; + bool suspending = (info->flags & VK_RENDERING_SUSPENDING_BIT_KHR) == VK_RENDERING_SUSPENDING_BIT_KHR; + assert(!state->pass); + state->vk_framebuffer = NULL; + state->render_area = info->renderArea; + + unsigned num_attachments = info->colorAttachmentCount + (info->pDepthAttachment || info->pStencilAttachment); + unsigned i, color_resolves = 0; + for (i = 0; i < info->colorAttachmentCount; i++) { + if (info->pColorAttachments[i].resolveImageView) + color_resolves++; + } + bool zresolve = info->pDepthAttachment && info->pDepthAttachment->resolveImageView; + bool sresolve = info->pStencilAttachment && info->pStencilAttachment->resolveImageView; + unsigned num_resolves = color_resolves + (zresolve || sresolve); + unsigned attachment_count = num_attachments + num_resolves; + state->imageless_views = realloc(state->imageless_views, sizeof(*state->imageless_views) * attachment_count); + + state->render_area = info->renderArea; + state->framebuffer.width = info->renderArea.offset.x + info->renderArea.extent.width; + state->framebuffer.height = info->renderArea.offset.y + info->renderArea.extent.height; + state->framebuffer.layers = info->layerCount; + + if (state->num_pending_aspects < attachment_count) { + state->pending_clear_aspects = realloc(state->pending_clear_aspects, sizeof(VkImageAspectFlags) * attachment_count); + state->cleared_views = realloc(state->cleared_views, sizeof(uint32_t) * attachment_count); + state->num_pending_aspects = attachment_count; + } + + /* [lvp_subpass] [attachment_count * lvp_render_pass_attachment] [attachment_count * lvp_render_pass_attachment*] */ + size_t size = sizeof(struct lvp_subpass) + attachment_count * (sizeof(void*) + sizeof(struct lvp_render_pass_attachment)); + size_t attachment_offset = sizeof(struct lvp_subpass); + size_t attachment_ref_offset = attachment_offset + attachment_count * sizeof(struct lvp_render_pass_attachment); + struct lvp_subpass *subpass = calloc(1, size); + subpass->color_count = info->colorAttachmentCount; + bool has_ds = !!info->pDepthAttachment + !!info->pStencilAttachment; + state->attachments = realloc(state->attachments, sizeof(*state->attachments) * attachment_count); + struct lvp_render_pass_attachment *attachments = (void*)((uint8_t*)subpass + attachment_offset); + struct lvp_render_pass_attachment *resolve_attachments = num_resolves ? &attachments[subpass->color_count + has_ds] : NULL; + struct lvp_render_pass_attachment **attachment_refs = (void*)((uint8_t*)subpass + attachment_ref_offset); + struct lvp_render_pass_attachment **resolve_attachment_refs = num_resolves ? &attachment_refs[subpass->color_count + has_ds] : NULL; + + subpass->view_mask = info->viewMask; + subpass->has_color_resolve = color_resolves > 0; + if (info->colorAttachmentCount) + subpass->color_attachments = attachment_refs; + if (has_ds) + subpass->depth_stencil_attachment = &attachment_refs[info->colorAttachmentCount]; + if (color_resolves) + subpass->resolve_attachments = resolve_attachment_refs; + if (zresolve || sresolve) + subpass->ds_resolve_attachment = &resolve_attachment_refs[color_resolves]; + + unsigned resolve_idx = 0; + for (i = 0; i < info->colorAttachmentCount; i++) { + if (!info->pColorAttachments[i].imageView) + continue; + struct lvp_render_pass_attachment *att = &attachments[i]; + + att->attachment = i; + att->load_op = get_load_op(info->pColorAttachments[i].loadOp, resuming); + if (att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { + state->attachments[i].pending_clear_aspects = VK_IMAGE_ASPECT_COLOR_BIT; + state->attachments[i].clear_value = info->pColorAttachments[i].clearValue; + } else + state->attachments[i].pending_clear_aspects = 0; + + state->pending_clear_aspects[i] = state->attachments[i].pending_clear_aspects; + state->cleared_views[i] = 0; + + state->imageless_views[i] = lvp_image_view_from_handle(info->pColorAttachments[i].imageView); + att->format = state->imageless_views[i]->format; + att->samples = state->imageless_views[i]->image->bo->nr_samples; + attachment_refs[i] = att; + if (!suspending && info->pColorAttachments[i].resolveImageView) { + struct lvp_render_pass_attachment *resolve_att = &resolve_attachments[resolve_idx]; + resolve_att->attachment = num_attachments + resolve_idx; + resolve_att->load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + state->imageless_views[num_attachments + resolve_idx] = lvp_image_view_from_handle(info->pColorAttachments[i].resolveImageView); + resolve_att->format = state->imageless_views[num_attachments + resolve_idx]->format; + resolve_att->samples = state->imageless_views[num_attachments + resolve_idx]->image->bo->nr_samples; + resolve_attachment_refs[resolve_idx] = resolve_att; + resolve_idx++; + } + } + if (info->pDepthAttachment && info->pDepthAttachment->imageView) { + struct lvp_render_pass_attachment *att = &attachments[i]; + + att->attachment = i; + att->load_op = get_load_op(info->pDepthAttachment->loadOp, resuming); + att->stencil_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + if (att->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { + state->attachments[i].pending_clear_aspects = VK_IMAGE_ASPECT_DEPTH_BIT; + state->attachments[i].clear_value = info->pDepthAttachment->clearValue; + } else + state->attachments[i].pending_clear_aspects = 0; + + state->pending_clear_aspects[i] = state->attachments[i].pending_clear_aspects; + state->cleared_views[i] = 0; + + state->imageless_views[i] = lvp_image_view_from_handle(info->pDepthAttachment->imageView); + att->format = state->imageless_views[i]->format; + att->samples = state->imageless_views[i]->image->bo->nr_samples; + attachment_refs[i] = att; + if (!suspending && info->pDepthAttachment->resolveImageView) { + struct lvp_render_pass_attachment *resolve_att = &resolve_attachments[resolve_idx]; + resolve_att->attachment = num_attachments + resolve_idx; + resolve_att->load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + state->imageless_views[num_attachments + resolve_idx] = lvp_image_view_from_handle(info->pDepthAttachment->resolveImageView); + resolve_att->format = state->imageless_views[num_attachments + resolve_idx]->format; + resolve_att->samples = state->imageless_views[num_attachments + resolve_idx]->image->bo->nr_samples; + resolve_attachment_refs[resolve_idx] = resolve_att; + } + } + if (info->pStencilAttachment && info->pStencilAttachment->imageView) { + struct lvp_render_pass_attachment *att = &attachments[i]; + + att->attachment = i; + if (!info->pDepthAttachment) + att->load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + att->stencil_load_op = get_load_op(info->pStencilAttachment->loadOp, resuming); + if (!info->pDepthAttachment) + state->attachments[i].pending_clear_aspects = 0; + if (att->stencil_load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { + state->attachments[i].pending_clear_aspects |= VK_IMAGE_ASPECT_STENCIL_BIT; + state->attachments[i].clear_value.depthStencil.stencil = info->pStencilAttachment->clearValue.depthStencil.stencil; + } + + state->pending_clear_aspects[i] |= state->attachments[i].pending_clear_aspects; + state->cleared_views[i] = 0; + + state->imageless_views[i] = lvp_image_view_from_handle(info->pStencilAttachment->imageView); + att->format = state->imageless_views[i]->format; + att->samples = state->imageless_views[i]->image->bo->nr_samples; + attachment_refs[i] = att; + if (!suspending && info->pStencilAttachment->resolveImageView) { + struct lvp_render_pass_attachment *resolve_att = &resolve_attachments[resolve_idx]; + resolve_att->attachment = num_attachments + resolve_idx; + resolve_att->load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + state->imageless_views[num_attachments + resolve_idx] = lvp_image_view_from_handle(info->pStencilAttachment->resolveImageView); + resolve_att->format = state->imageless_views[num_attachments + resolve_idx]->format; + resolve_att->samples = state->imageless_views[num_attachments + resolve_idx]->image->bo->nr_samples; + resolve_attachment_refs[resolve_idx] = resolve_att; + } + } + + begin_render_subpass(state, subpass); +} + +static void +end_rendering(struct rendering_state *state) { state->pctx->flush(state->pctx, NULL, 0); @@ -1815,6 +1978,20 @@ static void handle_end_render_pass2(struct vk_cmd_queue_entry *cmd, free(state->attachments); state->attachments = NULL; state->pass = NULL; +} + +static void handle_end_rendering(struct vk_cmd_queue_entry *cmd, + struct rendering_state *state) +{ + end_rendering(state); + free(state->subpass); + state->subpass = NULL; +} + +static void handle_end_render_pass2(struct vk_cmd_queue_entry *cmd, + struct rendering_state *state) +{ + end_rendering(state); state->subpass = NULL; } @@ -3909,6 +4086,12 @@ static void lvp_execute_cmd_buffer(struct lvp_cmd_buffer *cmd_buffer, case VK_CMD_SET_COLOR_WRITE_ENABLE_EXT: handle_set_color_write_enable(cmd, state); break; + case VK_CMD_BEGIN_RENDERING_KHR: + handle_begin_rendering(cmd, state); + break; + case VK_CMD_END_RENDERING_KHR: + handle_end_rendering(cmd, state); + break; case VK_CMD_SET_DEVICE_MASK: /* no-op */ break; diff --git a/src/gallium/frontends/lavapipe/lvp_pipeline.c b/src/gallium/frontends/lavapipe/lvp_pipeline.c index ef5de756281..8720fd8479b 100644 --- a/src/gallium/frontends/lavapipe/lvp_pipeline.c +++ b/src/gallium/frontends/lavapipe/lvp_pipeline.c @@ -279,6 +279,7 @@ deep_copy_graphics_create_info(void *mem_ctx, VkPipelineVertexInputStateCreateInfo *vertex_input; VkPipelineRasterizationStateCreateInfo *rasterization_state; LVP_FROM_HANDLE(lvp_render_pass, pass, src->renderPass); + const VkPipelineRenderingCreateInfoKHR *rp_info = vk_find_struct_const(src->pNext, PIPELINE_RENDERING_CREATE_INFO_KHR); dst->sType = src->sType; dst->pNext = NULL; @@ -367,7 +368,8 @@ deep_copy_graphics_create_info(void *mem_ctx, dst->pMultisampleState = NULL; /* pDepthStencilState */ - if (src->pDepthStencilState && !rasterization_disabled && pass->has_zs_attachment) { + if (src->pDepthStencilState && !rasterization_disabled && + (pass ? pass->has_zs_attachment : (rp_info->depthAttachmentFormat || rp_info->stencilAttachmentFormat))) { LVP_PIPELINE_DUP(dst->pDepthStencilState, src->pDepthStencilState, VkPipelineDepthStencilStateCreateInfo, @@ -376,7 +378,8 @@ deep_copy_graphics_create_info(void *mem_ctx, dst->pDepthStencilState = NULL; /* pColorBlendState */ - if (src->pColorBlendState && !rasterization_disabled && pass->has_color_attachment) { + if (src->pColorBlendState && !rasterization_disabled && + (pass ? pass->has_color_attachment : rp_info->colorAttachmentCount)) { VkPipelineColorBlendStateCreateInfo* cb_state; cb_state = ralloc(mem_ctx, VkPipelineColorBlendStateCreateInfo);