Texture UnorderedAccessView problem (compute shader)

Started by
5 comments, last by DgekGD 11 years, 4 months ago
Hi, guys!

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[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, &amp;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!
Advertisement
You cannot read from and write to the same resource at the same time, you will have to work with a second texture. Creating the device in debug mode should warn you about this.
Yep, I heard that to read and write simultaneously I need to cast format to D3D11_FORMAT_R32_UINT for UAV... But I don't read and write to the resource at the same time.

1)For the first render pass i don't use the second texture at all.
2)Than in Compute Shader I use the first texture for reading (shader resource view) and the second one for writing (unordered access view).
3)Final pass: I use the second texture for reading as shader resource view

Or maybe i misunderstand something ...
Argh, sorry, I really wasn't looking/reading carefully. It's really strange. Dont' you get any hints from the debug layer ?

Edit: Try setting the compute shaders UAV explicitly to NULL before setting the pixel shaders SRV.
Setting NULL UAV for the place of UAV of my texture helped! Before that, i tried to set the compute shader itself to NULL, it didn't help me.

My gaussian filter still does't worked corretly, but I think I can handle it as the main problem solved:)

Thanks for your help!
You're welcome. I hope you find your other problem, too, I don't see anything suspicious yet.

Anyway: I want to show the usefulness of the debug layer. This will show up when you have the same resource bound for input and output:

[3636] D3D11: WARNING: ID3D11DeviceContext::CSSetUnorderedAccessViews: Resource being set to CS UnorderedAccessView slot 0 is still bound on input! [ STATE_SETTING WARNING #2097355: DEVICE_CSSETUNORDEREDACCESSVIEWS_HAZARD ]
[3636] D3D11: WARNING: ID3D11DeviceContext::CSSetUnorderedAccessViews: Forcing CS shader resource slot 0 to NULL. [ STATE_SETTING WARNING #2097317: DEVICE_CSSETSHADERRESOURCES_HAZARD ]


Probably something like this happened in your setup:

[4388] D3D11: WARNING: ID3D11DeviceContext::PSSetShaderResources: Resource being set to PS shader resource slot 0 is still bound on output! Forcing to NULL. [ STATE_SETTING WARNING #7: DEVICE_PSSETSHADERRESOURCES_HAZARD ]


So the pipeline automatically resets illegal combinations, but it also tells you.
Indeed, it would have helped to find error in my program faster. Now, i create device with debug layer enabled in debug mode;) I appreciate your explanation.

By the way, i managed to rapair my shader to work correctly. It suffered the same problem, I didn't unbound first texture's RTV before binding resource as SRV in the Compute Shader :)

This topic is closed to new replies.

Advertisement