当前位置: 首页 > 知识库问答 >
问题:

Vulkan计算着色器从image2D结果复制到下一帧的sampler2D

郑曜灿
2023-03-14

我试图用计算着色器对图像进行后期处理,并在当前计算中使用前一帧的颜色。我需要sampler2D来访问插值操作,尽管在下面的简单示例中似乎不是这样。我使用以下着色器更新当前输入输出“颜色”:

#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;
    // Frame 2 and onwards
    vec3 prev_color = texture(previous_color, xy_float).xyz;
    
    vec3 mixed_color = mix(sample_color, prev_color, 0.5);
    imageStore(color, vec4(mixed_color, 1.0f), xy_int);
}

调度后:

  1. 我使用管道屏障转换图像布局
  2. 使用vkCmdCopyImage将“颜色”图像复制到“上一个颜色”
  3. 转换回布局,以便在下一帧中使用

所有这些(包括计算着色器调度)都在一个命令缓冲区中完成。然而,在使用Renderdoc检查“previous_color”作为输入纹理时,我发现该纹理始终是黑色的,并且不存在。我还可以检查复制事件,这表明复制成功,并且“previous_color”图像的颜色正确。

我是不是搞错了?为什么下一帧纹理不可用?我的设置没有任何Vulkan验证层错误。

我假设我的同步出现了问题,但无法找出原因。我不使用排队族。更具体地说,我的布局转换是:

vkBeginCommandBuffer()

...

vkCmdDispatch() // the example_shader.comp above

...


color ImageMemoryBarrier with:
access flags:       VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT -> VK_ACCESS_TRANSFER_READ_BIT
layout transition:  VK_IMAGE_LAYOUT_GENERAL -> VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
stage:              VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT -> VK_PIPELINE_STAGE_TRANSFER_BIT

prev_color ImageMemoryBarrier with:
access flags:       VK_ACCESS_SHADER_READ_BIT -> VK_ACCESS_TRANSFER_WRITE_BIT
layout transition:  VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL -> VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
stage:              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 with:
access flags:       VK_ACCESS_TRANSFER_WRITE_BIT -> VK_ACCESS_SHADER_READ_BIT
layout transition:  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL -> VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
stage:              VK_PIPELINE_STAGE_TRANSFER_BIT -> VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT

color ImageMemoryBarrier with:
access flags:       VK_ACCESS_TRANSFER_READ_BIT -> VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT
layout transition:  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL -> VK_IMAGE_LAYOUT_GENERAL
stage:              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;

编辑:我没意识到“以前的颜色”现在真的可用了!除了Renderdoc中的一个错误之外,实际上可能没有任何错误,即没有将上一个_颜色显示为黑色作为输入纹理。这不需要进一步的探索,因为我确实改变了壁垒,使之比以前更加严格。我只是在用renderdoc寻找,没有意识到最终结果就是我已经在寻找的。

共有1个答案

慕容齐智
2023-03-14

确认同步问题的最佳方法是临时添加更多同步以强制串行执行。如果它开始工作,那就是同步问题。

// Issue earlier work

vkQueueSubmit()
vkQueueWaitIdle()

// Issue copy image

vkQueueSubmit()
vkQueueWaitIdle()

// Issue follow on work

如果仍然是黑色,那就不是同步问题。

 类似资料:
  • 我已经创建了一个正投影相机,用于我简单的OpenGL2D渲染器。目前我有一个问题,当我在着色器上计算它们时,计算的归一化设备坐标是错误的,但当我在cpu上计算它们时,我得到了想要的结果。 我使用以下公式创建了一个正投影矩阵: 其中右=1280,左=0,上=0,下=720,zFar=1.0和zNear=-1.0。 因此,如果我使用以下顶点位置创建一个矩形: 它应该导致一个矩形填充整个屏幕。 为了计算

  • 我一直在尝试渲染到一个FBO,并将两个FBO渲染到屏幕上,但在合并两个FBO时进行深度测试失败。我尝试使用计算着色器合并纹理,但无法读取深度纹理的值(所有值都是值1,但渲染到FBO时深度测试有效)。有人知道我做错了什么,或者知道其他方法来合并两个FBO吗? 以下是我创建FBO的方式: 以下是我向FBO渲染的方式: 我尝试用glBindTexture绑定纹理(所有值均为1): 计算着色器: 我已尝试

  • 我已经成功地完成了在Amazon EMR上的工作,现在我想将结果从复制到,但是我遇到了一些问题 这是代码(--steps) 这是日志:

  • 但是由于某种原因,当我运行我的程序时,它似乎没有完全接受输入,并且给我一个错误的答案,当按下按钮时,它给我的答案是179.0的男性和169.0的女性。 我看了一遍又一遍,似乎无法找出这个逻辑错误。这是我的代码。

  • 注意 最后一次构建:2014年1月20日下午18:00。 这章的源代码能够在assetts folder找到。 http://labs.qt.nokia.com/2012/02/02/qt-graphical-effects-in-qt-labs/ http://labs.qt.nokia.com/2011/05/03/qml-shadereffectitem-on-qgraphicsview/

  • 我是机器人和爪哇的新手。我已经构建了一个计算器,当我输入3个输入时,我需要它来自动显示结果,但我不知道该怎么做。 我将multiply添加到了一个文本视图(通过属性onclick),它可以工作,但我希望它能在textview中自动显示。