I am thinking to achieve it in the pixel shader.Here is part of my code:
Firstly, I create a Texture1D as a color 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;
And then I pass it to the Pixel shader
m_ImmediateContext->PSSetShaderResources(0, 1, &m_ColorResView);
In the pixel shader, i use this color table like this:
Texture1D RandomTex : register(t0);
float4 PS(VS_OUTPUT Input, uint Primitive : SV_PrimitiveID) : SV_Target
{
uint Index = Primitive % ColorCount.x;
return RandomTex[Index];
}
I want to use the alpha channel of each color in this color table to count how many times the color used during whole Pixel Shader Stage...
I want to to modify the color table in the pixel shader just like the code below.But it seem to be infeasible.
RandomTex[Index].a = RandomTex[Index].a + 1;
I have been finding a way to count the color efficiently rather than render it on a texture and count in on cpu using c++.
All method I have thought has to do some extra counting work on cpu because I find it is hard to do the operation like x++(maybe some parallel problem on gpu),besides those method that I thought need to render the texture twice which might be slower that counting it on cpu straightly.
I am digging into it for a long time.But no use.Please help or try to give some ideas how to achieve this.
You can attach a small write buffer to your pixel shader (with an unordered view), and use atomic operations in the pixel shader.
Here is the modified HLSL code
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];
}
Here I use a StructuredBuffer, but you can also use a ByteAddressBuffer if you prefer. Also note that resource is attached to register u1, as first slot is still taken by your render target.
Your write buffer should have the same element count as your 1d texture, and needs to be attached to the pipeline (on top of the render target), with OMSetRenderTargetsAndUnorderedAccessViews
Every frame, you will also need to clear your buffer back to 0 (if required), otherwise, values will increment over time, for this you can use ClearUnorderedAccessViewUint
Please note in your case, as you are using a uint buffer and the function expects UINT Values[4], only Values[0] will be used as clear value.