[D3D10] D3D says that resource is bound to otput, but PIX doesn't agree

Started by
10 comments, last by rychu_elektryk 12 years, 1 month ago
Hi all

I have a problem with setting shader resource which was previously bound as a render target. Typical way to handle this case would be:

unbind that resource from being a render target
set it as a resource for another pass

Well unfortunalley it does not work in this case. Let me show you some pseudo code:

Set resource "texture 1"

Set "switch" variable to false

Set render target to "texture 2"

Apply and draw

Clear all render targets

//------------------------

Set resource "texture 2"

Set "switch" variable to true

Apply and draw

//------------------------

HLSL pass which is the same for both draw calls

if(switch == true) sample texture 2
else sample texture 1


I've checked in PIX that before second draw call there is no render targets bound. When I do a second draw call I get information that my resource "texture 2" was nullified because it is still bound to an output. How can it be? Could someone explain what is going on here?



[color=#fafafa !important]small-logo.png



[color=#fafafa !important]

small-logo.png

Advertisement
First create a 2d texture ( ID3D11Texture2D), that will be used to create the render target view (ID3D11RenderTargetView) and the shader resource view (ID3D11ShaderResourceView). Make sure you set the bind flags for the 2d texture's description to D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;, so it can be used as both a shader resource view and a render target view. start by creating the 2d texture:


// Set these 3 in the same "scope" as the functions and classes you want to use them in
ID3D11Texture2D* renderTargetTex;
ID3D11RenderTargetView* renderTargetView;
ID3D11ShaderResourceView* renderTargetsShaderResourceView;

D3D11_TEXTURE2D_DESC texDesc;
// fill out the 2d texture, but make sure to set BindFlags to:
texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;

// Now create the texture:
d3dDevice->CreateTexture2D(&texDesc, NULL, &renderTargetTex);

// create the render target views description, making sure to use the same format that was used when creating the 2d texture above
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;

// Fill out the description making sure the formats are the same
rtvDesc.Format = texDesc.Format;

// Now create the render target view using the created texture above and the rtv description:
d3dDevice->CreateRenderTargetView(renderTargetTex, &rtvDesc, &renderTargetView);

// Now create the description for the shader resource view. make sure this also has the same format as the 2d texture above:
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;

// Fill out the description making sure the format is the same as the texture above
srvDesc.Format = texDesc.Format;

// Now create the shader resource view using the srvDesc and 2d Texture created above:
d3dDevice->CreateShaderResourceView(renderTargetTex, &srvDesc, &renderTargetsShaderResourceView);


Now when setting the render target, set it to "renderTargetView", and when binding a resource to the shaders, use "renderTargetsShaderResourceView"

I hope i didn't miss anything, but if i did, sorry ;)
@iedoc

Thanks for the answer, but i think You missed the point of my post. I know how to create render targets and set resources. I have problem with only one case, when the resource I'am trying to set to pass was previously bound to the same pass as a render target. It should work because I've removed this texture from the render target slot before trying to use it again in the same pass, not as a render target, but as a resource.

I hope that the problem is now clearwink.png


[color=#fafafa !important]

small-logo.png

I'm sorry, maybe i still don't understand exactly, but what i was trying to say was that you can't have a resource be a render target AND a shader resource. What you have to do is make a render target AND shader resource BOTH as pointers to a 2d texture, so what happens is when you render to the render target that is pointing to the 2d texture, the 2d texture is filled with the data. then when you bind the shader resource, it uses the data in the 2d texture that it points to. Am i still misunderstanding? ;)

You can't use a render target as a shader resource directly, as far as i know anyway
I'm sorry, maybe i still don't understand exactly, but what i was trying to say was that you can't have a resource be a render target AND a shader resource. What you have to do is make a render target AND shader resource BOTH as pointers to a 2d texture, so what happens is when you render to the render target that is pointing to the 2d texture, the 2d texture is filled with the data. then when you bind the shader resource, it uses the data in the 2d texture that it points to. Am i still misunderstanding? ;)

You can't use a render target as a shader resource directly, as far as i know anyway
Well, sorry for not precising it correctly.

By "setting resource to pass" I meant setting the shaderResourceView of a texture to pass
By "setting render target" I meant setting the renderTargetView of a texture to pass

Here's modified pseudo code


Set resource "tex1_ShaderResourceView"
Set "switch" variable to false
Set render target to "tex2_RenderTargetView"
Apply and draw
Clear all render targets
//------------------------
Set resource "tex2_ShaderResourceView"
Set "switch" variable to true
Set render target to back buffer
Apply and draw
//------------------------
HLSL pass which is the same for both draw calls
if(switch == true) sample tex2
else sample tex1


[color=#fafafa !important]

small-logo.png

When you say that you're clearing the render targets, you're setting RT0 to NULL?

When you say that you're clearing the render targets, you're setting RT0 to NULL?


I have 3 element array of null render targets

ID3D10RenderTargetView* aRenderTargets[3] = {0, 0, 0};

In this particular moment I use

M_pD3D10Device->OMSetRenderTargets(1, aRenderTargets, 0);

because i know that only one render target was set. To be 100% sure I've checked that in PIX and I can confirm that at that moment You're asking there are no render targets bound.


[color=#fafafa !important]

small-logo.png

I encountered this problem because i wanted to implement bilateral blur in one pass. I am basing on an implementation of HBAO that was in nvidia's sdk. In this example from sdk the bilateral blur is splitted into two passes:

BLUR1 pass: occlusion texture is being blured vertically and rendered to texture1
BLUR2 pass: texture1 is used as a resource and blurred horizontally

I my version I want to have only one pass and just call this pass twice
Just a minor point, but you should be explicitly using NULL rather than 0.

To unbind your render targets, have you tried OMSetRenderTargets (0, NULL, NULL)? From the SDK documentation:
Pointer to an array of render targets (see ID3D10RenderTargetView) to bind to the device. If this parameter is NULL, no render targets are bound[/quote]

Also, ID3D10Device::ClearState will unbind all of your render targets too - worth testing with (although it's overkill for solving this).

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

This topic is closed to new replies.

Advertisement