Vulkan中计算着色器image2D拷贝到sampler2D后读取为黑如何处理?
Vulkan计算着色器帧间数据复用Renderdoc显示异常问题
我正在尝试用计算着色器做图像后处理,需要在当前帧计算中使用上一帧的颜色数据,同时需要sampler2D实现插值操作(该需求在下方简单示例中表现不明显)。我通过如下着色器更新当前输入输出的color图像:
#version 460 #extension GL_GOOGLE_include_directive : enable layout (local_size_x = 16, local_size_y = 16) in; layout(binding = 0, set = 0, rgba32f) uniform image2D color; layout(binding = 1, set = 0) uniform sampler2D previous_color; void main() { ivec2 xy_int = ivec2(gl_GlobalInvocationID.xy); ivec2 size = imageSize(color); vec2 xy_float = vec2(gl_GlobalInvocationID.x / size.x, gl_GlobalInvocationID.y / size.y); vec3 sample_color = imageLoad(color, xy_int).xyz; // 第2帧及之后运行 vec3 prev_color = texture(previous_color, xy_float).xyz; vec3 mixed_color = mix(sample_color, prev_color, 0.5); imageStore(color, xy_int, vec4(mixed_color, 1.0f)); }
调度着色器后我执行了以下操作:
- 通过管线屏障转换图像布局
- 调用
vkCmdCopyImage将color图像拷贝到previous_color - 转换回适配布局,为下一帧使用做准备
上述所有操作(包括计算着色器调度)都在同一个命令缓冲中执行。但我通过Renderdoc查看作为输入纹理的previous_color时,发现该纹理始终为纯黑,仿佛不存在;但查看拷贝事件却显示拷贝成功,previous_color图像存储了正确颜色数据。
我的拷贝方案是否存在问题?为什么拷贝得到的图像下一帧无法作为纹理使用?我的部署没有触发任何Vulkan验证层报错。我推测是同步逻辑出错,但始终无法定位问题,我没有使用队列家族,布局转换流程具体如下:
vkBeginCommandBuffer() ... vkCmdDispatch() // 上述示例的example_shader.comp ... color ImageMemoryBarrier参数: 访问标志: VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT -> VK_ACCESS_TRANSFER_READ_BIT 布局转换: VK_IMAGE_LAYOUT_GENERAL -> VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL 阶段: VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT -> VK_PIPELINE_STAGE_TRANSFER_BIT prev_color ImageMemoryBarrier参数: 访问标志: VK_ACCESS_SHADER_READ_BIT -> VK_ACCESS_TRANSFER_WRITE_BIT 布局转换: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL -> VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL 阶段: VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT -> VK_PIPELINE_STAGE_TRANSFER_BIT vkCmdCopyImage(color, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, previous_color, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) prev_color ImageMemoryBarrier参数: 访问标志: VK_ACCESS_TRANSFER_WRITE_BIT -> VK_ACCESS_SHADER_READ_BIT 布局转换: VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL -> VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL 阶段: VK_PIPELINE_STAGE_TRANSFER_BIT -> VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT color ImageMemoryBarrier参数: 访问标志: VK_ACCESS_TRANSFER_READ_BIT -> VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT 布局转换: VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL -> VK_IMAGE_LAYOUT_GENERAL 阶段: VK_PIPELINE_STAGE_TRANSFER_BIT -> VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT ... vkEndCommandBuffer()
我使用的Sampler2D创建参数如下:
VkSamplerCreateInfo samplerInfo{}; samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; samplerInfo.magFilter = VK_FILTER_LINEAR; samplerInfo.minFilter = VK_FILTER_LINEAR; samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; samplerInfo.anisotropyEnable = VK_FALSE; samplerInfo.maxAnisotropy = 0; samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; samplerInfo.unnormalizedCoordinates = VK_FALSE; samplerInfo.compareEnable = VK_FALSE; samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; samplerInfo.mipLodBias = 0.0f; samplerInfo.minLod = 0.0f; samplerInfo.maxLod = 0.0f;
编辑补充:我后续发现
previous_color实际可以正常使用!除了Renderdoc存在bug、将作为输入纹理的previous_color显示为黑色之外,我的代码不存在其他问题。我之前将屏障规则调整得更严格后功能就已正常,此前我只关注Renderdoc的显示,没注意到最终运行结果已经符合预期。
内容的提问来源于stack exchange,提问作者Toothery
相关产品推荐
相关产品推荐

