SetRenderTarget() question...

Mintmaster

New member
Say, can you only use SetRenderTarget() (this in D3D btw) to draw on the largest surface in a mipmap chain? Whenever I set the render surface to one of the lower mip-maps in the texture, I still get it rendering to the top level surface. Does anyone know more about this?
 
JasonM [ATI] said:
Are you passing the right value to GetSurfaceLevel()?

-Jason

I tried all values. 0 gets me the top mip-map, and thought that setting a higher value (like 1 or 2) was giving me the top level again but actually what I saw rendered was just left from the last time I rendered. It was in fact not doing anything whenever I give GetSurfaceLevel() a different value, and nothing was rendered to the texture.

Do I have to worry about locking, adding dirty regions, or updating the texture?

Also, is D3DXFilterTexture() hardware accelerated? This is the main reason I want to access the lower levels (fast dynamic filtering), but also so that I can write my own filtering function to take things like gamma correction into account with a pixel shader when filtering.
 
Last edited:
When you're rendering TO a given mip level are you also trying to texture FROM the top mip level of the same texture? If so, this is the problem as the LOD calculations will not likely pull from the top mip level. The way to generate mip maps from a top level mip map in DX8.1 is to create a separate parallel "unchained mip chain" to do the filtering in and then copy to the real chained mip chain. Gross, I know. Have a look at the Treasure Chest source (grep for GetSurfaceLevel()) for some code which does this.

The D3DX filtering routines are not hardware accellerated. Additionally, hardware filtering assumes linear gamma textures. In DX9, there is hardware generated mip-mapping and support for gamma textures.

-Jason
 
JasonM [ATI] said:
When you're rendering TO a given mip level are you also trying to texture FROM the top mip level of the same texture? If so, this is the problem as the LOD calculations will not likely pull from the top mip level. The way to generate mip maps from a top level mip map in DX8.1 is to create a separate parallel "unchained mip chain" to do the filtering in and then copy to the real chained mip chain. Gross, I know. Have a look at the Treasure Chest source (grep for GetSurfaceLevel()) for some code which does this.

The D3DX filtering routines are not hardware accellerated. Additionally, hardware filtering assumes linear gamma textures. In DX9, there is hardware generated mip-mapping and support for gamma textures.

-Jason

This was my original intent, and I also thought of doing the "unchained mip chain", flipping between two mip map chains and copying every other mipmap after I was done.

As for LOD calculations, I was going to set the LOD bias to -1 (or otherwise) so that the correct mipmap would be sampled at each level. Is there any protection built into DX8.1 or ATI's drivers to stop me from using the same texture resource (but not the same mip level) for both render destination and texture source?

In any case, I disabled that part of my code. I was just trying to render polygons onto a surface. I'm not doing any fancy texturing at all. I'm just trying to render simple coloured polygons onto a surface. It worked for the top level, but not for any level below that.

Here's the basic code structure:

rendertex->GetSurfaceLevel(2, &psurf2);

pd3ddev->GetRenderTarget(&psurf1);
pd3ddev->GetDepthStencilSurface(&pzsurf1);
pd3ddev->SetRenderTarget(psurf2, NULL);
psurf2->Release();

pd3ddev->BeginScene();

pd3ddev->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_ARGB(0,100,100,100),1.0f,0);

pd3ddev->SetStreamSource(0, pvb,sizeof(D3DXVECTOR3));
pd3ddev->SetVertexShader(D3DFVF_XYZ);

pd3ddev->DrawPrimitive(D3DPT_TRIANGLEFAN,0,numPrim)))

pd3ddev->EndScene();

pd3ddev->SetRenderTarget(psurf1, pzsurf1);
psurf1->Release();
pzsurf1->Release();
pzsurf1->Release();

The various releases are there to compensate for D3D's automatic incrementing/decrementing of reference counts for surfaces (I hope I did it right). The various *surf variables are to retrieve the original render location (the screen). The rendertex texture was created with the usage parameter set to D3DUSAGE_RENDERTARGET. In my actual code, I check the return value of all these function calls for errors.

At the top, you can see the GetSurfaceLevel() function being called. With a value of 0, it works, and renders the polygons correctly to the surface (the top mipmap of rendertex). With a value of 1 or greater, nothing gets rendered to any mipmap of the texture.

Eventually I would like to render to the same texture I am sampling from to create a mipmap chain, but right now I'm just trying to render anything at all to the lower mipmaps. I hope this is enough information for you to help me out.
 
I don't think you should be releasing the render target right after you make it active.

Edited for length.
 
Last edited:
Boke said:
I don't think you should be releasing the render target right after you make it active. I think your code should look like this->



I use the same Z buffer for my textures as the one for the back buffer, It seems to work fine.. but of course I can't render to a texture with a larger dimension the vertical resolution of the screen... I don't really know if I should do it this way, but the performance seems good.

Well, I didn't have any releases in the first place and had the same problems, and I think I had a memory leak. I did the release there because first GetSurfaceLevel() increments the reference count, and then SetRenderTarget() increases it again. As for pzsurf, its reference count get incremented by both GetDepthStencilSurface() and the second SetRenderTarget(). I'm not using Z at all for my simple scene on the texture, just drawing polygons.

My problem lies in trying to render to the lower mipmap levels. I can render fine to the top level. It's just when GetSurfaceLevel is anything other than 0, it doesn't render to that surface of the mip chain - there is just noise there. Is there any other initialization I need to be able to render to lower mipmaps?
 
Ah... I understand what you are doing now...

I've spent the last several hours trying to render to a mipmap level with no luck. Like you said, level 0 renders fine but no other level does.
I thought it strange that no error codes were being returned from any of the functions. After some experimentation I found that the geometry was actually being rendered... but... it was to the back buffer!

So here is what I have->

512x512 Texture with a full MipMap chain created.

RenderTarget set to MipLevel 0 works fine.
RenderTarget set to MipLevel 1 ( or greater ) renders to the back buffer... at the correct size for the MipLevel that I desired the rendering to be performed in. Level 1 renders at 256x256, Level 2 128x128.. and so on... but always to the back buffer.

Ok, so now I'm confused too. Anyone have any ideas why this is happening?
 
Last edited:
Boke said:
Ah... I understand what you are doing now...

I've spent the last several hours trying to render to a mipmap level with no luck. Like you said, level 0 renders fine but no other level does.
I thought it strange that no error codes were being returned from any of the functions. After some experimentation I found that the geometry was actually being rendered... but... it was to the back buffer!

So here is what I have->

512x512 Texture with a full MipMap chain created.

RenderTarget set to MipLevel 0 works fine.
RenderTarget set to MipLevel 1 ( or greater ) renders to the back buffer... at the correct size for the MipLevel that I desired the rendering to be performed in. Level 1 renders at 256x256, Level 2 128x128.. and so on... but always to the back buffer.

Ok, so now I'm confused too. Anyone have any ideas why this is happening?

You mean the back-buffer of the screen (i.e. the original render target) ? That's really bizarre. I can see why I didn't notice this because I clear the backbuffer after I render to the texture.

So I guess it's almost as if SetRenderTarget() didn't work, and just kept the original backbuffer surface as the render target. However, it did adjust the viewport. Still, I would have expected some form of a return code in this situation, unless its a driver problem.

By the way Boke, thanks a lot for spending the time to try this out. I appreciate it - not many people would go to those lengths to help out some stranger on a forum!

JasonM, I looked at the TreasureChest source code (although breifly), and noticed that when I ran it the "Mip filter reflections" option was disabled (greyed out) in the menu. Is this a driver issue? Is it because of the same problems that I am having? Thanks for helping me out, BTW.
 
Last edited:
"You mean the back-buffer of the screen (i.e. the original render target) ?"

Yes... and it is very bizarre.

I checked the pointer that is being returned by GetRenderTarget(), It does not appear to be the same as the pointer to the back buffer. I suppose I should probably try locking the surfaces so I can get a pointer to the actual memory just to be sure... But it may be that GetRenderTarget() is the function that is having problems... I will try to find out.

"By the way Boke, thanks a lot for spending the time to try this out."
No problem!
 
JasonM, do you have any new info to help me out? Can you explain the weird behaviour Boke and I have observed? It's been a good 3 weeks since you're last post, and this subject is sort of important for me to get decent looking dynamic textures without any crazy aliasing (except with CPU filtering, which is very slow).
 
I'm afraid I can't explain the behavior as I've been swamped with launch and SIGGRAPH the past several weeks. Why would you need to filter with the CPU? The treasure chest filters six 512x512 faces of a cube map every frame and runs quite well. Just grab the code from there, as suggested before.

-Jason
 
Mintmaster said:


JasonM, I looked at the TreasureChest source code (although breifly), and noticed that when I ran it the "Mip filter reflections" option was disabled (greyed out) in the menu. Is this a driver issue? Is it because of the same problems that I am having? Thanks for helping me out, BTW.

Ah.. thats cuz mipmapped cube maps are turned off currently in the driver, but not because of this issue.. I havent run into this issue myself when I did this very thing, so i'm not sure whats going on. What is your render state when you draw the quad? do you have the texture set as active when trying to apply the SetRenderTarget? are there any warnings out of the d3d runtime when in debug mode? crank up the spam level by one and check again? (dont go to max.. its just too much hehe) Check the num levels on the mip chain to see if its greater that 1. i doubt thats it at all, but it may have not made a mip chain.. eh.. just a couple stabs in the dark.

(Sorry.. i've been so busy that i havent checked here in over a month as well..)

also BTW, releasing the surface right after setting it as a render target is fine.. as long as you never reference it again.. The SetRenderTarget call itself increments the ref count, so there's no worries of it disappearing on you.
 
Back
Top