HLSL写的Compute Shader处理简单贴图时产生的问题

tigerccx 2018-10-26 11:44:33
在尝试编写 《Introduction to 3D Game Programming with DirectX 11》中12章习题5时产生的问题。
再第一次初始化两张格式为DXGI_FORMAT_R32_FLOAT的贴图作为 现在时刻 和 过去时刻 的波浪高度贴图时,使用全0初始化:

D3D11_TEXTURE2D_DESC tex2DDesc;
tex2DDesc.Height = hCount;
tex2DDesc.Width = wCount;
tex2DDesc.MipLevels = 1;
tex2DDesc.ArraySize = 1;
tex2DDesc.Format = DXGI_FORMAT_R32_FLOAT;
tex2DDesc.SampleDesc.Count = 1;
tex2DDesc.SampleDesc.Quality = 0;
tex2DDesc.Usage = D3D11_USAGE_DEFAULT;
tex2DDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
tex2DDesc.CPUAccessFlags = 0;
tex2DDesc.MiscFlags = 0;
// Set init data for both height maps to 0.0f
std::vector<float> vecInitHeight;
for (int i = 0; i < hCount*wCount; ++i)
{
vecInitHeight.push_back(0.0f);
}
D3D11_SUBRESOURCE_DATA subHeightData;
subHeightData.pSysMem = &vecInitHeight[0];
subHeightData.SysMemPitch = wCount*sizeof(float);
subHeightData.SysMemSlicePitch = hCount*wCount*sizeof(float);
// Sampled in VS to do transform
HR(device->CreateTexture2D(&tex2DDesc, &subHeightData, &mCurHeightMap));
HR(device->CreateTexture2D(&tex2DDesc, &subHeightData, &mLasHeightMap));

然后创建了相应的SRV和UAV,之后使用Compute Shader进行更新:

#define THREAD_NUM 32
#define MEM_SIZE (THREAD_NUM+2)

// Only need 3 params for CSUpdateHeight
cbuffer cbUpdateHeightPerObject
{
float gK1;
float gK2;
float gK3;
};

cbuffer cbUpdateNormAndTangPerObject
{
float gSpatialStep;
};

Texture2D<float> gCurTex;
RWTexture2D<float> gLasTex;
RWTexture2D<float2> gNormTex;
RWTexture2D<float2> gTangTex;

groupshared float gCache1[MEM_SIZE][MEM_SIZE]; //curtex
groupshared float gCache2[MEM_SIZE][MEM_SIZE]; //prevtex

int2 MaxInt2(int2 src, int2 border)
{
return int2(max(src.x, border.x), max(src.y, border.y));
}

int2 MinInt2(int2 src, int2 border)
{
return int2(min(src.x, border.x), min(src.y, border.y));
}

[numthreads(THREAD_NUM, THREAD_NUM, 1)]
void CSUpdateHeight(int3 groupThreadID:SV_GroupThreadID,
int3 dispatchThreadID : SV_DispatchThreadID)
{
// Update gCurTex data to gChache1
// Update gLasTex data to gCache2
// Clamp left up border
if (groupThreadID.x == 0 || groupThreadID.y == 0)
{
int2 xy0 = int2(dispatchThreadID.x - 1, dispatchThreadID.y - 1);//-1 needed?
int2 xy1 = int2(0, 0);
int2 xy = MaxInt2(xy0,int2(0,0));
gCache1[groupThreadID.x][groupThreadID.y] = gCurTex[xy];
gCache2[groupThreadID.x][groupThreadID.y] = gLasTex[xy];
}
// Clamp right down border
if (groupThreadID.x == (THREAD_NUM - 1) || groupThreadID.y == (THREAD_NUM - 1))//-1 needed?
{
int2 xy0 = int2(dispatchThreadID.x + 1, dispatchThreadID.y + 1);
int2 xy1 = int2(gCurTex.Length.x - 1, gCurTex.Length.y - 1);
int2 xy = MinInt2(xy0, xy1);
gCache1[groupThreadID.x + 2][groupThreadID.y + 2] = gCurTex[xy];
gCache2[groupThreadID.x + 2][groupThreadID.y + 2] = gLasTex[xy];
}
// Other
int2 xy0 = int2(gCurTex.Length.x - 1, gCurTex.Length.y - 1);
int2 xy = MinInt2(dispatchThreadID.xy, xy0);
gCache1[groupThreadID.x + 1][groupThreadID.y + 1] = gCurTex[xy];
gCache2[groupThreadID.x + 1][groupThreadID.y + 1] = gLasTex[xy];

// Wait for cache synchronize
GroupMemoryBarrierWithGroupSync();

int cx = groupThreadID.x + 1;
int cy = groupThreadID.y + 1;
// Restrict border from changing
if(dispatchThreadID.x!=0 &&
dispatchThreadID.y!=0 &&
dispatchThreadID.x<gCurTex.Length.x - 1 &&
dispatchThreadID.y<gCurTex.Length.y- 1)
gLasTex[dispatchThreadID.xy] =
gK1*gCache2[cx][cy] +
gK2*gCache1[cx][cy] +
gK3*(gCache1[cx + 1][cy] +
gCache1[cx - 1][cy] +
gCache1[cx][cy + 1] +
gCache1[cx][cy - 1]);
}

technique11 UpdateHeight
{
pass P0
{
SetVertexShader(NULL);
SetPixelShader(NULL);
SetComputeShader(CompileShader(cs_5_0, CSUpdateHeight()));
}
}

并在代码中调用


t += dt;
if (t >= mTimeStep)
{
++testcount;
// Update current and last height map
D3DX11_TECHNIQUE_DESC techDesc;
Effects::WavesUpdateFX->Test->GetDesc(&techDesc);
for (int p = 0; p < techDesc.Passes; ++p)
{
Effects::WavesUpdateFX->SetTestMap(mLasHeightSRV);
Effects::WavesUpdateFX->SetTestCount(testcount);

Effects::WavesUpdateFX->Test->GetPassByIndex(p)->Apply(0, dc);
int cxGroups = ceilf(1.0f * mNumRows / THREAD_NUM);
int cyGroups = ceilf(1.0f * mNumCols / THREAD_NUM);
HR(dc->Dispatch(cxGroups, cyGroups, 1));

ID3D11ShaderResourceView* clearSRVs[] = { NULL };
dc->CSSetShaderResources(0, 1, clearSRVs);
}

Effects::WavesUpdateFX->UpdateHeightTech->GetDesc(&techDesc);
for (int p = 0; p < techDesc.Passes; ++p)
{
Effects::WavesUpdateFX->SetK1(mK1);
Effects::WavesUpdateFX->SetK2(mK2);
Effects::WavesUpdateFX->SetK3(mK3);
Effects::WavesUpdateFX->SetCurTex(mCurHeightSRV);
Effects::WavesUpdateFX->SetLasTex(mLasHeightUAV);

Effects::WavesUpdateFX->UpdateHeightTech->GetPassByIndex(p)->Apply(0, dc);
int cxGroups = ceilf(1.0f * mNumRows / THREAD_NUM);
int cyGroups = ceilf(1.0f * mNumCols / THREAD_NUM);
HR(dc->Dispatch(cxGroups, cyGroups, 1));
}

// Good house keeping
ID3D11ShaderResourceView* clearSRVs[] = { NULL };
dc->CSSetShaderResources(0, 1, clearSRVs);

ID3D11UnorderedAccessView* clearUAVs[] = { NULL };
dc->CSSetUnorderedAccessViews(0, 1, clearUAVs, 0);

t = 0.0f;
}
dc->CSSetShader(0, 0, 0);

初步做的大致流程就是这样,使用的是Effect,使用fxc编译。

然后使用Visual Studio自带的Graphic Debug进行调试,但是发现gCurTex正常,一直为全黑,但gLasTex在线程组处理的边缘处(左下角和右上角)出现了奇怪的数据:



以上是300多帧的时候截图到的数据。
下面这个是第7帧截图到的:



有人知道这个是怎么产生的吗?求一个解决,谢谢!
...全文
284 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
tigerccx 2018-10-28
  • 打赏
  • 举报
回复
没有人吗

2,537

社区成员

发帖
与我相关
我的任务
社区描述
Unity3D相关内容讨论专区
游戏unity 技术论坛(原bbs)
社区管理员
  • Unity3D
  • 芝麻粒儿
  • 「已注销」
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

Unity3D社区公告:

  1. 社区致力于解决各种Unity3D相关的“疑难杂症”。
  2. 社区不允许发布与Unity3D或相关技术无关内容。
  3. 社区版主邀请各位一道为打造优秀社区不懈努力。

试试用AI创作助手写篇文章吧