Flooded by warnings when using RenderTargets as textures

Started by
5 comments, last by matches81 17 years, 10 months ago
Hi there! I have come across a problem when using render targets as textures: I have three render-target textures (created with D3DUSAGE_RENDERTARGET) RTColor, RTNormals and RTDepth. The first pass (filling the RTs) works fine, however the second pass, where I use those as textures floods me with this warning:
Quote: Direct3D9: (WARN) :Can not render to a render target that is also used as a texture. A render target was detected as bound, but couldn't detect if texture was actually used in rendering.
I do the following:

device->GetRenderTarget(0, &RTBackbuffer);
device->SetRenderTarget(0, RTColor);
device->SetRenderTarget(1, RTNormals);
device->SetRenderTarget(2, RTDepth);

//clear render target and z-buffer
device->BeginScene();
//render my stuff using a shader here, works fine
device->EndScene();

device->SetRenderTarget(0, RTBackbuffer);
device->SetRenderTarget(1, NULL);
device->SetRenderTarget(2, NULL);

device->BeginScene();
//clear render target and z-buffer
//render a fullscreen quad, using the RTs as texture with "SimpleLight.fx"
device->EndScene();
device->Present(0,0,0,0);

That´s about all I do with the RTs for now. The shader ("SimpleLight.fx") mentioned in the source above looks like this:

float4 simpleLight_PS(in A2P v) : COLOR
{
    float4 diff = tex2D(colorSampler, v.uv);
    
    float depth = colorToFloat(tex2D(depthSampler, v.uv));
    depth = depth * (fFar -fNear) + fNear;
    float3 p = mul(float3(v.uv*2.0 -1.0, 1.0), mat_invProj);
    float3 viewPos = float3(p.xy / p.z * depth,depth);
    

    float3 lightViewPos = mul(float4(LightPos,1), mat_View).xyz;
    float3 Normal = tex2D(normalSampler, v.uv).xyz;
    
    float3 L = viewPos-lightViewPos;
    float nDotL = dot(Normal, normalize(L));
    
    return float4(diff * LightColor * nDotL, 1);      <<----- gives warnings
//    return colorToFloat(tex2D(depthSampler, v.uv));   <<---- works
//    return tex2D(colorSampler, v.uv);                 <<---- works
//    return tex2D(normalSampler, v.uv);                <<---- works
//    return tex2D(colorSampler, v.uv) *                <<---- works
//             tex2D(normalSampler, v.uv);
//    return tex2D(colorSampler, v.uv) *                <<---- works
//             colorToFloat(tex2D(depthSampler, v.uv));
//    return tex2D(colorSampler, v.uv) *               <<----- gives warnings
//             colorToFloat(tex2D(depthSampler, v.uv)) *;
//             tex2D(normalSampler, v.uv);
}

Okay, so I tried to make it simpler, as you can see in the source. Using less than all 3 RTs as textures in the shader works fine. So a look-up in one or two of them isn´t a problem, but using all three of them results in those warnings... Any help appreciated, thx for reading!
Advertisement
The warning message is pretty clear :
as soon as you set one texture as a texture (SetTexture)
you should make sure any sublevel is not bound as rendertarget
so if you previously had a SetRendertarget(TextureLevel)
you have to explicitely SetRendertarget(NULL) or to another rendertarget.

I'd like to add that this works the other way too. If you call SetTexture() or Effect->SetTexture(), and then call SetRenderTarget() using a surface from the texture, you're going to get the warning, since the texture is still bound. This could also be from the previous frame.

Be sure to call SetTexture(0, NULL) when you're done with it, or at the end of the frame.

Hope this helps.
Sirob Yes.» - status: Work-O-Rama.
[edit]
Okay, I can use these textures now. I really had to call SetTexture(..., NULL) on the SimpleLight ID3DXEffect after rendering.
However I still don´t understand why I only got those warnings when using _all_ textures, but not if I only used 1 or 2 of them, regardless of which I used.
The warnings are back, however I don´t have a clue why they reappeared...
this is the current source that deals with render targets and textures, there´s no other line of code in my project that sets any textures or render targets:
	this->m_pRTBackBuffer = NULL;	HRESULT hr = this->m_pDirect3DDevice->GetRenderTarget(0, &this->m_pRTBackBuffer);	if(FAILED(hr))	{		MessageBox(NULL, "GetRenderTarget failed!", "RenderGeometryPass error!", MB_OK);		return -11;	}		hr = this->m_pDirect3DDevice->SetRenderTarget(0, this->m_pRTColorSurface);	if(FAILED(hr))	{		MessageBox(NULL, "SetRenderTarget for ColorTexture failed!", "RenderGeometryPass error!", MB_OK);		return -12;	}	this->m_pDirect3DDevice->SetRenderTarget(1, this->m_pRTNormalsSurface);	if(FAILED(hr))	{		MessageBox(NULL, "SetRenderTarget for NormalTexture failed!", "RenderGeometryPass error!", MB_OK);		return -12;	}	this->m_pDirect3DDevice->SetRenderTarget(2, this->m_pRTDepthSurface);	if(FAILED(hr))	{		MessageBox(NULL, "SetRenderTarget for DepthTexture failed!", "RenderGeometryPass error!", MB_OK);		return -12;	}	this->m_pDirect3DDevice->SetRenderTarget(3, this->m_pRTSpecularSurface);	if(FAILED(hr))	{		MessageBox(NULL, "SetRenderTarget for SpecTexture failed!", "RenderGeometryPass error!", MB_OK);		return -12;	}	this->m_pDirect3DDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.f, 0);	this->m_pDirect3DDevice->BeginScene();// I render the first pass here	this->m_pDirect3DDevice->EndScene();			hr = this->m_pDirect3DDevice->SetRenderTarget(0, this->m_pRTBackBuffer);	if(FAILED(hr))	{		MessageBox(NULL, "Reverting to backbuffer failed!", "Renderer::RenderGeometryPass() error", MB_OK);		return -30;	}	this->m_pRTBackBuffer->Release();	this->m_pRTBackBuffer = NULL;	this->m_pDirect3DDevice->SetRenderTarget(1, NULL);	this->m_pDirect3DDevice->SetRenderTarget(2, NULL);	this->m_pDirect3DDevice->SetRenderTarget(3, NULL);		this->m_pDirect3DDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, D3DCOLOR_XRGB(70, 70, 100), 1.0, 0);	        //e is an ID3DXEffect containing the SimpleLight.fx shader from my first                //    post	e->SetTexture("ColorMap", this->m_pRTColor);	e->SetTexture("DepthMap", this->m_pRTDepth);	e->SetTexture("NormalMap", this->m_pRTNormals);	e->SetTechnique("tec0");	this->m_pDirect3DDevice->SetStreamSource(0,this->m_pVBQuads,0,20);this->m_pDirect3DDevice->SetVertexDeclaration(this->m_TransformedVerticesVD);	this->m_pDirect3DDevice->BeginScene();//rendering one full-screen quad here	this->m_pDirect3DDevice->EndScene();	e->SetTexture("ColorMap", NULL);	e->SetTexture("DepthMap", NULL);	e->SetTexture("NormalMap", NULL);	this->m_pDirect3DDevice->Present(0,0,0,0);


I left out some lines that set floats and matrices for the shader, as I don´t think they´re related to the problem.
As you see I call SetTexture(..., NULL) for all the textures I set during the second pass.
The warnings are spilled at every DrawIndexedPrimitive() call during the first pass, where I use m_pRTColor, m_pRTNormals and m_pRTDepth as render targets.
Anything else I can do to be really sure those textures aren´t bound anymore, as it seems that SetTexture(...,NULL) didn´t do the trick.

PS: I still only get those warnings when I use all three textures at once, using one or two of them works fine.
It's possible than calling Effect->SetTexture()
may just update the internal pointer to the texture inside the technique object and not call any of the setTexture method on the d3dDevice (waiting for the next begin call to really apply the states).
You can probably live with it, if you're annoyed by the debug spew
you can force the texture to be NULL outside the technique (do an explicit m_pDirect3DDevice->SetTexture(0..N, NULL) and remove the effect SetTextures which would then become redundant).

LeGreg
Quote:Original post by LeGreg
It's possible than calling Effect->SetTexture()
may just update the internal pointer to the texture inside the technique object and not call any of the setTexture method on the d3dDevice (waiting for the next begin call to really apply the states).
You can probably live with it, if you're annoyed by the debug spew
you can force the texture to be NULL outside the technique (do an explicit m_pDirect3DDevice->SetTexture(0..N, NULL) and remove the effect SetTextures which would then become redundant).

LeGreg


Thx! Calling SetTexture(...) of the device instead of the effect did the trick.

So it might be feasible to bind the samplers in the shader to a specific register? If I understand that binding to registers correctly that would mean, that if I bind a sampler in a shader to register s0 for example, calling m_pDirect3DDevice->SetTexture(0, NULL) should unbind the texture for that sampler bound to s0, right?
What I mean is: Does the sampler register sN correspond to the N in SetTexture(N, NULL) of the device?

If they do, I could just use SetTexture(...) of the device instead of the effect most of the time, at least for my lighting shaders, as I could just impose a standard in which register which texture has to be for them.


This topic is closed to new replies.

Advertisement