如何有效计算在整个Pixel Shader Stage中使用颜色的时间?
我想实现它在像素shader.Here是我的代码部分:如何有效计算在整个Pixel Shader Stage中使用颜色的时间?
首先,我创建了一个Texture1D作为色表
D3D11_TEXTURE1D_DESC t1d;
t1d.Width = ModelInfo::ColorCount;
t1d.ArraySize = 1;
t1d.MipLevels = 1;
t1d.CPUAccessFlags = 0;
t1d.MiscFlags = 0;
t1d.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
t1d.Usage = D3D11_USAGE_DEFAULT;
t1d.BindFlags = D3D11_BIND_SHADER_RESOURCE;
ZeroMemory(&InitData, sizeof(InitData));
InitData.pSysMem = ModelInfo::Colors;
hr = m_D3DDevice->CreateTexture1D(&t1d, &InitData, &m_ColorTable);
if (FAILED(hr))
return hr;
D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
viewDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
viewDesc.Texture1D.MostDetailedMip = 0;
viewDesc.Texture1D.MipLevels = 1;
hr = m_D3DDevice->CreateShaderResourceView(m_ColorTable, &viewDesc, &m_ColorResView);
if (FAILED(hr))
return hr;
然后我把它传递给像素着色器
m_ImmediateContext->PSSetShaderResources(0, 1, &m_ColorResView);
在像素着色器,我使用这种颜色表是这样的:
Texture1D RandomTex : register(t0);
float4 PS(VS_OUTPUT Input, uint Primitive : SV_PrimitiveID) : SV_Target
{
uint Index = Primitive % ColorCount.x;
return RandomTex[Index];
}
我想用每一种颜色的alpha通道在此色表来算多少次全像素着色阶段过程中使用的颜色...
我想修改颜色表在像素着色器就像下面的代码一样。但它似乎是不可行的。
RandomTex[Index].a = RandomTex[Index].a + 1;
我一直在寻找一种方法来有效地计算颜色,而不是在纹理上渲染它,并在cpu上使用C++计数。
我想过的所有方法都必须在cpu上做一些额外的计数工作,因为我发现很难执行像x ++这样的操作(也许在GPU上有一些并行问题),除了那些我认为需要渲染纹理的方法两次,可能会比较慢,直接计算在CPU上。
我正在挖掘它很长一段时间,但没有用。请帮助或尝试给一些想法如何实现这一点。
您可以将一个小写入缓冲区附加到像素着色器(具有无序视图),并在像素着色器中使用原子操作。
下面是修改的HLSL代码
Texture1D RandomTex : register(t0);
RWStructuredBuffer<uint> RWColorCountData : register(u1);
float4 PS(VS_OUTPUT Input, uint Primitive : SV_PrimitiveID) : SV_Target
{
uint Index = Primitive % ColorCount.x;
InterlockedAdd(RWColorCountData[Index], 1);
return RandomTex[Index];
}
这里我用一个StructuredBuffer,但你也可以使用一个ByteAddressBuffer如果你喜欢。另请注意,资源已附加到寄存器u1,因为第一个插槽仍由您的渲染目标占用。
你写缓冲区应该有相同的元素算作你的1D纹理,并且需要连接到管道(上的渲染目标顶部),与OMSetRenderTargetsAndUnorderedAccessViews
每一帧,还需要清除您的缓冲区回到0(如果需要),否则,值会随着时间而增加,为此,您可以使用ClearUnorderedAccessViewUint
请注意您的情况,因为您使用的是uint缓冲区,并且函数需要UINT值[4] ,只有值[0]将被用作清除值。
无法更改着色器的输入。你只能指定输出,但这不适用于你的情况。 一个选项可能是将索引渲染到一个特殊的渲染目标,然后对CPU上的索引进行计数,但这不会考虑透支。 – Gnietschow
@Gnietschow我打算使用GPU来计算指数,认为这可能会加速计数过程。对于某种方式来说,并行问题,我发现很难做像x ++这样的操作(读取变量然后增加它)...沮丧:(..... – BlauHimmel
如果要从像素着色器写入缓冲区,则必须使用无人机。使用AtomicIncrement,您可以计算您想要计数的内容。 – galop1n