I'm trying to implement Gaussian Filter using compute shader.
I have two texture resources. Firstly, I render entire scene to the first texture. Then I apply gaussian filter for this texture using compute shader( which writes results to the second texture). And finally, i use shader resource view of the second texture in final render pass (pixel shader just executes texture.Sample). But as result i just get black screen:(
Initialize textures and their resource views:
//Texture used for rendering ID3D11Texture2D* renderTargetTexture; ID3D11RenderTargetView* renderTargetTextureView; ID3D11ShaderResourceView* shaderRenderTextureView; //texture to which result of gaussian filter will be applied ID3D11Texture2D* gaussTexture; ID3D11UnorderedAccessView* gaussTextureUAView; ID3D11ShaderResourceView* gaussTextureSRView; ID3D11RenderTargetView* gaussTextureRTView; /***** Create Texture Render Target View *****/ D3D11_TEXTURE2D_DESC textureDesc; D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc; D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc; //create render texture ZeroMemory(&textureDesc, sizeof(D3D11_TEXTURE2D_DESC)); textureDesc.Width = textureWidth; textureDesc.Height = textureHeight; textureDesc.MipLevels = 1; textureDesc.ArraySize = 1; textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; textureDesc.SampleDesc.Count = 1; textureDesc.Usage = D3D11_USAGE_DEFAULT; textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; textureDesc.CPUAccessFlags = 0; textureDesc.MiscFlags = 0; hr = d3d11Device->CreateTexture2D(&textureDesc, NULL, &renderTargetTexture); if (FAILED(hr)) return false; //create render target view renderTargetViewDesc.Format = textureDesc.Format; renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; renderTargetViewDesc.Texture2D.MipSlice = 0; hr = d3d11Device->CreateRenderTargetView(renderTargetTexture, &renderTargetViewDesc, &renderTargetTextureView); if (FAILED(hr)) return false; //create shader resource view shaderResourceViewDesc.Format = textureDesc.Format; shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; shaderResourceViewDesc.Texture2D.MostDetailedMip = 0; shaderResourceViewDesc.Texture2D.MipLevels = 1; hr = d3d11Device->CreateShaderResourceView(renderTargetTexture, &shaderResourceViewDesc, &shaderRenderTextureView); if (FAILED(hr)) return false; /*** GAUSSIAN TEXTURE ***/ D3D11_TEXTURE2D_DESC gtDesc; D3D11_SHADER_RESOURCE_VIEW_DESC srView; D3D11_UNORDERED_ACCESS_VIEW_DESC uaDesc; D3D11_RENDER_TARGET_VIEW_DESC rtDesc; //create gauss texture ZeroMemory(&gtDesc, sizeof(gtDesc)); gtDesc.Width = textureWidth; gtDesc.Height = textureHeight; gtDesc.MipLevels = 1; gtDesc.ArraySize = 1; gtDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; gtDesc.SampleDesc.Count = 1; gtDesc.Usage = D3D11_USAGE_DEFAULT; gtDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; gtDesc.CPUAccessFlags = 0; gtDesc.MiscFlags = 0; hr = d3d11Device->CreateTexture2D(&gtDesc, NULL, &gaussTexture); if (FAILED(hr)) return false; //create render target view rtDesc.Format = gtDesc.Format; rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; rtDesc.Texture2D.MipSlice = 0; hr = d3d11Device->CreateRenderTargetView(gaussTexture, &rtDesc, &gaussTextureRTView); if (FAILED(hr)) return false; //create shader resource view srView.Format = gtDesc.Format; srView.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srView.Texture2D.MostDetailedMip = 0; srView.Texture2D.MipLevels = 1; hr = d3d11Device->CreateShaderResourceView(gaussTexture, &srView, &gaussTextureSRView); if (FAILED(hr)) return false; //create unordered access view uaDesc.Format = gtDesc.Format; uaDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; uaDesc.Texture2D.MipSlice = 0; hr = d3d11Device->CreateUnorderedAccessView(gaussTexture, &uaDesc, &gaussTextureUAView); if (FAILED(hr)) return false;
Now render entire scene to the first texture:
float bgTexColor[4] = {(1.0f, 0.0f, 0.0f, 1.0f)}; //default color is red!
d3d11DevCon->VSSetShader(VS, 0, 0);
d3d11DevCon->PSSetShader(PS, 0, 0);
d3d11DevCon->RSSetViewports(1, &texViewport);
d3d11DevCon->OMSetRenderTargets(1, &renderTargetTextureView, NULL);
d3d11DevCon->ClearRenderTargetView(renderTargetTextureView, bgTexColor);
d3d11DevCon->Draw(36, 0); //draw the cube
Apply gaussian filter:
d3d11DevCon->CSSetShader(CS, 0, 0); d3d11DevCon->CSSetShaderResources(0, 1, &shaderRenderTextureView); //bind out rendered scene as shader resource view d3d11DevCon->CSSetUnorderedAccessViews(0, 1, &gaussTextureUAView, NULL); //unordered access for resulting texture! UINT x = (UINT)( ceil( textureWidth / 32.0f ) ); UINT y = (UINT)( ceil( textureHeight / 32.0f ) ); d3d11DevCon->Dispatch(x, y, 1);
Finally, render our final texture to the screen (in pixel shader i just use texture.Sample) :
d3d11DevCon->VSSetShader(textureVS, 0, 0); d3d11DevCon->PSSetShader(texturePS, 0, 0); d3d11DevCon->RSSetViewports(1, &viewport); d3d11DevCon->OMSetRenderTargets(1, &renderTargetView, NULL); //back buffer now is render target d3d11DevCon->PSSetShaderResources(0, 1, &gaussTextureSRView); d3d11DevCon->Draw(6, 0);
Oh, by the way, here is my compute shader:
//Resources
Texture2D<float4> InputTex : register( t0 );
RWTexture2D<float4> OutputTex : register( u0 );
//filter kernel coefficients
static const float kernel[7][7] = {
0.000904706, 0.003157733, 0.00668492, 0.008583607, 0.00668492, 0.003157733, 0.000904706,
0.003157733, 0.01102157, 0.023332663, 0.029959733, 0.023332663, 0.01102157, 0.003157733,
0.00668492, 0.023332663, 0.049395249, 0.063424755, 0.049395249, 0.023332663, 0.00668492,
0.008583607, 0.029959733, 0.063424755, 0.081438997, 0.063424755, 0.029959733, 0.008583607,
0.00668492, 0.023332663, 0.049395249, 0.063424755, 0.049395249, 0.023332663, 0.00668492,
0.003157733, 0.01102157, 0.023332663, 0.029959733, 0.023332663, 0.01102157, 0.003157733,
0.000904706, 0.003157733, 0.00668492, 0.008583607, 0.00668492, 0.003157733, 0.000904706
};
[numthreads(32, 32, 1)]
void CS(uint3 DispatchThreadId : SV_DispatchThreadID)
{
//get coordinates of top left corner
int3 textureCoords = DispatchThreadId - int3(3, 3, 0);
//initialize final color
float4 finalColor = (float4)0.0f;
//loop through filter kernel getting final color
for (int i = 0; i < 7; i++)
for (int j = 0; j < 7; j++)
finalColor += InputTex.Load(textureCoords + int3(i, j, 0) ) * kernel[i][j];
//assign new color value to the output image
OutputTex[DispatchThreadId.xy] = finalColor;
//OutputTex[DispatchThreadId.xy] = float4(1.0f, 1.0f, 1.0f, 1.0f);
}
Why I think that the problem is with Unordered Access View? I tried to clear gaussTexture with red color after the compute shader has executed:
float bgTexColor[4] = {(1.0f, 0.0f, 0.0f, 1.0f)};
d3d11DevCon->ClearRenderTargetView(gaussTextureRTView, bgTexColor);
And i still get the black screen. But if I comment binding the unordered access to the compute shader I get what I should get - the red screen:
//d3d11DevCon->CSSetUnorderedAccessViews(0, 1, &gaussTextureUAView, NULL); //unordered access for resulting texture!
I'm pretty sure that compute shader itself works correctly as commenting Dispatch call without commenting CSSetUnorderedAccessViews still suffers the problem and I get only black screen.
Where the problem can be?
I would appreciate any help! Thanks in advance!
Edited by DgekGD, 03 December 2012 - 12:04 PM.






