从 vulkan 中的附件中读取当前样本

Read current sample from an attachment in vulkan

我有一个多重采样的全屏效果通道。 如果我从输入附件(也是多重采样的)读取。我好像只看过同一个样本。

管道示例设置:

VkPipelineMultisampleStateCreateInfo multisampling_info = {};
multisampling_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling_info.rasterizationSamples = static_cast<VkSampleCountFlagBits>(samples);
multisampling_info.sampleShadingEnable = samples > 1 ? VK_TRUE : VK_FALSE;
multisampling_info.minSampleShading = 1.0;
multisampling_info.pSampleMask = nullptr;
multisampling_info.alphaToCoverageEnable = VK_FALSE;
multisampling_info.alphaToOneEnable = VK_FALSE;

在着色器中,我使用的图像类型为:

%28 = OpTypeImage %float SubpassData 0 0 1 2 Unknown

并从坐标 (0, 0)

中读取
 %34 = OpImageRead %v4float %30 %36

似乎每个样本都会调用着色器,因为我正在正确获取 SampleId。

Spir-v 规范说:

When the Image Dim operand is SubpassData, Coordinate is relative to the current fragment location. That is, the integer value (rounded down) of the current fragment’s window-relative (x, y) coordinate is added to (u, v).

如果我理解正确的话,坐标为 (0, 0) 我应该总是得到相应的样本?

我是误会了什么还是这不可能?

这是我正在使用的完整 spirv 着色器:

               OpCapability Shader
               OpCapability InputAttachment
               OpCapability SampleRateShading
               OpMemoryModel Logical GLSL450
               OpEntryPoint Fragment %44 "main" %41 %gl_SampleID
               OpExecutionMode %44 OriginUpperLeft
               OpDecorate %_struct_3 Block
               OpMemberDecorate %_struct_3 0 Offset 0
               OpDecorate %gl_SampleID BuiltIn SampleId
               OpDecorate %32 DescriptorSet 0
               OpDecorate %32 Binding 0
               OpDecorate %32 InputAttachmentIndex 0
               OpDecorate %41 Location 0
        %int = OpTypeInt 32 1
  %_struct_3 = OpTypeStruct %int
%_ptr_PushConstant__struct_3 = OpTypePointer PushConstant %_struct_3
          %5 = OpVariable %_ptr_PushConstant__struct_3 PushConstant
%_ptr_PushConstant_int = OpTypePointer PushConstant %int
       %bool = OpTypeBool
%_ptr_Input_int = OpTypePointer Input %int
%gl_SampleID = OpVariable %_ptr_Input_int Input
      %float = OpTypeFloat 32
         %28 = OpTypeImage %float SubpassData 0 0 1 2 Unknown
%_ptr_UniformConstant_28 = OpTypePointer UniformConstant %28
         %32 = OpVariable %_ptr_UniformConstant_28 UniformConstant
    %v4float = OpTypeVector %float 4
      %v2int = OpTypeVector %int 2
%_ptr_Output_v4float = OpTypePointer Output %v4float
         %41 = OpVariable %_ptr_Output_v4float Output
       %void = OpTypeVoid
         %42 = OpTypeFunction %void
      %int_0 = OpConstant %int 0
      %int_3 = OpConstant %int 3
      %int_1 = OpConstant %int 1
      %int_5 = OpConstant %int 5
     %int_16 = OpConstant %int 16
         %36 = OpConstantComposite %v2int %int_16 %int_0
         %39 = OpConstantNull %v4float
         %44 = OpFunction %void None %42
          %1 = OpLabel
          %7 = OpAccessChain %_ptr_PushConstant_int %5 %int_0
          %9 = OpLoad %int %7
         %10 = OpShiftRightArithmetic %int %9 %int_3
         %13 = OpSLessThan %bool %10 %int_0
         %14 = OpSelect %int %13 %int_1 %int_0
         %16 = OpBitwiseAnd %int %9 %int_5
         %18 = OpINotEqual %bool %16 %int_0
         %19 = OpSelect %int %18 %int_1 %int_0
         %20 = OpBitwiseOr %int %19 %14
         %21 = OpIAdd %int %10 %20
         %22 = OpLoad %int %gl_SampleID
         %25 = OpSLessThan %bool %22 %21
               OpSelectionMerge %26 None
               OpBranchConditional %25 %27 %26
         %27 = OpLabel
         %30 = OpLoad %28 %32
         %34 = OpImageRead %v4float %30 %36
               OpBranch %26
         %26 = OpLabel
         %38 = OpPhi %v4float %34 %27 %39 %1
               OpStore %41 %38
               OpReturn
               OpFunctionEnd

最后超级简单。 OpImageRead 可能有可选的图像操作数,其中之一可以是 Sample,它将读取样本。 将内置变量 SampleId(当前阴影样本)输入其中修复它。