From 9b844d7c42129925525d613c19622b11aee16298 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Mon, 18 Jul 2022 16:49:59 +0200 Subject: [PATCH] tu: Add debug option to use emulated renderpass support This should be useful for stress-testing dynamic rendering. Part-of: --- src/freedreno/ci/deqp-freedreno-a630-vk.toml | 11 ++++ src/freedreno/vulkan/tu_cmd_buffer.c | 59 +++++++++++++++++--- src/freedreno/vulkan/tu_descriptor_set.c | 7 +++ src/freedreno/vulkan/tu_device.c | 12 ++++ src/freedreno/vulkan/tu_pass.c | 11 ++++ src/freedreno/vulkan/tu_pipeline.c | 15 +++++ src/freedreno/vulkan/tu_private.h | 2 + src/freedreno/vulkan/tu_shader.c | 20 ++++--- 8 files changed, 120 insertions(+), 17 deletions(-) diff --git a/src/freedreno/ci/deqp-freedreno-a630-vk.toml b/src/freedreno/ci/deqp-freedreno-a630-vk.toml index e83db59f505..3ac25c75258 100644 --- a/src/freedreno/ci/deqp-freedreno-a630-vk.toml +++ b/src/freedreno/ci/deqp-freedreno-a630-vk.toml @@ -49,3 +49,14 @@ prefix = "spill-" fraction = 10 [deqp.env] IR3_SHADER_DEBUG = "spillall" + +# dynamic rendering testing using emulated renderpass +[[deqp]] +deqp = "/deqp/external/vulkancts/modules/vulkan/deqp-vk" +caselists = ["/deqp/mustpass/vk-master.txt"] +skips = ["install/freedreno-a630-premerge-skips.txt"] +include = ["dEQP-VK.renderpass2.*"] +prefix = "dynamic-" +fraction = 10 +[deqp.env] +TU_DEBUG = "dynamic" diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c index 4843b37be8c..285d2c9872b 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.c +++ b/src/freedreno/vulkan/tu_cmd_buffer.c @@ -31,6 +31,7 @@ #include "adreno_common.xml.h" #include "vk_format.h" +#include "vk_render_pass.h" #include "vk_util.h" #include "tu_cs.h" @@ -1845,17 +1846,24 @@ tu_BeginCommandBuffer(VkCommandBuffer commandBuffer, } if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) { - 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); + const VkCommandBufferInheritanceRenderingInfo *rendering_info = + vk_find_struct_const(pBeginInfo->pInheritanceInfo->pNext, + COMMAND_BUFFER_INHERITANCE_RENDERING_INFO); + + if (unlikely(cmd_buffer->device->instance->debug_flags & TU_DEBUG_DYNAMIC)) { + rendering_info = + vk_get_command_buffer_inheritance_rendering_info(cmd_buffer->vk.level, + pBeginInfo); + } + + if (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; + } else { + cmd_buffer->state.pass = tu_render_pass_from_handle(pBeginInfo->pInheritanceInfo->renderPass); + cmd_buffer->state.subpass = + &cmd_buffer->state.pass->subpasses[pBeginInfo->pInheritanceInfo->subpass]; } tu_lrz_begin_secondary_cmdbuf(cmd_buffer); } else { @@ -3822,6 +3830,13 @@ tu_CmdBeginRenderPass2(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo *pSubpassBeginInfo) { TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer); + + if (unlikely(cmd->device->instance->debug_flags & TU_DEBUG_DYNAMIC)) { + vk_common_CmdBeginRenderPass2(commandBuffer, pRenderPassBegin, + pSubpassBeginInfo); + return; + } + TU_FROM_HANDLE(tu_render_pass, pass, pRenderPassBegin->renderPass); TU_FROM_HANDLE(tu_framebuffer, fb, pRenderPassBegin->framebuffer); @@ -3937,6 +3952,22 @@ tu_CmdBeginRendering(VkCommandBuffer commandBuffer, } } + if (unlikely(cmd->device->instance->debug_flags & TU_DEBUG_DYNAMIC)) { + const VkRenderingSelfDependencyInfoMESA *self_dependency = + vk_find_struct_const(pRenderingInfo->pNext, RENDERING_SELF_DEPENDENCY_INFO_MESA); + if (self_dependency && + (self_dependency->colorSelfDependencies || + self_dependency->depthSelfDependency || + self_dependency->stencilSelfDependency)) { + /* Mesa's renderpass emulation requires us to use normal attachments + * for input attachments, and currently doesn't try to keep track of + * which color/depth attachment an input attachment corresponds to. + * So when there's a self-dependency, we have to use sysmem. + */ + cmd->state.rp.disable_gmem = true; + } + } + cmd->state.renderpass_cache.pending_flush_bits = cmd->state.cache.pending_flush_bits; cmd->state.renderpass_cache.flush_bits = 0; @@ -4008,6 +4039,13 @@ tu_CmdNextSubpass2(VkCommandBuffer commandBuffer, const VkSubpassEndInfo *pSubpassEndInfo) { TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer); + + if (unlikely(cmd->device->instance->debug_flags & TU_DEBUG_DYNAMIC)) { + vk_common_CmdNextSubpass2(commandBuffer, pSubpassBeginInfo, + pSubpassEndInfo); + return; + } + const struct tu_render_pass *pass = cmd->state.pass; struct tu_cs *cs = &cmd->draw_cs; const struct tu_subpass *last_subpass = cmd->state.subpass; @@ -5116,6 +5154,11 @@ tu_CmdEndRenderPass2(VkCommandBuffer commandBuffer, { TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer); + if (unlikely(cmd_buffer->device->instance->debug_flags & TU_DEBUG_DYNAMIC)) { + vk_common_CmdEndRenderPass2(commandBuffer, pSubpassEndInfo); + return; + } + cmd_buffer->trace_renderpass_end = u_trace_end_iterator(&cmd_buffer->trace); tu_cs_end(&cmd_buffer->draw_cs); diff --git a/src/freedreno/vulkan/tu_descriptor_set.c b/src/freedreno/vulkan/tu_descriptor_set.c index 7cf268f49d9..b40c3f7f590 100644 --- a/src/freedreno/vulkan/tu_descriptor_set.c +++ b/src/freedreno/vulkan/tu_descriptor_set.c @@ -58,6 +58,9 @@ descriptor_size(struct tu_device *dev, VkDescriptorType type) { switch (type) { case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + if (unlikely(dev->instance->debug_flags & TU_DEBUG_DYNAMIC)) + return A6XX_TEX_CONST_DWORDS * 4; + /* Input attachment doesn't use descriptor sets at all */ return 0; case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: @@ -1079,6 +1082,8 @@ tu_update_descriptor_sets(const struct tu_device *device, break; case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: /* nothing in descriptor set - framebuffer state is used instead */ + if (unlikely(device->instance->debug_flags & TU_DEBUG_DYNAMIC)) + write_image_descriptor(ptr, writeset->descriptorType, writeset->pImageInfo + j); break; default: unreachable("unimplemented descriptor type"); @@ -1306,6 +1311,8 @@ tu_update_descriptor_set_with_template( break; case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: /* nothing in descriptor set - framebuffer state is used instead */ + if (unlikely(device->instance->debug_flags & TU_DEBUG_DYNAMIC)) + write_image_descriptor(ptr, templ->entry[i].descriptor_type, src); break; default: unreachable("unimplemented descriptor type"); diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c index f5b7778f25a..b484a482813 100644 --- a/src/freedreno/vulkan/tu_device.c +++ b/src/freedreno/vulkan/tu_device.c @@ -373,6 +373,7 @@ static const struct debug_control tu_debug_options[] = { { "rast_order", TU_DEBUG_RAST_ORDER }, { "unaligned_store", TU_DEBUG_UNALIGNED_STORE }, { "log_skip_gmem_ops", TU_DEBUG_LOG_SKIP_GMEM_OPS }, + { "dynamic", TU_DEBUG_DYNAMIC }, { NULL, 0 } }; @@ -2637,6 +2638,11 @@ tu_CreateFramebuffer(VkDevice _device, VkFramebuffer *pFramebuffer) { TU_FROM_HANDLE(tu_device, device, _device); + + if (unlikely(device->instance->debug_flags & TU_DEBUG_DYNAMIC)) + return vk_common_CreateFramebuffer(_device, pCreateInfo, pAllocator, + pFramebuffer); + TU_FROM_HANDLE(tu_render_pass, pass, pCreateInfo->renderPass); struct tu_framebuffer *framebuffer; @@ -2694,6 +2700,12 @@ tu_DestroyFramebuffer(VkDevice _device, const VkAllocationCallbacks *pAllocator) { TU_FROM_HANDLE(tu_device, device, _device); + + if (unlikely(device->instance->debug_flags & TU_DEBUG_DYNAMIC)) { + vk_common_DestroyFramebuffer(_device, _fb, pAllocator); + return; + } + TU_FROM_HANDLE(tu_framebuffer, fb, _fb); if (!fb) diff --git a/src/freedreno/vulkan/tu_pass.c b/src/freedreno/vulkan/tu_pass.c index 8031b1439cd..2ecbb47527b 100644 --- a/src/freedreno/vulkan/tu_pass.c +++ b/src/freedreno/vulkan/tu_pass.c @@ -749,6 +749,11 @@ tu_CreateRenderPass2(VkDevice _device, VkRenderPass *pRenderPass) { TU_FROM_HANDLE(tu_device, device, _device); + + if (unlikely(device->instance->debug_flags & TU_DEBUG_DYNAMIC)) + return vk_common_CreateRenderPass2(_device, pCreateInfo, pAllocator, + pRenderPass); + struct tu_render_pass *pass; size_t size; size_t attachments_offset; @@ -938,6 +943,12 @@ tu_DestroyRenderPass(VkDevice _device, const VkAllocationCallbacks *pAllocator) { TU_FROM_HANDLE(tu_device, device, _device); + + if (unlikely(device->instance->debug_flags & TU_DEBUG_DYNAMIC)) { + vk_common_DestroyRenderPass(_device, _pass, pAllocator); + return; + } + TU_FROM_HANDLE(tu_render_pass, pass, _pass); if (!_pass) diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c index 90acc12a3f2..b96ca44f7f0 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -38,6 +38,7 @@ #include "util/u_atomic.h" #include "vk_format.h" #include "vk_pipeline.h" +#include "vk_render_pass.h" #include "vk_util.h" #include "tu_cs.h" @@ -3897,6 +3898,9 @@ tu_pipeline_builder_init_graphics( const VkPipelineRenderingCreateInfo *rendering_info = vk_find_struct_const(create_info->pNext, PIPELINE_RENDERING_CREATE_INFO); + if (unlikely(dev->instance->debug_flags & TU_DEBUG_DYNAMIC) && !rendering_info) + rendering_info = vk_get_pipeline_rendering_create_info(create_info); + if (rendering_info) { builder->subpass_raster_order_attachment_access = false; builder->subpass_feedback_loop_ds = false; @@ -3914,6 +3918,17 @@ tu_pipeline_builder_init_graphics( */ builder->emit_msaa_state = !builder->rasterizer_discard; + const VkRenderingSelfDependencyInfoMESA *self_dependency = + vk_find_struct_const(rendering_info->pNext, RENDERING_SELF_DEPENDENCY_INFO_MESA); + + if (self_dependency) { + builder->subpass_feedback_loop_ds = + self_dependency->depthSelfDependency || + self_dependency->stencilSelfDependency; + builder->subpass_feedback_loop_color = + self_dependency->colorSelfDependencies; + } + if (!builder->rasterizer_discard) { builder->depth_attachment_format = rendering_info->depthAttachmentFormat == VK_FORMAT_UNDEFINED ? diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h index 91f63d3e676..3ae319b6ee1 100644 --- a/src/freedreno/vulkan/tu_private.h +++ b/src/freedreno/vulkan/tu_private.h @@ -95,6 +95,7 @@ typedef uint32_t xcb_window_t; #include #include "tu_entrypoints.h" +#include "vulkan/runtime/vk_common_entrypoints.h" #include "vk_format.h" #include "vk_image.h" @@ -266,6 +267,7 @@ enum tu_debug_flags TU_DEBUG_LOG_SKIP_GMEM_OPS = 1 << 17, TU_DEBUG_PERF = 1 << 18, TU_DEBUG_NOLRZFC = 1 << 19, + TU_DEBUG_DYNAMIC = 1 << 20, }; struct tu_instance diff --git a/src/freedreno/vulkan/tu_shader.c b/src/freedreno/vulkan/tu_shader.c index ca5af8b2bf3..24a43f0fddd 100644 --- a/src/freedreno/vulkan/tu_shader.c +++ b/src/freedreno/vulkan/tu_shader.c @@ -329,7 +329,8 @@ lower_ssbo_ubo_intrinsic(struct tu_device *dev, } static nir_ssa_def * -build_bindless(nir_builder *b, nir_deref_instr *deref, bool is_sampler, +build_bindless(struct tu_device *dev, nir_builder *b, + nir_deref_instr *deref, bool is_sampler, struct tu_shader *shader, const struct tu_pipeline_layout *layout) { @@ -341,7 +342,8 @@ build_bindless(nir_builder *b, nir_deref_instr *deref, bool is_sampler, &layout->set[set].layout->binding[binding]; /* input attachments use non bindless workaround */ - if (bind_layout->type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) { + if (bind_layout->type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT && + likely(!(dev->instance->debug_flags & TU_DEBUG_DYNAMIC))) { const struct glsl_type *glsl_type = glsl_without_array(var->type); uint32_t idx = var->data.index * 2; @@ -388,12 +390,12 @@ build_bindless(nir_builder *b, nir_deref_instr *deref, bool is_sampler, } static void -lower_image_deref(nir_builder *b, +lower_image_deref(struct tu_device *dev, nir_builder *b, nir_intrinsic_instr *instr, struct tu_shader *shader, const struct tu_pipeline_layout *layout) { nir_deref_instr *deref = nir_src_as_deref(instr->src[0]); - nir_ssa_def *bindless = build_bindless(b, deref, false, shader, layout); + nir_ssa_def *bindless = build_bindless(dev, b, deref, false, shader, layout); nir_rewrite_image_intrinsic(instr, bindless, true); } @@ -454,7 +456,7 @@ lower_intrinsic(nir_builder *b, nir_intrinsic_instr *instr, case nir_intrinsic_image_deref_atomic_comp_swap: case nir_intrinsic_image_deref_size: case nir_intrinsic_image_deref_samples: - lower_image_deref(b, instr, shader, layout); + lower_image_deref(dev, b, instr, shader, layout); return true; default: @@ -533,7 +535,7 @@ lower_tex_ycbcr(const struct tu_pipeline_layout *layout, } static bool -lower_tex(nir_builder *b, nir_tex_instr *tex, +lower_tex(nir_builder *b, nir_tex_instr *tex, struct tu_device *dev, struct tu_shader *shader, const struct tu_pipeline_layout *layout) { lower_tex_ycbcr(layout, b, tex); @@ -541,7 +543,7 @@ lower_tex(nir_builder *b, nir_tex_instr *tex, int sampler_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref); if (sampler_src_idx >= 0) { nir_deref_instr *deref = nir_src_as_deref(tex->src[sampler_src_idx].src); - nir_ssa_def *bindless = build_bindless(b, deref, true, shader, layout); + nir_ssa_def *bindless = build_bindless(dev, b, deref, true, shader, layout); nir_instr_rewrite_src(&tex->instr, &tex->src[sampler_src_idx].src, nir_src_for_ssa(bindless)); tex->src[sampler_src_idx].src_type = nir_tex_src_sampler_handle; @@ -550,7 +552,7 @@ lower_tex(nir_builder *b, nir_tex_instr *tex, int tex_src_idx = nir_tex_instr_src_index(tex, nir_tex_src_texture_deref); if (tex_src_idx >= 0) { nir_deref_instr *deref = nir_src_as_deref(tex->src[tex_src_idx].src); - nir_ssa_def *bindless = build_bindless(b, deref, false, shader, layout); + nir_ssa_def *bindless = build_bindless(dev, b, deref, false, shader, layout); nir_instr_rewrite_src(&tex->instr, &tex->src[tex_src_idx].src, nir_src_for_ssa(bindless)); tex->src[tex_src_idx].src_type = nir_tex_src_texture_handle; @@ -576,7 +578,7 @@ lower_instr(nir_builder *b, nir_instr *instr, void *cb_data) b->cursor = nir_before_instr(instr); switch (instr->type) { case nir_instr_type_tex: - return lower_tex(b, nir_instr_as_tex(instr), params->shader, params->layout); + return lower_tex(b, nir_instr_as_tex(instr), params->dev, params->shader, params->layout); case nir_instr_type_intrinsic: return lower_intrinsic(b, nir_instr_as_intrinsic(instr), params->dev, params->shader, params->layout); default: