From 97f1aeb84ca62bd00dac081cd5258be67cc4e3bf Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 8 Aug 2025 08:08:58 +0200 Subject: [PATCH] Vulkan: Remove support for render passes Vulkan 1.0 render passes have been replaced by dynamic rendering in 1.2. Blender Vulkan backend was implemented with dynamic rendering in mind. All our supported platforms support dynamic rendering. Render pass support was added to try to work around an issue with legacy drivers. However these drivers also fail with render passes. Using render passes had several limitations (blending and some workbench features were not supported). As no GPU uses it and it is quite some code to support it is better to remove it. Pull Request: https://projects.blender.org/blender/blender/pulls/144149 --- intern/ghost/intern/GHOST_ContextVK.cc | 6 +- .../draw/engines/workbench/workbench_state.cc | 9 - source/blender/gpu/GPU_capabilities.hh | 2 - source/blender/gpu/intern/gpu_capabilities.cc | 5 - .../gpu/intern/gpu_capabilities_private.hh | 3 - .../nodes/vk_begin_rendering_node.hh | 53 ++-- .../nodes/vk_end_rendering_node.hh | 15 +- .../tests/vk_render_graph_test_render.cc | 5 +- .../tests/vk_render_graph_test_scheduler.cc | 5 +- .../tests/vk_render_graph_test_types.hh | 19 +- .../render_graph/vk_command_buffer_wrapper.cc | 1 - .../render_graph/vk_resource_state_tracker.hh | 1 - source/blender/gpu/vulkan/vk_backend.cc | 10 +- .../blender/gpu/vulkan/vk_descriptor_set.cc | 48 +--- source/blender/gpu/vulkan/vk_device.cc | 3 - source/blender/gpu/vulkan/vk_device.hh | 6 - source/blender/gpu/vulkan/vk_framebuffer.cc | 258 +----------------- source/blender/gpu/vulkan/vk_framebuffer.hh | 12 - source/blender/gpu/vulkan/vk_pipeline_pool.cc | 25 +- source/blender/gpu/vulkan/vk_pipeline_pool.hh | 5 +- source/blender/gpu/vulkan/vk_shader.cc | 53 +--- .../blender/gpu/vulkan/vk_shader_interface.cc | 1 - source/blender/gpu/vulkan/vk_texture.cc | 3 +- 23 files changed, 62 insertions(+), 486 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextVK.cc b/intern/ghost/intern/GHOST_ContextVK.cc index 4bcd5b6b796..e029f71c527 100644 --- a/intern/ghost/intern/GHOST_ContextVK.cc +++ b/intern/ghost/intern/GHOST_ContextVK.cc @@ -329,9 +329,7 @@ class GHOST_DeviceVK { VkPhysicalDeviceDynamicRenderingFeatures dynamic_rendering = {}; dynamic_rendering.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES; dynamic_rendering.dynamicRendering = VK_TRUE; - if (extension_enabled(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME)) { - feature_struct_ptr.push_back(&dynamic_rendering); - } + feature_struct_ptr.push_back(&dynamic_rendering); VkPhysicalDeviceDynamicRenderingUnusedAttachmentsFeaturesEXT dynamic_rendering_unused_attachments = {}; @@ -1241,7 +1239,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext() #else required_device_extensions.push_back(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME); #endif - optional_device_extensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); + required_device_extensions.push_back(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); optional_device_extensions.push_back(VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME); optional_device_extensions.push_back(VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_EXTENSION_NAME); optional_device_extensions.push_back(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME); diff --git a/source/blender/draw/engines/workbench/workbench_state.cc b/source/blender/draw/engines/workbench/workbench_state.cc index d1088b64a3a..94c0bda516e 100644 --- a/source/blender/draw/engines/workbench/workbench_state.cc +++ b/source/blender/draw/engines/workbench/workbench_state.cc @@ -246,15 +246,6 @@ void SceneState::init(const DRWContext *context, shading.flag & V3D_SHADING_DEPTH_OF_FIELD; draw_object_id = (draw_outline || draw_curvature); - - /* Legacy Vulkan devices don't support gaps between color attachments. We disable outline - * drawing on these devices. There are situations outline drawing can just work, but we need to - * be sure transparency depth drawing isn't used. */ - /* TODO(jbakker): Add support on legacy Vulkan devices by introducing specific depth shaders. */ - if ((shading.type < OB_SOLID || xray_mode) && GPU_vulkan_render_pass_workaround()) { - draw_object_id = false; - draw_outline = false; - } }; static const CustomData *get_loop_custom_data(const Mesh *mesh) diff --git a/source/blender/gpu/GPU_capabilities.hh b/source/blender/gpu/GPU_capabilities.hh index b63f3c54ea6..e459db9b4ec 100644 --- a/source/blender/gpu/GPU_capabilities.hh +++ b/source/blender/gpu/GPU_capabilities.hh @@ -53,8 +53,6 @@ bool GPU_use_main_context_workaround(); bool GPU_use_hq_normals_workaround(); bool GPU_crappy_amd_driver(); -bool GPU_vulkan_render_pass_workaround(); - bool GPU_geometry_shader_support(); bool GPU_shader_draw_parameters_support(); bool GPU_hdr_support(); diff --git a/source/blender/gpu/intern/gpu_capabilities.cc b/source/blender/gpu/intern/gpu_capabilities.cc index df09a9a9f9b..cb941b7491f 100644 --- a/source/blender/gpu/intern/gpu_capabilities.cc +++ b/source/blender/gpu/intern/gpu_capabilities.cc @@ -172,11 +172,6 @@ bool GPU_node_link_instancing_workaround() return GCaps.node_link_instancing_workaround; } -bool GPU_vulkan_render_pass_workaround() -{ - return GCaps.render_pass_workaround; -} - bool GPU_geometry_shader_support() { return GCaps.geometry_shader_support; diff --git a/source/blender/gpu/intern/gpu_capabilities_private.hh b/source/blender/gpu/intern/gpu_capabilities_private.hh index 683b742d723..a335d71aabe 100644 --- a/source/blender/gpu/intern/gpu_capabilities_private.hh +++ b/source/blender/gpu/intern/gpu_capabilities_private.hh @@ -64,9 +64,6 @@ struct GPUCapabilities { bool use_subprocess_shader_compilations = false; - /* Vulkan related workarounds. */ - bool render_pass_workaround = false; - /* Metal related workarounds. */ /* Minimum per-vertex stride in bytes (For a vertex buffer). */ int minimum_per_vertex_stride = 1; diff --git a/source/blender/gpu/vulkan/render_graph/nodes/vk_begin_rendering_node.hh b/source/blender/gpu/vulkan/render_graph/nodes/vk_begin_rendering_node.hh index 87a0ef0566c..548c44919a6 100644 --- a/source/blender/gpu/vulkan/render_graph/nodes/vk_begin_rendering_node.hh +++ b/source/blender/gpu/vulkan/render_graph/nodes/vk_begin_rendering_node.hh @@ -21,7 +21,6 @@ struct VKBeginRenderingData { VkRenderingAttachmentInfo depth_attachment; VkRenderingAttachmentInfo stencil_attachment; VkRenderingInfoKHR vk_rendering_info; - VkRenderPassBeginInfo vk_render_pass_begin_info; }; struct VKBeginRenderingCreateInfo { @@ -53,25 +52,19 @@ class VKBeginRenderingNode : public VKNodeInfo void set_node_data(Node &node, Storage &storage, const CreateInfo &create_info) { - const bool use_render_pass = create_info.node_data.vk_render_pass_begin_info.renderPass != - VK_NULL_HANDLE; - UNUSED_VARS_NDEBUG(use_render_pass); - BLI_assert_msg(use_render_pass || - ELEM(create_info.node_data.vk_rendering_info.pColorAttachments, - nullptr, - create_info.node_data.color_attachments), + BLI_assert_msg(ELEM(create_info.node_data.vk_rendering_info.pColorAttachments, + nullptr, + create_info.node_data.color_attachments), "When create_info.node_data.vk_rendering_info.pColorAttachments points to " "something, it should point to create_info.node_data.color_attachments."); - BLI_assert_msg(use_render_pass || - ELEM(create_info.node_data.vk_rendering_info.pDepthAttachment, - nullptr, - &create_info.node_data.depth_attachment), + BLI_assert_msg(ELEM(create_info.node_data.vk_rendering_info.pDepthAttachment, + nullptr, + &create_info.node_data.depth_attachment), "When create_info.node_data.vk_rendering_info.pDepthAttachment points to " "something, it should point to create_info.node_data.depth_attachment."); - BLI_assert_msg(use_render_pass || - ELEM(create_info.node_data.vk_rendering_info.pStencilAttachment, - nullptr, - &create_info.node_data.stencil_attachment), + BLI_assert_msg(ELEM(create_info.node_data.vk_rendering_info.pStencilAttachment, + nullptr, + &create_info.node_data.stencil_attachment), "When create_info.node_data.vk_rendering_info.pStencilAttachment points to " "something, it should point to create_info.node_data.stencil_attachment."); node.storage_index = storage.begin_rendering.append_and_get_index(create_info.node_data); @@ -97,25 +90,19 @@ class VKBeginRenderingNode : public VKNodeInfo &log, - bool use_dynamic_rendering_ = true, - bool use_dynamic_rendering_local_read_ = true) + CommandBufferLog(Vector &log, bool use_dynamic_rendering_local_read_ = true) : log_(log) { - use_dynamic_rendering = use_dynamic_rendering_; use_dynamic_rendering_local_read = use_dynamic_rendering_local_read_; } virtual ~CommandBufferLog() {} @@ -497,11 +494,9 @@ class VKRenderGraphTest : public ::testing::Test { public: VKRenderGraphTest() { - resources.use_dynamic_rendering = use_dynamic_rendering; resources.use_dynamic_rendering_local_read = use_dynamic_rendering_local_read; render_graph = std::make_unique(resources); - command_buffer = std::make_unique( - log, use_dynamic_rendering, use_dynamic_rendering_local_read); + command_buffer = std::make_unique(log, use_dynamic_rendering_local_read); } protected: @@ -509,21 +504,17 @@ class VKRenderGraphTest : public ::testing::Test { VKResourceStateTracker resources; std::unique_ptr render_graph; std::unique_ptr command_buffer; - bool use_dynamic_rendering = true; bool use_dynamic_rendering_local_read = true; }; -class VKRenderGraphTest_P : public ::testing::TestWithParam> { +class VKRenderGraphTest_P : public ::testing::TestWithParam> { public: VKRenderGraphTest_P() { - use_dynamic_rendering = std::get<0>(GetParam()); - use_dynamic_rendering_local_read = std::get<1>(GetParam()); - resources.use_dynamic_rendering = use_dynamic_rendering; + use_dynamic_rendering_local_read = std::get<0>(GetParam()); resources.use_dynamic_rendering_local_read = use_dynamic_rendering_local_read; render_graph = std::make_unique(resources); - command_buffer = std::make_unique( - log, use_dynamic_rendering, use_dynamic_rendering_local_read); + command_buffer = std::make_unique(log, use_dynamic_rendering_local_read); } protected: diff --git a/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.cc b/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.cc index 9c61045490d..1d06c3b6d78 100644 --- a/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.cc +++ b/source/blender/gpu/vulkan/render_graph/vk_command_buffer_wrapper.cc @@ -15,7 +15,6 @@ VKCommandBufferWrapper::VKCommandBufferWrapper(VkCommandBuffer vk_command_buffer const VKExtensions &extensions) : vk_command_buffer_(vk_command_buffer) { - use_dynamic_rendering = extensions.dynamic_rendering; use_dynamic_rendering_local_read = extensions.dynamic_rendering_local_read; } diff --git a/source/blender/gpu/vulkan/render_graph/vk_resource_state_tracker.hh b/source/blender/gpu/vulkan/render_graph/vk_resource_state_tracker.hh index 7278d331c35..51e0d1a7734 100644 --- a/source/blender/gpu/vulkan/render_graph/vk_resource_state_tracker.hh +++ b/source/blender/gpu/vulkan/render_graph/vk_resource_state_tracker.hh @@ -256,7 +256,6 @@ class VKResourceStateTracker { return resources_.lookup(resource_handle).type; } - bool use_dynamic_rendering = true; bool use_dynamic_rendering_local_read = true; void debug_print() const; diff --git a/source/blender/gpu/vulkan/vk_backend.cc b/source/blender/gpu/vulkan/vk_backend.cc index b18d4271060..7b46b50af01 100644 --- a/source/blender/gpu/vulkan/vk_backend.cc +++ b/source/blender/gpu/vulkan/vk_backend.cc @@ -175,6 +175,9 @@ static Vector missing_capabilities_get(VkPhysicalDevice vk_physic if (!extensions.contains(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) { missing_capabilities.append(VK_KHR_SWAPCHAIN_EXTENSION_NAME); } + if (!extensions.contains(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME)) { + missing_capabilities.append(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); + } #ifndef __APPLE__ /* Metal doesn't support provoking vertex. */ if (!extensions.contains(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME)) { @@ -403,13 +406,10 @@ void VKBackend::detect_workarounds(VKDevice &device) extensions.shader_output_layer = false; extensions.shader_output_viewport_index = false; extensions.fragment_shader_barycentric = false; - extensions.dynamic_rendering = false; extensions.dynamic_rendering_local_read = false; extensions.dynamic_rendering_unused_attachments = false; extensions.descriptor_buffer = false; - GCaps.render_pass_workaround = true; - device.workarounds_ = workarounds; device.extensions_ = extensions; return; @@ -421,8 +421,6 @@ void VKBackend::detect_workarounds(VKDevice &device) device.physical_device_vulkan_12_features_get().shaderOutputViewportIndex; extensions.fragment_shader_barycentric = device.supports_extension( VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME); - extensions.dynamic_rendering = device.supports_extension( - VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); extensions.dynamic_rendering_local_read = device.supports_extension( VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME); extensions.dynamic_rendering_unused_attachments = device.supports_extension( @@ -491,8 +489,6 @@ void VKBackend::detect_workarounds(VKDevice &device) workarounds.vertex_formats.r8g8b8 = (format_properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0; - GCaps.render_pass_workaround = !extensions.dynamic_rendering; - #ifdef __APPLE__ /* Due to a limitation in MoltenVK, attachments should be sequential even when using * dynamic rendering. MoltenVK internally uses render passes to simulate dynamic rendering and diff --git a/source/blender/gpu/vulkan/vk_descriptor_set.cc b/source/blender/gpu/vulkan/vk_descriptor_set.cc index b50ecbda48f..c471d72ae77 100644 --- a/source/blender/gpu/vulkan/vk_descriptor_set.cc +++ b/source/blender/gpu/vulkan/vk_descriptor_set.cc @@ -167,7 +167,6 @@ void VKDescriptorSetUpdator::bind_input_attachment_resource( } } else { - bool supports_dynamic_rendering = device.extensions_get().dynamic_rendering; const BindSpaceTextures::Elem *elem_ptr = state_manager.textures_.get( resource_binding.binding); if (!elem_ptr) { @@ -179,39 +178,20 @@ void VKDescriptorSetUpdator::bind_input_attachment_resource( VKTexture *texture = static_cast(elem.resource); BLI_assert(texture); BLI_assert(elem.resource_type == BindSpaceTextures::Type::Texture); - if (supports_dynamic_rendering) { - const VKSampler &sampler = device.samplers().get(elem.sampler); - bind_image( - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - sampler.vk_handle(), - texture->image_view_get(resource_binding.arrayed, VKImageViewFlags::DEFAULT).vk_handle(), - VK_IMAGE_LAYOUT_GENERAL, - resource_binding.location); - VkImage vk_image = texture->vk_image_handle(); - if (vk_image != VK_NULL_HANDLE) { - access_info.images.append({vk_image, - resource_binding.access_mask, - to_vk_image_aspect_flag_bits(texture->device_format_get()), - 0, - VK_REMAINING_ARRAY_LAYERS}); - } - } - else { - /* Fall back to render-passes / sub-passes. */ - bind_image(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, - VK_NULL_HANDLE, - texture->image_view_get(resource_binding.arrayed, VKImageViewFlags::NO_SWIZZLING) - .vk_handle(), - VK_IMAGE_LAYOUT_GENERAL, - resource_binding.location); - VkImage vk_image = texture->vk_image_handle(); - if (vk_image != VK_NULL_HANDLE) { - access_info.images.append({vk_image, - resource_binding.access_mask, - to_vk_image_aspect_flag_bits(texture->device_format_get()), - 0, - VK_REMAINING_ARRAY_LAYERS}); - } + const VKSampler &sampler = device.samplers().get(elem.sampler); + bind_image( + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + sampler.vk_handle(), + texture->image_view_get(resource_binding.arrayed, VKImageViewFlags::DEFAULT).vk_handle(), + VK_IMAGE_LAYOUT_GENERAL, + resource_binding.location); + VkImage vk_image = texture->vk_image_handle(); + if (vk_image != VK_NULL_HANDLE) { + access_info.images.append({vk_image, + resource_binding.access_mask, + to_vk_image_aspect_flag_bits(texture->device_format_get()), + 0, + VK_REMAINING_ARRAY_LAYERS}); } } } diff --git a/source/blender/gpu/vulkan/vk_device.cc b/source/blender/gpu/vulkan/vk_device.cc index d0ae8abb1a9..b65714f51ad 100644 --- a/source/blender/gpu/vulkan/vk_device.cc +++ b/source/blender/gpu/vulkan/vk_device.cc @@ -39,7 +39,6 @@ void VKExtensions::log() const " - [%c] fragment shader barycentric\n" "Device extensions\n" " - [%c] descriptor buffer\n" - " - [%c] dynamic rendering\n" " - [%c] dynamic rendering local read\n" " - [%c] dynamic rendering unused attachments\n" " - [%c] external memory\n" @@ -48,7 +47,6 @@ void VKExtensions::log() const shader_output_layer ? 'X' : ' ', fragment_shader_barycentric ? 'X' : ' ', descriptor_buffer ? 'X' : ' ', - dynamic_rendering ? 'X' : ' ', dynamic_rendering_local_read ? 'X' : ' ', dynamic_rendering_unused_attachments ? 'X' : ' ', external_memory ? 'X' : ' ', @@ -139,7 +137,6 @@ void VKDevice::init(void *ghost_context) debug::object_label(vk_queue_, "GenericQueue"); init_glsl_patch(); - resources.use_dynamic_rendering = extensions_.dynamic_rendering; resources.use_dynamic_rendering_local_read = extensions_.dynamic_rendering_local_read; orphaned_data.timeline_ = 0; diff --git a/source/blender/gpu/vulkan/vk_device.hh b/source/blender/gpu/vulkan/vk_device.hh index 089f7c0b448..c29101e8ea6 100644 --- a/source/blender/gpu/vulkan/vk_device.hh +++ b/source/blender/gpu/vulkan/vk_device.hh @@ -39,12 +39,6 @@ struct VKExtensions { * VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR::fragmentShaderBarycentric. */ bool fragment_shader_barycentric = false; - /** - * Does the device support VK_KHR_dynamic_rendering enabled. - * - * We should assume that this is always supported. Option will be removed later in 5.0. - */ - bool dynamic_rendering = false; /** * Does the device support VK_KHR_dynamic_rendering_local_read enabled. diff --git a/source/blender/gpu/vulkan/vk_framebuffer.cc b/source/blender/gpu/vulkan/vk_framebuffer.cc index 683f5e1f90c..d6826128e22 100644 --- a/source/blender/gpu/vulkan/vk_framebuffer.cc +++ b/source/blender/gpu/vulkan/vk_framebuffer.cc @@ -42,20 +42,6 @@ VKFrameBuffer::~VKFrameBuffer() if (context && context->active_framebuffer_get() == this) { context->deactivate_framebuffer(); } - render_pass_free(); -} - -void VKFrameBuffer::render_pass_free() -{ - VKDiscardPool &discard_pool = VKDiscardPool::discard_pool_get(); - if (vk_framebuffer != VK_NULL_HANDLE) { - discard_pool.discard_framebuffer(vk_framebuffer); - vk_framebuffer = VK_NULL_HANDLE; - } - if (vk_render_pass != VK_NULL_HANDLE) { - discard_pool.discard_render_pass(vk_render_pass); - vk_render_pass = VK_NULL_HANDLE; - } } /** \} */ @@ -563,237 +549,6 @@ void VKFrameBuffer::rendering_reset() is_rendering_ = false; } -void VKFrameBuffer::rendering_ensure_render_pass(VKContext &context) -{ - render_pass_free(); - - depth_attachment_format_ = VK_FORMAT_UNDEFINED; - stencil_attachment_format_ = VK_FORMAT_UNDEFINED; - - render_graph::VKResourceAccessInfo access_info; - Vector vk_attachment_descriptions; - Vector color_attachments; - Vector input_attachments; - Vector vk_image_views; - - uint32_t max_layer_count = 1; - - /* Color attachments */ - VkAttachmentReference depth_attachment_reference = {0u}; - for (int color_attachment_index : - IndexRange(GPU_FB_COLOR_ATTACHMENT0, GPU_FB_MAX_COLOR_ATTACHMENT)) - { - const GPUAttachment &attachment = attachments_[color_attachment_index]; - if (attachment.tex == nullptr) { - continue; - } - VKTexture &color_texture = *unwrap(unwrap(attachment.tex)); - BLI_assert_msg(color_texture.usage_get() & GPU_TEXTURE_USAGE_ATTACHMENT, - "Texture is used as an attachment, but doesn't have the " - "GPU_TEXTURE_USAGE_ATTACHMENT flag."); - GPUAttachmentState attachment_state = attachment_states_[color_attachment_index]; - uint32_t layer_base = max_ii(attachment.layer, 0); - int layer_count = color_texture.layer_count(); - if (attachment.layer == -1 && layer_count != 1) { - max_layer_count = max_ii(max_layer_count, layer_count); - } - - VKImageViewInfo image_view_info = { - eImageViewUsage::Attachment, - IndexRange(layer_base, - layer_count != 1 ? max_ii(layer_count - layer_base, 1) : layer_count), - IndexRange(attachment.mip, 1), - {{'r', 'g', 'b', 'a'}}, - false, - srgb_ && enabled_srgb_, - VKImageViewArrayed::DONT_CARE}; - const VKImageView &image_view = color_texture.image_view_get(image_view_info); - /* TODO: Use VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL for read-only attachments. */ - VkImageLayout vk_image_layout = (attachment_state == GPU_ATTACHMENT_READ) ? - VK_IMAGE_LAYOUT_GENERAL : - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - uint32_t attachment_reference = color_attachment_index - GPU_FB_COLOR_ATTACHMENT0; - /* Depth attachment should always be right after the last color attachment. If not shaders - * cannot be reused between frame-buffers with and without depth/stencil attachment. */ - depth_attachment_reference.attachment = attachment_reference + 1; - - VkAttachmentDescription vk_attachment_description = {}; - vk_attachment_description.format = image_view.vk_format(); - vk_attachment_description.samples = VK_SAMPLE_COUNT_1_BIT; - vk_attachment_description.initialLayout = vk_image_layout; - vk_attachment_description.finalLayout = vk_image_layout; - vk_attachment_descriptions.append(std::move(vk_attachment_description)); - vk_image_views.append(image_view.vk_handle()); - - switch (attachment_state) { - case GPU_ATTACHMENT_WRITE: { - color_attachments.append({attachment_reference, vk_image_layout}); - - access_info.images.append( - {color_texture.vk_image_handle(), - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_IMAGE_ASPECT_COLOR_BIT, - layer_base}); - break; - } - - case GPU_ATTACHMENT_READ: { - input_attachments.append({attachment_reference, vk_image_layout}); - access_info.images.append({color_texture.vk_image_handle(), - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, - VK_IMAGE_ASPECT_COLOR_BIT, - layer_base}); - break; - } - - case GPU_ATTACHMENT_IGNORE: { - input_attachments.append({VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_UNDEFINED}); - break; - } - } - } - - /* Update the color attachment size attribute. This is used to generate the correct amount of - * color blend states in the graphics pipeline. */ - color_attachment_size = color_attachments.size(); - - /* Depth attachment */ - bool has_depth_attachment = false; - for (int depth_attachment_index : IndexRange(GPU_FB_DEPTH_ATTACHMENT, 2)) { - const GPUAttachment &attachment = attachments_[depth_attachment_index]; - - if (attachment.tex == nullptr) { - continue; - } - has_depth_attachment = true; - bool is_stencil_attachment = depth_attachment_index == GPU_FB_DEPTH_STENCIL_ATTACHMENT; - VKTexture &depth_texture = *unwrap(unwrap(attachment.tex)); - BLI_assert_msg(depth_texture.usage_get() & GPU_TEXTURE_USAGE_ATTACHMENT, - "Texture is used as an attachment, but doesn't have the " - "GPU_TEXTURE_USAGE_ATTACHMENT flag."); - VkImageAspectFlags depth_texture_aspect = to_vk_image_aspect_flag_bits( - depth_texture.device_format_get()); - bool is_depth_stencil_attachment = depth_texture_aspect & VK_IMAGE_ASPECT_STENCIL_BIT; - VkImageLayout vk_image_layout = is_depth_stencil_attachment ? - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL; - GPUAttachmentState attachment_state = attachment_states_[GPU_FB_DEPTH_ATTACHMENT]; - VkImageView depth_image_view = VK_NULL_HANDLE; - uint32_t layer_base = max_ii(attachment.layer, 0); - if (attachment_state == GPU_ATTACHMENT_WRITE) { - VKImageViewInfo image_view_info = {eImageViewUsage::Attachment, - IndexRange(layer_base, 1), - IndexRange(attachment.mip, 1), - {{'r', 'g', 'b', 'a'}}, - is_stencil_attachment, - false, - VKImageViewArrayed::DONT_CARE}; - depth_image_view = depth_texture.image_view_get(image_view_info).vk_handle(); - } - VkAttachmentDescription vk_attachment_description = {}; - vk_attachment_description.format = to_vk_format(depth_texture.device_format_get()); - vk_attachment_description.samples = VK_SAMPLE_COUNT_1_BIT; - vk_attachment_description.initialLayout = vk_image_layout; - vk_attachment_description.finalLayout = vk_image_layout; - vk_attachment_descriptions.append(std::move(vk_attachment_description)); - depth_attachment_reference.layout = vk_image_layout; - vk_image_views.append(depth_image_view); - access_info.images.append({depth_texture.vk_image_handle(), - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - is_stencil_attachment ? - static_cast(VK_IMAGE_ASPECT_DEPTH_BIT | - VK_IMAGE_ASPECT_STENCIL_BIT) : - static_cast(VK_IMAGE_ASPECT_DEPTH_BIT), - 0}); - - VkFormat vk_format = to_vk_format(depth_texture.device_format_get()); - depth_attachment_format_ = vk_format; - if (is_stencil_attachment) { - stencil_attachment_format_ = vk_format; - } - } - - /* Sub-pass description. */ - VkSubpassDescription vk_subpass_description = {}; - vk_subpass_description.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - vk_subpass_description.colorAttachmentCount = color_attachments.size(); - vk_subpass_description.pColorAttachments = color_attachments.data(); - vk_subpass_description.inputAttachmentCount = input_attachments.size(); - vk_subpass_description.pInputAttachments = input_attachments.data(); - if (has_depth_attachment) { - vk_subpass_description.pDepthStencilAttachment = &depth_attachment_reference; - } - - VKDevice &device = VKBackend::get().device; - /* Render-pass create info. */ - VkRenderPassCreateInfo vk_render_pass_create_info = {}; - vk_render_pass_create_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - vk_render_pass_create_info.subpassCount = 1; - vk_render_pass_create_info.pSubpasses = &vk_subpass_description; - vk_render_pass_create_info.attachmentCount = vk_attachment_descriptions.size(); - vk_render_pass_create_info.pAttachments = vk_attachment_descriptions.data(); - vkCreateRenderPass(device.vk_handle(), &vk_render_pass_create_info, nullptr, &vk_render_pass); - debug::object_label(vk_render_pass, name_); - - /* Frame buffer create info */ - VkFramebufferCreateInfo vk_framebuffer_create_info = {}; - vk_framebuffer_create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - vk_framebuffer_create_info.renderPass = vk_render_pass; - vk_framebuffer_create_info.attachmentCount = vk_image_views.size(); - vk_framebuffer_create_info.pAttachments = vk_image_views.data(); - vk_framebuffer_create_info.width = width_; - vk_framebuffer_create_info.height = height_; - vk_framebuffer_create_info.layers = max_layer_count; - vkCreateFramebuffer(device.vk_handle(), &vk_framebuffer_create_info, nullptr, &vk_framebuffer); - debug::object_label(vk_framebuffer, name_); - - /* Begin rendering */ - render_graph::VKBeginRenderingNode::CreateInfo begin_rendering(access_info); - VkRenderPassBeginInfo &begin_info = begin_rendering.node_data.vk_render_pass_begin_info; - begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - begin_info.renderPass = vk_render_pass; - begin_info.framebuffer = vk_framebuffer; - render_area_update(begin_info.renderArea); - - context.render_graph().add_node(begin_rendering); - - /* Load store operations are not supported inside a render pass. - * It requires duplicating render passes and frame-buffers to support suspend/resume rendering. - * After suspension all the graphics pipelines needs to be created using the resume handles. - * Due to command reordering it is unclear when this switch needs to be made and would require - * to double the graphics pipelines. - * - * This all adds a lot of complexity just to support clearing ops on legacy platforms. An easier - * solution is to use #vkCmdClearAttachments right after the begin rendering. - */ - if (use_explicit_load_store_) { - render_graph::VKClearAttachmentsNode::CreateInfo clear_attachments = {}; - for (int attachment_index : IndexRange(GPU_FB_MAX_ATTACHMENT)) { - GPULoadStore &load_store = load_stores[attachment_index]; - if (load_store.load_action != GPU_LOADACTION_CLEAR) { - continue; - } - - bool is_depth = attachment_index < GPU_FB_COLOR_ATTACHMENT0; - if (is_depth) { - build_clear_attachments_depth_stencil( - GPU_DEPTH_BIT, load_store.clear_value[0], 0, clear_attachments); - } - else { - build_clear_attachments_color(&load_store.clear_value, false, clear_attachments); - } - } - - if (clear_attachments.attachment_count != 0) { - render_area_update(clear_attachments.vk_clear_rect.rect); - clear_attachments.vk_clear_rect.baseArrayLayer = 0; - clear_attachments.vk_clear_rect.layerCount = 1; - context.render_graph().add_node(clear_attachments); - } - } -} - void VKFrameBuffer::rendering_ensure_dynamic_rendering(VKContext &context, const VKExtensions &extensions) { @@ -969,12 +724,7 @@ void VKFrameBuffer::rendering_ensure(VKContext &context) const VKExtensions &extensions = VKBackend::get().device.extensions_get(); is_rendering_ = true; - if (extensions.dynamic_rendering) { - rendering_ensure_dynamic_rendering(context, extensions); - } - else { - rendering_ensure_render_pass(context); - } + rendering_ensure_dynamic_rendering(context, extensions); dirty_attachments_ = false; dirty_state_ = false; } @@ -999,13 +749,7 @@ void VKFrameBuffer::rendering_end(VKContext &context) } if (is_rendering_) { - const VKExtensions &extensions = VKBackend::get().device.extensions_get(); render_graph::VKEndRenderingNode::CreateInfo end_rendering = {}; - end_rendering.vk_render_pass = VK_NULL_HANDLE; - if (!extensions.dynamic_rendering) { - BLI_assert(vk_render_pass); - end_rendering.vk_render_pass = vk_render_pass; - } context.render_graph().add_node(end_rendering); is_rendering_ = false; } diff --git a/source/blender/gpu/vulkan/vk_framebuffer.hh b/source/blender/gpu/vulkan/vk_framebuffer.hh index ad5d4ea1c16..274e838d95f 100644 --- a/source/blender/gpu/vulkan/vk_framebuffer.hh +++ b/source/blender/gpu/vulkan/vk_framebuffer.hh @@ -36,11 +36,7 @@ class VKFrameBuffer : public FrameBuffer { Array load_stores; Array attachment_states_; - /* Render pass workaround when dynamic rendering isn't supported. */ - VkFramebuffer vk_framebuffer = VK_NULL_HANDLE; - public: - VkRenderPass vk_render_pass = VK_NULL_HANDLE; uint32_t color_attachment_size = 0u; /** @@ -116,7 +112,6 @@ class VKFrameBuffer : public FrameBuffer { */ void rendering_ensure(VKContext &context); void rendering_ensure_dynamic_rendering(VKContext &context, const VKExtensions &extensions); - void rendering_ensure_render_pass(VKContext &context); /** * End the rendering on this framebuffer. @@ -139,13 +134,6 @@ class VKFrameBuffer : public FrameBuffer { int color_attachments_resource_size() const; private: - /** - * Discard both the render pass and framebuffer - * - * TODO: render pass could be reusable. - */ - void render_pass_free(); - /* Clearing attachments */ void build_clear_attachments_depth_stencil( eGPUFrameBufferBits buffers, diff --git a/source/blender/gpu/vulkan/vk_pipeline_pool.cc b/source/blender/gpu/vulkan/vk_pipeline_pool.cc index fea8643d0b9..89540dc41c6 100644 --- a/source/blender/gpu/vulkan/vk_pipeline_pool.cc +++ b/source/blender/gpu/vulkan/vk_pipeline_pool.cc @@ -565,22 +565,14 @@ VkPipeline VKPipelinePool::get_or_create_graphics_pipeline(VKGraphicsInfo &graph } /* VK_KHR_dynamic_rendering */ - if (extensions.dynamic_rendering) { - vk_pipeline_rendering_create_info_.depthAttachmentFormat = - graphics_info.fragment_out.depth_attachment_format; - vk_pipeline_rendering_create_info_.stencilAttachmentFormat = - graphics_info.fragment_out.stencil_attachment_format; - vk_pipeline_rendering_create_info_.colorAttachmentCount = - graphics_info.fragment_out.color_attachment_formats.size(); - vk_pipeline_rendering_create_info_.pColorAttachmentFormats = - graphics_info.fragment_out.color_attachment_formats.data(); - } - else { - BLI_assert(ELEM( - vk_graphics_pipeline_create_info_.pNext, &vk_pipeline_rendering_create_info_, nullptr)); - vk_graphics_pipeline_create_info_.pNext = nullptr; - vk_graphics_pipeline_create_info_.renderPass = graphics_info.fragment_out.vk_render_pass; - } + vk_pipeline_rendering_create_info_.depthAttachmentFormat = + graphics_info.fragment_out.depth_attachment_format; + vk_pipeline_rendering_create_info_.stencilAttachmentFormat = + graphics_info.fragment_out.stencil_attachment_format; + vk_pipeline_rendering_create_info_.colorAttachmentCount = + graphics_info.fragment_out.color_attachment_formats.size(); + vk_pipeline_rendering_create_info_.pColorAttachmentFormats = + graphics_info.fragment_out.color_attachment_formats.data(); /* Common values */ vk_graphics_pipeline_create_info_.layout = graphics_info.vk_pipeline_layout; @@ -610,7 +602,6 @@ VkPipeline VKPipelinePool::get_or_create_graphics_pipeline(VKGraphicsInfo &graph vk_graphics_pipeline_create_info_.stageCount = 0; vk_graphics_pipeline_create_info_.layout = VK_NULL_HANDLE; vk_graphics_pipeline_create_info_.basePipelineHandle = VK_NULL_HANDLE; - vk_graphics_pipeline_create_info_.renderPass = VK_NULL_HANDLE; for (VkPipelineShaderStageCreateInfo &info : MutableSpan(vk_pipeline_shader_stage_create_info_, 3)) { diff --git a/source/blender/gpu/vulkan/vk_pipeline_pool.hh b/source/blender/gpu/vulkan/vk_pipeline_pool.hh index d04bcfe3caa..5807cb06fcd 100644 --- a/source/blender/gpu/vulkan/vk_pipeline_pool.hh +++ b/source/blender/gpu/vulkan/vk_pipeline_pool.hh @@ -144,8 +144,6 @@ struct VKGraphicsInfo { VkFormat depth_attachment_format; VkFormat stencil_attachment_format; Vector color_attachment_formats; - /* Render pass rendering */ - VkRenderPass vk_render_pass; bool operator==(const FragmentOut &other) const { @@ -172,8 +170,7 @@ struct VKGraphicsInfo { uint64_t hash() const { - uint64_t hash = uint64_t(vk_render_pass); - hash = hash * 33 ^ uint64_t(depth_attachment_format); + uint64_t hash = uint64_t(depth_attachment_format); hash = hash * 33 ^ uint64_t(stencil_attachment_format); hash = hash * 33 ^ XXH3_64bits(color_attachment_formats.data(), color_attachment_formats.size() * sizeof(VkFormat)); diff --git a/source/blender/gpu/vulkan/vk_shader.cc b/source/blender/gpu/vulkan/vk_shader.cc index ee20564dcc4..33c33b818a0 100644 --- a/source/blender/gpu/vulkan/vk_shader.cc +++ b/source/blender/gpu/vulkan/vk_shader.cc @@ -991,7 +991,6 @@ std::string VKShader::fragment_interface_declare(const shader::ShaderCreateInfo ss << "\n/* Sub-pass Inputs. */\n"; const VKShaderInterface &interface = interface_get(); const bool use_local_read = extensions.dynamic_rendering_local_read; - const bool use_dynamic_rendering = extensions.dynamic_rendering; if (use_local_read) { uint32_t subpass_input_binding_index = 0; @@ -1029,7 +1028,7 @@ std::string VKShader::fragment_interface_declare(const shader::ShaderCreateInfo pre_main += ss_pre.str(); } } - else if (use_dynamic_rendering) { + else { for (const ShaderCreateInfo::SubpassIn &input : info.subpass_inputs_) { std::string image_name = "gpu_subpass_img_"; image_name += std::to_string(input.index); @@ -1071,57 +1070,10 @@ std::string VKShader::fragment_interface_declare(const shader::ShaderCreateInfo pre_main += ss_pre.str(); } } - else { - /* Use subpass passes input attachments when dynamic rendering isn't available. */ - for (const ShaderCreateInfo::SubpassIn &input : info.subpass_inputs_) { - using Resource = ShaderCreateInfo::Resource; - Resource res(Resource::BindType::SAMPLER, input.index); - const VKDescriptorSet::Location location = interface.descriptor_set_location(res); - - std::string image_name = "gpu_subpass_img_" + std::to_string(input.index); - - /* Declare global for input. */ - ss << to_string(input.type) << " " << input.name << ";\n"; - /* Declare subpass input. */ - ss << "layout(input_attachment_index=" << input.index << ", set=0, binding=" << location - << ") uniform "; - switch (to_component_type(input.type)) { - case Type::int_t: - ss << "isubpassInput"; - break; - case Type::uint_t: - ss << "usubpassInput"; - break; - case Type::float_t: - default: - ss << "subpassInput"; - break; - } - ss << " " << image_name << ";"; - - /* Read data from subpass input. */ - char swizzle[] = "xyzw"; - swizzle[to_component_count(input.type)] = '\0'; - std::stringstream ss_pre; - ss_pre << " " << input.name << " = subpassLoad(" << image_name << ")." << swizzle << ";\n"; - pre_main += ss_pre.str(); - } - } ss << "\n/* Outputs. */\n"; - int fragment_out_location = 0; for (const ShaderCreateInfo::FragOut &output : info.fragment_outputs_) { - /* When using dynamic rendering the attachment location doesn't change. When using render - * passes and sub-passes the location refers to the color attachment of the sub-pass. - * - * LIMITATION: dual source blending cannot be used together with sub-passes. - */ - const bool use_dual_blending = output.blend != DualBlend::NONE; - BLI_assert_msg(!(use_dual_blending && !info.subpass_inputs_.is_empty()), - "Dual source blending are not supported with subpass inputs when using render " - "passes. It can be supported, but wasn't for code readability."); - const int location = (use_dynamic_rendering || use_dual_blending) ? output.index : - fragment_out_location++; + const int location = output.index; ss << "layout(location = " << location; switch (output.blend) { case DualBlend::SRC_0: @@ -1378,7 +1330,6 @@ VkPipeline VKShader::ensure_and_get_graphics_pipeline(GPUPrimType primitive, graphics_info.fragment_shader.scissors.clear(); framebuffer.vk_render_areas_append(graphics_info.fragment_shader.scissors); - graphics_info.fragment_out.vk_render_pass = framebuffer.vk_render_pass; graphics_info.fragment_out.depth_attachment_format = framebuffer.depth_attachment_format_get(); graphics_info.fragment_out.stencil_attachment_format = framebuffer.stencil_attachment_format_get(); diff --git a/source/blender/gpu/vulkan/vk_shader_interface.cc b/source/blender/gpu/vulkan/vk_shader_interface.cc index 173dcc002f6..c7a12e0a889 100644 --- a/source/blender/gpu/vulkan/vk_shader_interface.cc +++ b/source/blender/gpu/vulkan/vk_shader_interface.cc @@ -424,7 +424,6 @@ void VKShaderInterface::init_descriptor_set_layout_info( UNUSED_VARS(index); // TODO: clean up remove negation. descriptor_set_layout_info_.bindings.append_n_times( - !extensions.dynamic_rendering ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT : !extensions.dynamic_rendering_local_read ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, info.subpass_inputs_.size()); diff --git a/source/blender/gpu/vulkan/vk_texture.cc b/source/blender/gpu/vulkan/vk_texture.cc index 66bbfca2ac2..d3e9116caca 100644 --- a/source/blender/gpu/vulkan/vk_texture.cc +++ b/source/blender/gpu/vulkan/vk_texture.cc @@ -485,7 +485,6 @@ static VkImageUsageFlags to_vk_image_usage(const eGPUTextureUsage usage, { const VKDevice &device = VKBackend::get().device; const bool supports_local_read = device.extensions_get().dynamic_rendering_local_read; - const bool supports_dynamic_rendering = device.extensions_get().dynamic_rendering; VkImageUsageFlags result = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; @@ -506,7 +505,7 @@ static VkImageUsageFlags to_vk_image_usage(const eGPUTextureUsage usage, } else { result |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - if (supports_local_read || (!supports_dynamic_rendering)) { + if (supports_local_read) { result |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; } }