You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 06:27:03