dx12) 着色器常量出错
dx12) Shader Constants goes wrong
如您所见,在 PIX 中,Pipeline 表示 GPU 上有正确的值,但是当我调试 Pixels 时,它在没有 gZSplits[0] 的情况下使用了错误的值。
然后我像这样将值上传到 GPU,mZSplits 是 std::vector:
for (int i = 1; i < mMapCount + 1; ++i)
{
cmdList->SetGraphicsRoot32BitConstants(7, 1, &mZSplits[i], i - 1);
}
这是我的着色器代码。
cbuffer ShadowCB : register(b5)
{
float gZSplits[3] : packoffset(c0);
}
float4 PS(DsOut din) : SV_Target
{
float4 result = 0.0f;
if(gKeyInput)
{
if (din.Tessellation.w <= 5.0f)
result = float4(1.0f, 0.0f, 0.0f, 1.0f);
else if (din.Tessellation.w <= 10.0f)
result = float4(0.0f, 1.0f, 0.0f, 1.0f);
else if (din.Tessellation.w <= 20.0f)
result = float4(0.0f, 0.0f, 1.0f, 1.0f);
else if (din.Tessellation.w <= 30.0f)
result = float4(1.0f, 1.0f, 0.0f, 1.0f);
else if (din.Tessellation.w <= 40.0f)
result = float4(1.0f, 0.0f, 1.0f, 1.0f);
else if (din.Tessellation.w <= 50.0f)
result = float4(0.0f, 1.0f, 1.0f, 1.0f);
else if (din.Tessellation.w <= 60.0f)
result = float4(1.0f, 1.0f, 1.0f, 1.0f);
else
result = float4(1.0f, 0.5f, 0.5f, 1.0f);
}
else
{
int idx = -1;
float4 PosV = mul(float4(din.PosW, 1.0f), gView);
for (int j = 2; j >= 0; j--)
{
float zSplits = gZSplits[j];
if (PosV.z < zSplits)
{
idx = j;
}
}
float4 PosS = mul(float4(din.PosW, 1.0f), gShadowTransform[idx]);
float4 diffuse = 0.0f;
float4 baseTexDiffuse = gBaseTexture.Sample(gAnisotropicWrap, din.TexCoord0) * gMat.Diffuse;
float4 detailedTexDiffuse = gDetailedTexture.Sample(gAnisotropicWrap, din.TexCoord1) * gMat.Diffuse;
float4 roadTexDiffuse = gRoadTexture.Sample(gAnisotropicWrap, din.TexCoord0) * gMat.Diffuse;
if (roadTexDiffuse.a < 0.4f)
{
diffuse = saturate(baseTexDiffuse * 0.6f + detailedTexDiffuse * 0.4f);
}
else
{
diffuse = roadTexDiffuse;
}
float3 view = normalize(gCameraPos - din.PosW);
float4 ambient = gAmbient * float4(gMat.Ambient, 1.0f) * diffuse;
float shadowFactor[3] = { 1.0f, 1.0f, 1.0f };
for (int i = 0; i < 3; i++)
shadowFactor[i] = CalcShadowFactor(PosS, idx);
float4 directLight;
float shadowFactorOut[3] = { 1.0f, 1.0f, 1.0f };
if (PosS.x < 0.0f || PosS.x > 1.0f || PosS.z < 0.0f || PosS.z > 1.0f || PosS.y < 0.0f || PosS.y > 1.0f)
directLight = ComputeLighting(gLights, gMat, normalize(din.NormalW), view, shadowFactorOut);
else
{
directLight = ComputeLighting(gLights, gMat, normalize(din.NormalW), view, shadowFactor);
}
result = ambient + directLight;
result.a = gMat.Diffuse.a;
float4 debugColor = { 1.0f, 1.0f, 1.0f, 1.0f };
//for (int k = 2; k >= 0; --k)
//{
// float4 pos = mul(float4(din.PosW, 1.0f), gShadowViewProj[k]);
// if (pos.x > 0.0f && pos.x < 1.0f && pos.z > 0.0f && pos.z < 1.0f && pos.y > 0.0f && pos.y < 1.0f)
// {
// if (k == 2)
// {
// debugColor = float4(1.0f, 0.0f, 0.0f, 1.0f);
// }
// if (k == 1)
// {
// debugColor = float4(0.0f, 1.0f, 0.0f, 1.0f);
// }
// if (k == 0)
// {
// debugColor = float4(0.0f, 0.0f, 1.0f, 1.0f);
// }
// }
//}
//result *= debugColor;
if (idx == 2)
{
debugColor = float4(1.0f, 0.0f, 0.0f, 1.0f);
}
else if (idx == 1)
{
debugColor = float4(0.0f, 1.0f, 0.0f, 1.0f);
}
else if (idx == 0)
{
debugColor = float4(0.0f, 0.0f, 1.0f, 1.0f);
}
result *= debugColor;
}
return result;
}
我检查了根签名或任何其他选项,但我找不到任何东西。
也许着色器偏移可能是问题?
根据常量缓冲区中数组的打包规则:
cbuffer ShadowCB : register(b5)
{
float gZSplits[3] : packoffset(c0);
}
不是3个浮点数(大小为12字节),所以表示不是
cbuffer ShadowCB : register(b5)
{
float gZSplits0;
float gZSplits1;
float gZSplits2;
};
实际展开为:
cbuffer ShadowCB : register(b5)
{
float gZSplits0;
float3 pad0;
float gZSplits1;
float3 pad0;
float gZSplits2;
};
所以您需要确保您的 cpu 侧缓冲区实际上与该布局匹配。
您可以通过检查反汇编再次确认 ShadowCB 大小确实是 36 字节。
如您所见,在 PIX 中,Pipeline 表示 GPU 上有正确的值,但是当我调试 Pixels 时,它在没有 gZSplits[0] 的情况下使用了错误的值。
然后我像这样将值上传到 GPU,mZSplits 是 std::vector:
for (int i = 1; i < mMapCount + 1; ++i)
{
cmdList->SetGraphicsRoot32BitConstants(7, 1, &mZSplits[i], i - 1);
}
这是我的着色器代码。
cbuffer ShadowCB : register(b5)
{
float gZSplits[3] : packoffset(c0);
}
float4 PS(DsOut din) : SV_Target
{
float4 result = 0.0f;
if(gKeyInput)
{
if (din.Tessellation.w <= 5.0f)
result = float4(1.0f, 0.0f, 0.0f, 1.0f);
else if (din.Tessellation.w <= 10.0f)
result = float4(0.0f, 1.0f, 0.0f, 1.0f);
else if (din.Tessellation.w <= 20.0f)
result = float4(0.0f, 0.0f, 1.0f, 1.0f);
else if (din.Tessellation.w <= 30.0f)
result = float4(1.0f, 1.0f, 0.0f, 1.0f);
else if (din.Tessellation.w <= 40.0f)
result = float4(1.0f, 0.0f, 1.0f, 1.0f);
else if (din.Tessellation.w <= 50.0f)
result = float4(0.0f, 1.0f, 1.0f, 1.0f);
else if (din.Tessellation.w <= 60.0f)
result = float4(1.0f, 1.0f, 1.0f, 1.0f);
else
result = float4(1.0f, 0.5f, 0.5f, 1.0f);
}
else
{
int idx = -1;
float4 PosV = mul(float4(din.PosW, 1.0f), gView);
for (int j = 2; j >= 0; j--)
{
float zSplits = gZSplits[j];
if (PosV.z < zSplits)
{
idx = j;
}
}
float4 PosS = mul(float4(din.PosW, 1.0f), gShadowTransform[idx]);
float4 diffuse = 0.0f;
float4 baseTexDiffuse = gBaseTexture.Sample(gAnisotropicWrap, din.TexCoord0) * gMat.Diffuse;
float4 detailedTexDiffuse = gDetailedTexture.Sample(gAnisotropicWrap, din.TexCoord1) * gMat.Diffuse;
float4 roadTexDiffuse = gRoadTexture.Sample(gAnisotropicWrap, din.TexCoord0) * gMat.Diffuse;
if (roadTexDiffuse.a < 0.4f)
{
diffuse = saturate(baseTexDiffuse * 0.6f + detailedTexDiffuse * 0.4f);
}
else
{
diffuse = roadTexDiffuse;
}
float3 view = normalize(gCameraPos - din.PosW);
float4 ambient = gAmbient * float4(gMat.Ambient, 1.0f) * diffuse;
float shadowFactor[3] = { 1.0f, 1.0f, 1.0f };
for (int i = 0; i < 3; i++)
shadowFactor[i] = CalcShadowFactor(PosS, idx);
float4 directLight;
float shadowFactorOut[3] = { 1.0f, 1.0f, 1.0f };
if (PosS.x < 0.0f || PosS.x > 1.0f || PosS.z < 0.0f || PosS.z > 1.0f || PosS.y < 0.0f || PosS.y > 1.0f)
directLight = ComputeLighting(gLights, gMat, normalize(din.NormalW), view, shadowFactorOut);
else
{
directLight = ComputeLighting(gLights, gMat, normalize(din.NormalW), view, shadowFactor);
}
result = ambient + directLight;
result.a = gMat.Diffuse.a;
float4 debugColor = { 1.0f, 1.0f, 1.0f, 1.0f };
//for (int k = 2; k >= 0; --k)
//{
// float4 pos = mul(float4(din.PosW, 1.0f), gShadowViewProj[k]);
// if (pos.x > 0.0f && pos.x < 1.0f && pos.z > 0.0f && pos.z < 1.0f && pos.y > 0.0f && pos.y < 1.0f)
// {
// if (k == 2)
// {
// debugColor = float4(1.0f, 0.0f, 0.0f, 1.0f);
// }
// if (k == 1)
// {
// debugColor = float4(0.0f, 1.0f, 0.0f, 1.0f);
// }
// if (k == 0)
// {
// debugColor = float4(0.0f, 0.0f, 1.0f, 1.0f);
// }
// }
//}
//result *= debugColor;
if (idx == 2)
{
debugColor = float4(1.0f, 0.0f, 0.0f, 1.0f);
}
else if (idx == 1)
{
debugColor = float4(0.0f, 1.0f, 0.0f, 1.0f);
}
else if (idx == 0)
{
debugColor = float4(0.0f, 0.0f, 1.0f, 1.0f);
}
result *= debugColor;
}
return result;
}
我检查了根签名或任何其他选项,但我找不到任何东西。 也许着色器偏移可能是问题?
根据常量缓冲区中数组的打包规则:
cbuffer ShadowCB : register(b5)
{
float gZSplits[3] : packoffset(c0);
}
不是3个浮点数(大小为12字节),所以表示不是
cbuffer ShadowCB : register(b5)
{
float gZSplits0;
float gZSplits1;
float gZSplits2;
};
实际展开为:
cbuffer ShadowCB : register(b5)
{
float gZSplits0;
float3 pad0;
float gZSplits1;
float3 pad0;
float gZSplits2;
};
所以您需要确保您的 cpu 侧缓冲区实际上与该布局匹配。
您可以通过检查反汇编再次确认 ShadowCB 大小确实是 36 字节。