RWTexture 中的浮点数<float4>输出不一致的值,具体取决于 if 语句中的哪一端



我正在尝试编写一个hlsl计算着色器,该hlsl compute着色器在rwtexture2中写入红色频道2,但我看到不一致时,当我尝试读取该值时,所有这些都取决于我是否放置了任意命令之前或之后的分配:

具体示例。我只派遣一个线程shader.Dispatch(1, 1, 1)

从附录结构缓冲程序读取后,派遣以下代码返回一个值为255的条目。

RWTexture2D<float4> gridModel;
AppendStructuredBuffer<float> outlierIndeces;
[numthreads(1, 1, 1)]
void IdentifyBorderPoints(uint3 id : SV_DispatchThreadID)
{
    if (id.x == 0)
    {
        gridModel[id.xy] = float4(255, 0, 0, 0);
        outlierIndeces.Append(gridModel[id.xy].r);
    }
}

但是将分配移动在if-Statement之外使其返回1。但是,从我所看到的,这仍然应该只有255:

RWTexture2D<float4> gridModel;
AppendStructuredBuffer<float> outlierIndeces;
[numthreads(1, 1, 1)]
void IdentifyBorderPoints(uint3 id : SV_DispatchThreadID)
{
    gridModel[id.xy] = float4(255, 0, 0, 0);
    if (id.x == 0)
    {
        outlierIndeces.Append(gridModel[id.xy].r);
    }
}

作为理智检查,评论作业使其返回0:

RWTexture2D<float4> gridModel;
AppendStructuredBuffer<float> outlierIndeces;
[numthreads(1, 1, 1)]
void IdentifyBorderPoints(uint3 id : SV_DispatchThreadID)
{
    //gridModel[id.xy] = float4(255, 0, 0, 0);
    if (id.x == 0)
    {
        outlierIndeces.Append(gridModel[id.xy].r);
    }
}

我对编译的代码进行了更深入的了解,在那里我也看到了一个区别:以下编译的代码来自示例,该示例发生在if-Statement之前:

// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Input
//
// Output signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Output
      cs_5_0
      dcl_globalFlags refactoringAllowed
      dcl_uav_structured u0, 4
      dcl_uav_typed_texture2d (float,float,float,float) u1
      dcl_input vThreadID.xy
      dcl_temps 2
      dcl_thread_group 1, 1, 1
   0: store_uav_typed u1.xyzw, vThreadID.xyyy, l(255.000000,0,0,0)
   1: if_z vThreadID.x
   2:   mov r0.x, l(0)
   3:   mov r0.yzw, vThreadID.yyyy
   4:   ld_uav_typed_indexable(texture2d)(float,float,float,float) r0.x, r0.xyzw, u1.xyzw
   5:   imm_atomic_alloc r1.x, u0
   6:   store_structured u0.x, r1.x, l(0), r0.x
   7: endif 
   8: ret 
// Approximately 0 instruction slots used

这是在if statement之后发生分配的示例中的编译代码:

// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Input
//
// Output signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Output
      cs_5_0
      dcl_globalFlags refactoringAllowed
      dcl_uav_structured u0, 4
      dcl_uav_typed_texture2d (float,float,float,float) u1
      dcl_input vThreadID.xy
      dcl_temps 1
      dcl_thread_group 1, 1, 1
   0: if_z vThreadID.x
   1:   mov r0.x, l(0)
   2:   mov r0.yzw, vThreadID.yyyy
   3:   store_uav_typed u1.xyzw, r0.xyzw, l(255.000000,0,0,0)
   4:   imm_atomic_alloc r0.x, u0
   5:   store_structured u0.x, r0.x, l(0), l(255.000000)
   6: endif 
   7: ret 
// Approximately 0 instruction slots used

我不完全理解编译代码,但似乎只有在if-statement之后发生分配的情况下,值255才分配给结构化Buffy。

附加信息:我正在使用Unity的着色器编译器来编译代码。我使用的Unity的版本是2018.3.14f1。

我得到了一些帮助,我们发现了问题。在Unity中,我使用以下设置的重新文字初始化了网格模型:

texture = new RenderTexture(512, 512, 1, RenderTextureFormat.ARGB32);
texture.depth = 0;
texture.enableRandomWrite = true;
texture.Create();

我将其发送给着色器:

int identifyBorderPointsKernel = cShader.FindKernel("IdentifyBorderPoints");
cShader.SetTexture(identifyBorderPointsKernel, "gridModel", texture);

但是出现问题是因为RenderTextureFormat.argb32中的每个通道都是8位Float Chhanel,因此将我的INT夹至1。通过用float值代替255,而不是float值代替0.4,无论我在哪里完成分配,我都得到了平等。

我在if-statement的任一侧都会收到差异的原因是因为在if-statement内部发生分配的情况下,编译器将值直接分配给附录案件,并且不费心从纹理首先因此,该值永远不会被夹紧。

最新更新