Vulkan中图像兼作颜色与输入附件时的异常行为排查
Vulkan子通道自依赖下subpassLoad读取异常问题
我正尝试在片段着色器中实现颜色混合,将alpha通道用作后续绘制调用的动态模板缓冲区。具体做法是把交换链图像同时附加为输入附件和颜色附件,并在绘制调用间设置了子通道自依赖及管线屏障。
渲染通道依赖配置
const dependencies = [_]vk.SubpassDependency{ .{ .src_subpass = vk.SUBPASS_EXTERNAL, .dst_subpass = 0, .src_stage_mask = .{ .color_attachment_output_bit = true }, .dst_stage_mask = .{ .color_attachment_output_bit = true }, .src_access_mask = .{}, .dst_access_mask = .{ .color_attachment_write_bit = true }, // .dependency_flags = .{ .by_region_bit = true }, }, .{ .src_subpass = 0, .dst_subpass = 0, .src_stage_mask = .{ .color_attachment_output_bit = true }, .dst_stage_mask = .{ .fragment_shader_bit = true, .color_attachment_output_bit = true }, .src_access_mask = .{ .color_attachment_write_bit = true }, .dst_access_mask = .{ .input_attachment_read_bit = true, .color_attachment_write_bit = true }, .dependency_flags = .{ .by_region_bit = true }, } };
子通道描述
const subpasses = [_]vk.SubpassDescription{.{ .pipeline_bind_point = .graphics, .input_attachment_count = 1, .p_input_attachments = &.{.{ .attachment = 0, .layout = .general }}, .color_attachment_count = 1, .p_color_attachments = &.{.{ .attachment = 0, .layout = .general }}, }};
管线屏障代码
dev.cmdPipelineBarrier( cb, .{ .color_attachment_output_bit = true }, .{ .fragment_shader_bit = true, .color_attachment_output_bit = true }, .{ .by_region_bit = true }, 0, undefined, 0, undefined, 1, &.{.{ .src_access_mask = .{ .color_attachment_write_bit = true }, .dst_access_mask = .{ .input_attachment_read_bit = true, .color_attachment_write_bit = true }, .old_layout = .general, .new_layout = .general, .src_queue_family_index = vk.QUEUE_FAMILY_IGNORED, .dst_queue_family_index = vk.QUEUE_FAMILY_IGNORED, .image = image, .subresource_range = .{ .aspect_mask = .{ .color_bit = true }, .base_mip_level = 0, .level_count = 1, .base_array_layer = 0, .layer_count = 1, }, }}, );
其中image为交换链图像,我在绘制调用之间及首次绘制前调用该屏障,以与渲染通道清除操作同步。
异常现象
调试片段着色器时发现,subpassLoad()竟返回绘制后的最终颜色(仿佛“预知未来”):
- 首次绘制前清除操作将像素设为(1,1,1,1),但
subpassLoad()返回(1,1,1,0)(绘制后的值) - 第二次绘制时,
subpassLoad()读取到本次绘制后的结果,导致输出不符合预期
已尝试的排查手段
- 将绘制调用拆分到不同渲染通道实例
- 修改屏障参数(最初版本的dst_access_mask不含
.color_attachment_write_bit) - 在不同Mesa驱动设备测试(Intel集成显卡、AMD独立显卡)
Vulkan验证层(核心、同步、GPUAV)未报错,RenderDoc捕获中像素历史的“Tex Before”值与subpassLoad()返回值不符。
内容的提问来源于stack exchange,提问作者Jim Morrison
相关产品推荐
相关产品推荐

