如何有效地计算整个像素着色器阶段使用颜色的次数?
How to efficiently count the times that a color was used during whole Pixel Shader Stage?
我想在像素中实现它shader.Here是我代码的一部分:
首先,我创建一个 Texture1D 作为颜色 table
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);
在像素着色器中,我使用这种颜色 table 是这样的:
Texture1D RandomTex : register(t0);
float4 PS(VS_OUTPUT Input, uint Primitive : SV_PrimitiveID) : SV_Target
{
uint Index = Primitive % ColorCount.x;
return RandomTex[Index];
}
我想使用这种颜色中每种颜色的 alpha 通道 table 来计算在整个像素着色器阶段使用了多少次颜色...
我想像代码一样在pixel shader中修改颜色table below.But 好像不行
RandomTex[Index].a = RandomTex[Index].a + 1;
我一直在寻找一种有效计算颜色的方法,而不是使用 C++ 在纹理上渲染颜色并计算 cpu。
我认为的所有方法都必须在 cpu 上做一些额外的计数工作,因为我发现除了我认为的那些方法之外,很难像 x++ 那样进行操作(可能是 gpu 上的一些并行问题)需要渲染纹理两次,这可能比直接计算 cpu 慢。
我正在深入研究它 time.But 没有 use.Please 帮助或尝试提供一些如何实现此目标的想法。
您可以将一个小的写入缓冲区附加到您的像素着色器(使用无序视图),并在像素着色器中使用原子操作。
这里是修改后的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,因为第一个插槽仍由您的渲染目标占用。
您的写入缓冲区应具有与一维纹理相同的元素数,并且需要附加到管道(在渲染目标之上),OMSetRenderTargetsAndUnorderedAccessViews
每一帧,您还需要将缓冲区清除回 0(如果需要),否则值会随着时间增加,为此您可以使用 ClearUnorderedAccessViewUint
请注意,在您的情况下,由于您使用的是 uint 缓冲区并且该函数需要 UINT 值 [4],因此只有值 [0] 将用作清除值。
我想在像素中实现它shader.Here是我代码的一部分:
首先,我创建一个 Texture1D 作为颜色 table
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);
在像素着色器中,我使用这种颜色 table 是这样的:
Texture1D RandomTex : register(t0);
float4 PS(VS_OUTPUT Input, uint Primitive : SV_PrimitiveID) : SV_Target
{
uint Index = Primitive % ColorCount.x;
return RandomTex[Index];
}
我想使用这种颜色中每种颜色的 alpha 通道 table 来计算在整个像素着色器阶段使用了多少次颜色...
我想像代码一样在pixel shader中修改颜色table below.But 好像不行
RandomTex[Index].a = RandomTex[Index].a + 1;
我一直在寻找一种有效计算颜色的方法,而不是使用 C++ 在纹理上渲染颜色并计算 cpu。
我认为的所有方法都必须在 cpu 上做一些额外的计数工作,因为我发现除了我认为的那些方法之外,很难像 x++ 那样进行操作(可能是 gpu 上的一些并行问题)需要渲染纹理两次,这可能比直接计算 cpu 慢。
我正在深入研究它 time.But 没有 use.Please 帮助或尝试提供一些如何实现此目标的想法。
您可以将一个小的写入缓冲区附加到您的像素着色器(使用无序视图),并在像素着色器中使用原子操作。
这里是修改后的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,因为第一个插槽仍由您的渲染目标占用。
您的写入缓冲区应具有与一维纹理相同的元素数,并且需要附加到管道(在渲染目标之上),OMSetRenderTargetsAndUnorderedAccessViews
每一帧,您还需要将缓冲区清除回 0(如果需要),否则值会随着时间增加,为此您可以使用 ClearUnorderedAccessViewUint
请注意,在您的情况下,由于您使用的是 uint 缓冲区并且该函数需要 UINT 值 [4],因此只有值 [0] 将用作清除值。