Jump to content
  • Advertisement
Sign in to follow this  
coderchris

mipmap locking / tex2Dlod gotchas?

This topic is 3787 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am doing a simple test to see if my code to load some image data into a specific mip map of a texture is working, and its proving to be surprisingly painfull... Basically, all im doing is taking my image data, locking the 2ND mip map level of a texture and memcpy'ing the data in there. To test, im drawing a full screen quad that uses a simple pixel shader written in CG (not HLSL):

sampler2D decal = sampler_state
{
    WrapS = Clamp;
    WrapT = Clamp;
    MinFilter = LinearMipMapLinear;
    MagFilter = Linear;
};

...

void simplePS(float2 texCoords : TEXCOORD0, out float4 outColor : COLOR)
{
	outColor = tex2Dlod(decal, float4(texCoords, 0.0, 1.0));
}

...
What I intended this to do was fetch the color from the 2ND mip map level of my texture (which I loaded the image into) and draw it. What I get is black... What is more piculiar is that if I instead load that image into the first, top most mip map instead of the second, and use the same exact shader, It draws the image. This case should have been black, since I loaded NOTHING into the rest of the mip map chain. Whats more is that if I change the shader to fetch from the 6th mip level for example, I still get the original image... Its almost like tex2Dlod doesnt care what mip level I want, it always fetches from the first one. So, im all kinds of confused now, I cant seem to figure out if its a bug with my usage of lock, or if its something with CG Any ideas?

Share this post


Link to post
Share on other sites
Advertisement
Your code looks fine to me.

Maybe you're doing something wrong when writing to the texture (e.g. some pitch related problems). Also, what texture format are you using - ARGB8 or some compresses?

Posting the code that copies the data to the mip-level might help.

Also, not copying any data to some mip-level doesn't mean it should be black. I'd rather expect some random garbage in that case.

Share this post


Link to post
Share on other sites
Im using ARGB8 format;

Here is how I create the texture:

int levels = max(log2(width), log2(height)) + 1;
d3dDevice->CreateTexture(width, height, levels, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);


and heres how i am writing to the texture:


void writeData(void* data, int level)
{
D3DLOCKED_RECT lockedRect;
if (texture->LockRect(level, &lockedRect, NULL, 0) == D3D_OK)
{
int myPitch = getWidth(level) * 4;
for (int i=0;i<getHeight(level);i++)
{
memcpy((char*)lockedRect.pBits + lockedRect.Pitch * i,
(char*)data + myPitch*i, myPitch);
}
texture->UnlockRect(level);
}
}


getWidth and getHeight just return the width/height of a specific level

Share this post


Link to post
Share on other sites
Try locking the top level with a scaled version of your lock rectangle. According to UpdateTexture, "For performance reasons, dirty regions are only recorded for level zero of a texture. For sublevels, it is assumed that the corresponding (scaled) rectangle or box is also dirty"

If that doesn't help, try passing the D3DUSAGE_DYNAMIC to your texture creation. You'll need to move to POOL_DEFAULT for that too, but the surface is still lockable.

Share this post


Link to post
Share on other sites
I could just lock the top level and let auto mip generator take care of making the mip maps, but, I intensionally want to put different data into each of the mip levels, so that isnt really an option

I tried using dynamic instead of managed, but i get the same results...

Share this post


Link to post
Share on other sites
Your code still looks fine to me.

What you can do test what mip-level gets actually rendered is you could create your texture of some small dimensions, e.g. 8x8 and disable bilinear filtering so you can see the texels and you can count them - so you can tell which mip level you render. Fill that texture with some checkerboard pattern using different colors for each mip-level.

Once you've got that running try changing the LOD level in call to tex2Dlod to 0, 1, 2, 3. This might give you some idea whether it's tex2Dlod operation problem or whether it's a problem with properly loading the contents for mip-levels on C++ side.

The other, simplier thing you could do is to save your texture as DDS using D3DXSaveTextureToFile helper function. Then open your texture using DirectX Texture Tool and see what the content of each mip-level is.

Share this post


Link to post
Share on other sites
D3D doesn't realize you've locked a lower mip, and so it never updates the texture on the GPU unless you lock level 0. I'm not suggesting auto mip mapping, and only writing to level 0. Lock level 1, write data, unlock, multiply the rect to be a level 0 rect, and lock that, and unlock it. D3D will update the appropriate level 0 rect, and all the mips. If you haven't asked for auto mip generation in your usage, your wanted data should still be there and get uploaded.

Another option would be to create a system memory texture, write to that, and use UpdateTexture to upload the texture to a GPU based texture.

Share this post


Link to post
Share on other sites
Quote:

The other, simplier thing you could do is to save your texture as DDS using D3DXSaveTextureToFile helper function. Then open your texture using DirectX Texture Tool and see what the content of each mip-level is.


thats a good idea, thanks

I did just that, and it looks as though im able to get a different color for each mip level. So, it looks like its not a problem with the actual texture, rather CG


Something strange has come up though; i tried following your suggestion of turning off filtering all together (eg just point sampling the texture) but i catn seem to turn it off!

I changed the sampler to

sampler2D decal = sampler_state
{
WrapS = Clamp;
WrapT = Clamp;
MinFilter = Nearest;
MagFilter = Nearest;
};


And it still wants to use bilinear filtering for some reason...

Whats really odd is that if I put garbage for the MinFilter/MagFilter, like something that clearely shouldnt compile, it still runs! wierd..

any ideas?

Share this post


Link to post
Share on other sites
Quote:
Original post by coderchris
Something strange has come up though; i tried following your suggestion of turning off filtering all together (eg just point sampling the texture) but i catn seem to turn it off!

I changed the sampler to

sampler2D decal = sampler_state
{
WrapS = Clamp;
WrapT = Clamp;
MinFilter = Nearest;
MagFilter = Nearest;
};


And it still wants to use bilinear filtering for some reason...

Whats really odd is that if I put garbage for the MinFilter/MagFilter, like something that clearely shouldnt compile, it still runs! wierd..

any ideas?


I heard people are having some strange issues with CG, but wouldn't expect it to compile even if you ask it to compile garbage code.

I haven't done too much with CG, so I'm just guessing. Maybe try get rid of sampler_state block and stay with just "sampler2D decal;" and try to set sampler filtering using D3D interface.

Share this post


Link to post
Share on other sites
Thanks for the help so far guys.

So, Iv been posting on the nvidia forum asking them if this is a bug in CG, but got no answers... So I just got fed up with CG and droped it altogether, and just finished switching over to good old HLSL

But..

For some strange reason, I cant seem to get a valid handle to the first technique in my effect....

Whenever I run it, it breaks out on a call to ID3DXEffect::GetParameterDesc,
however through debuging I have determined that the handle I am passing it is garbage. I get the handle using ID3DXEffect::FindNextValidTechnique

And like I said, the "next valid technique" handle object is garbage (not even NULL!). It even returns D3D_OK...

Am I missing something here?

Here is how I get the handle to the technique:

D3DXHANDLE handle = NULL;
D3DXPARAMETER_DESC desc;

if (effect->FindNextValidTechnique(NULL, &handle) == D3D_OK)
{
if (handle != NULL)
effect->GetParameterDesc(handle, &desc); // crashes here, handle is garbage
}


Here is the complete shader I am using (just in case):

texture decal;

sampler decalSampler = sampler_state
{
Texture = <decal>;
MinFilter = Point;
MagFilter = Point;
MipFilter = Point;
AddressU = Wrap;
AddressV = Wrap;
};

void simpleVS1(float4 position : POSITION, float2 texCoords : TEXCOORD0,
out float4 outPos : POSITION, out float2 outTexCoords : TEXCOORD0)
{
outPos = position;
outTexCoords = texCoords;
}

void simplePS1(float2 texCoords : TEXCOORD0, out float4 outColor : COLOR)
{
outColor = tex2Dlod(decalSampler, float4(texCoords, 0.0, 0.0));
}

technique simpleTechnique1
{
pass P0
{
VertexShader = compile vs_3_0 simpleVS1();
PixelShader = compile ps_3_0 simplePS1();
}
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!