float in RWTexture<float4> 输出不一致的值,具体取决于它在 if 语句的哪一侧
float in RWTexture<float4> outputs inconsistent values depending on what side on an if-statement it is
我正在尝试编写一个写入 RWTexture2 中的红色通道的 HLSL 计算着色器,但是当我尝试读取值时,我发现不一致,这完全取决于我是将赋值放在任意值之前还是之后if 语句:
具体例子。我只调度一个线程 shader.Dispatch(1, 1, 1)
在分派以下代码后从 AppendStructureBuffer 读取时,returns 是一个值为 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 语句之外会使它变成 return 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);
}
}
作为完整性检查,注释掉作业使其成为 return 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 语句之前的示例:
// 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 语句之后:
// 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 语句之后的情况下,才将值 255 赋给结构化 buffy。
附加信息:我正在使用 Unity 的着色器编译器来编译代码。我使用的Unity版本是2018.3.14f1.
我得到了一些帮助,我们解决了问题。在 Unity 中,我使用具有以下设置的 RenderTexture 初始化了 gridModel:
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 位浮点通道,因此将我的 int 固定为 1。通过用浮点值代替 0.4 替换 255,无论我在何处执行作业。
我在 if 语句的两边收到差异的原因是,在 if 语句内部发生赋值的情况下,编译器直接将值赋值给 appendbuffer 而没有费心首先从纹理加载,因此该值从未被限制。
我正在尝试编写一个写入 RWTexture2 中的红色通道的 HLSL 计算着色器,但是当我尝试读取值时,我发现不一致,这完全取决于我是将赋值放在任意值之前还是之后if 语句:
具体例子。我只调度一个线程 shader.Dispatch(1, 1, 1)
在分派以下代码后从 AppendStructureBuffer 读取时,returns 是一个值为 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 语句之外会使它变成 return 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);
}
}
作为完整性检查,注释掉作业使其成为 return 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 语句之前的示例:
// 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 语句之后:
// 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 语句之后的情况下,才将值 255 赋给结构化 buffy。
附加信息:我正在使用 Unity 的着色器编译器来编译代码。我使用的Unity版本是2018.3.14f1.
我得到了一些帮助,我们解决了问题。在 Unity 中,我使用具有以下设置的 RenderTexture 初始化了 gridModel:
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 位浮点通道,因此将我的 int 固定为 1。通过用浮点值代替 0.4 替换 255,无论我在何处执行作业。
我在 if 语句的两边收到差异的原因是,在 if 语句内部发生赋值的情况下,编译器直接将值赋值给 appendbuffer 而没有费心首先从纹理加载,因此该值从未被限制。