Hi, just downloaded the font component. I'm getting an error (see below) when I run the demo, it's on the this.arial24 = this.content.Load<BitmapFont>("Content/Arial-24"); line.
Error Message:
The device does not support creating a texture of the given format with the given ResourceUsage.
Any ideas?
Feel the fear and do it
Feel the fear and do it anyway
Might be a graphics card specific issue
The font textures are using the Alpha-8 pixel format.
I assumed just about any graphics card would support this format, but maybe I'm mistaken and I have to provide a fallback path.
Could you try running the following code snippet in a fresh XNA application to validate my suspicion?
graphicsDevice,
256,
256,
1,
ResourceUsage.Dynamic,
SurfaceFormat.Alpha8,
ResourceManagementMode.Manual
);
Just tried the code and it
Just tried the code and it produces the same error, looks like my card doesn't support Alpha8.
Feel the fear and do it anyway
May I ask what make and
May I ask what make and model your graphics card is?
I'll try providing a fallback to SurfaceFormat.Color in the next release to get around this problem.
Thanks for testing, saves me a lot of headaches getting this component to work correctly now, before I start unleashing my indie games on poor end-users! :)
I've got a HP - Compaq
I've got a HP - Compaq xw6200 Workstation with a NVidia Quadro PCI-E Series card.
Thanks for the help.
Feel the fear and do it anyway
Did you ever find a solution to this?
Hi! We're having the same problem, on an NVIDIAFX 5900 Ultra. What's worrying is it can't seem to support 256x256 RGBA32 textures either :-S I know it's not exactly top of the range but geez :-S
So any insights you have would be much appreciated!
cheers!
lemmy
Asking if I ever found a
Asking if I ever found a solution seems a bit drastic when I had less than 24 hours to get a fix out there ;)
Could it be that you tried
SurfaceFormat.Rgba32instead ofSurfaceFormat.Color?SurfaceFormat.Coloris BGRA32 (notice the order of the color channels) and should pose no problem for a GeForce 5 series card. Even a GeForce (as in, GeForce 1) can handle BGRA32 afaik.So rest assured, I'll provide an updated component that I'm pretty sure will work. If nothing goes wrong, it should be done by this weekend, together with some other nice additions :)
I'm getting this same issue
I'm getting this same issue on the 360 - how hard is it to change the texture format?
Quite simple
I'm still looking for a way to detect whether the graphics device used can cope with Alpha8 textures, so I can avoid having to catch the exception. For now, though, I just added a fallback in the SharedTexture class which catches the exception that occurs.
Maybe I'll just switch to
SurfaceFormat.Colortextures all the way. I'm already planning on extending the importer to import colored bitmap fonts since .ttf basically is black-and-white.I'll provide an updated release soon, probably tomorrow!
woah sorry :) my bad
I didn't see the dates and kind of assumed it was an older post I was replying to ;) thanks for the reply and the fantastic plugin! :) Sorry again!
PS: SurfaceFormat.Color works fine on the GFX card. I had a play with it myself but Managed C++ is too much for my brain ;D
Fixed!
The release I just uploaded should be working perfectly, I switched all
SurfaceFormat.Alpha8surfaces toSurfaceFormat.Color!This means that fonts will use slightly more memory than before, but I can now easily add true color bitmap fonts to the importer at a later time without breaking compatibility :)
Hi I haven't had a chance to
Hi
I haven't had a chance to investigate properly, but I'm still getting an exception on Load<>() on 360:
"The device does not support creating a texture of the given format with the given ResourceUsage."
The XNA docs don't seem to say anything about ResourceUsage.Dynamic, SurfaceFormat.Color or ResourceManagementMode.Manual not being supported on 360 so maybe that means it's a more subtle problem?
Thanks for being so quick with new versions anyway, it'll be great if you can get this working on the 360!
Pete
Could you try this on your XBox 360 please?
I'm having a hard time guessing what might and what might not work on the XBox 360, not owning one myself. This is becoming a real drama :)
Could you try some variations of this code snippet on the XBox 360?
Point textureResolution = new Point(
graphicsDevice.GraphicsDeviceCapabilities.MaxTextureWidth,
graphicsDevice.GraphicsDeviceCapabilities.MaxTextureHeight
);
// No larger than 1024 to avoid becoming a memory hog on systems
// supporting insanely large textures :)
textureResolution.X = Math.Min(textureResolution.X, 1024);
textureResolution.Y = Math.Min(textureResolution.Y, 1024);
Texture2D texture = new Texture2D(
this.graphics.GraphicsDevice,
resolution.X, // width
resolution.Y, // height
1, // mipmap levels
ResourceUsage.Dynamic,
SurfaceFormat.Color,
ResourceManagementMode.Manual
);
It tries to construct a texture with the exact same parameters Nuclex.Fonts uses. Specifically, I'd be interested in what causes it to fail.
I think I can rule the
SurfaceFormatout, so what remains is either thatResourceUsage.Dynamicdoesn't work inResourceManagementMode.Manual(or maybe it is not supported at all), or possibly thatresolution.Xandresolution.Yare not dividable by two.Thanks for any help you can provide!
No joy...
Hi again,
I've tried many variants of the snippet to no avail.
MaxTextureWidth and MaxTextureHeight both come out as 8192. The documentation says that you must use ResourceManagementMode.Manual with ResourceUsage.Dynamic so that looks right.
I've tried ~10 different SurfaceFormats and they all fail with ResourceUsage.Dynamic but as soon as I change it to something else (e.g. Tiled) it works. Unfortunately this is only delaying the inevitable because it then throws an exception later when you try to SetData<byte>() the texture because this requires the texture to be created with ResourceUsage.Dynamic.
So, I don't know if there's something really obvious I'm doing wrong or if I've got a funny Xbox (both unlikely - I'm running your demo project with no mods, and the Xbox has been performing fine with the small amount of other stuff I've done so far (loading models pretty much)). Therefore I guess I have to assume there's something I don't understand about creating Texture2D's on the 360 - I can't believe that ResourceUsage.Dynamic is disallowed - it would be in the docs or on google.
Maybe the official XNA forum might be able to shed some light? Nuclex.Fonts would be a really useful public resource so it should be in someone's interest to look at it!
Sorry not to be the bringer of better news!
Pete
Wow, thanks for taking
Wow, thanks for taking the time to check all this!
I already posted this in the XNA Forum (Texture creation fails on XBox 360), where Shawn Hargreaves recommended to just use
ResourceUsage.None. From my previous DirectX experience, I know that you can still update textures in theD3D_MANAGEDpool normally byLock()ing andD3D_DEFAULTpool textures with theUpdate()method in theIDirect3DDevice9interface.So, depending on how the XNA framework handles Direct3D, it could work if in
GlyphCache.cs, Line #54, the texture creation code is replaced with this:graphicsDevice,
resolution.X,
resolution.Y,
1,
ResourceUsage.None,
SurfaceFormat.Color,
ResourceManagementMode.Automatic
);
I'll put this up in the XNA forum, too, it's time Nuclex.Fonts finally becomes usable on the XBox 360 :)
:( I'm still getting a
:( I'm still getting a System.ArgumentException at line 174 of GlyphCache.cs - i.e. when doing the DrawString call.
If you want to check the
If you want to check the idea Adam Hines just replied with in the XNA forum about not using
Texture2D.SetData() butTexture2D.SetData() , this should do the trick:for(int index = 0; index < glyph.Width * glyph.Height; ++index) {
int bitmapIndex = index * 4;
colors[index] = new Color(
glyph.Bitmap[bitmapIndex + 0],
glyph.Bitmap[bitmapIndex + 1],
glyph.Bitmap[bitmapIndex + 2],
glyph.Bitmap[bitmapIndex + 3]
);
}
this.currentCacheTexture.Texture.SetData<Color>(
0,
new Rectangle(location.X, location.Y, glyph.Width, glyph.Height),
colors,
0,
glyph.Width * glyph.Height, // ATTN: no * 4 anymore
SetDataOptions.None
);
...but I personally wouldn't expect any change in behavior from that.
The solution... probably
So, if what Shawn Hargreaves just proclaimed in the MSN forums holds true, this replacement for the
Texture2D.SetData<>()call should do the trick:byte[] cacheTexture = new byte[
this.currentCacheTexture.Texture.Width * this.currentCacheTexture.Texture.Height * 4
];
this.currentCacheTexture.Texture.GetData<byte>(cacheTexture);
for(int line = 0; line < glyph.Height; ++line) {
Array.Copy(
glyph.Bitmap, line * glyph.Width * 4,
cacheTexture,
((location.Y + line) * this.currentCacheTexture.Texture.Width + location.X) * 4,
glyph.Width * 4
);
}
this.currentCacheTexture.Texture.SetData<byte>(cacheTexture);
}
If that works, however, I'll have to do a total redesign of the Nuclex.Fonts texture allocation system to get to the level of performance Nuclex.Fonts is achieving on the PC. I hope there aren't any more surprises like this one on the XBox side of XNA... :/
Thanks for your ongoing help, Pete, I'll be sure to mention you in the release notes next time!
At last!
Ok - good news is I've finally got it working.
Bad news is I had the same SetData problem with
VertexBatcher so I tried the same fix:
1. Removed ResourceUsage.WriteOnly from vertexBuffer
constructor:
graphicsDevice,
typeof(VertexType),
VertexBatchSize * 4,
ResourceUsage.Dynamic,
ResourceManagementMode.Manual
);
2. Replaced SetData with:
this.vertexBuffer.GetData(tempVertexBuffer);
Array.Copy(
this.vertices, 0, tempVertexBuffer,
this.vertexBufferStartIndex, VertexBatchSize
);
this.vertexBuffer.SetData(tempVertexBuffer);
3. At this point I could see the text quads on screen but
the letter outlines weren't there. I checked the formats
and the problem was that Color is ARGB but the
Nuclex.Fonts.Content.Pipeline.TrueTypeImporter was
saving the glyph bitmaps as RGBA. So I just changed
that to be ARGB:
glyph->Bitmap[index + 0] = *pixelAddress;
glyph->Bitmap[index + 1] = 0xFF;
glyph->Bitmap[index + 2] = 0xFF;
glyph->Bitmap[index + 3] = 0xFF;
And it works! Exceptionally slowly I don't doubt, but
it'll be useful for debugging until they release a
proper component :)
Grr formatting...
Grr formatting...
Great!
Ok, I hereby declare you the hero of the day!
I'll release this as 1.1.1, with the inefficient variant
conditionally compiled only for the XBox 360!
When I can find the time, I'll do a redesign to properly
address these new limitations without copying megabytes
of memory around all the time.
P.S. The <blockcode> tag doesn't work well within
TinyMCE (the wysiwyg editor) yet, I took the liberty of
changing the tags in your post ;)
Cool. Look forward to the
Cool. Look forward to the next release ;) I think I'm gonna stick to PC for the time being - so much easier!
Whoops
Kind of funny, I also ended up creating a fix, not realizing there was a forum/website that had already produced one. I actually ended up taking a bit of a different route, however, and totally threw out the caching code from your Lookup() method and used a Generic.Dictionary to cache Entry objects instead. This allowed me to be able to just create Texture2D objects w/out having to worry about computing texture coordinates, copying bytes all over the place, blah, blah, blah...Most of my other changes were almost identical, though.
Here's mine if you care :)
http://www.ajstach.com/downloads/Golgotha.Nuclex.Fonts.1.1.0.rar
Thanks!
I've already seen your post in the MSDN forums but haven't gotten around to replying yet :)
Thanks for providing me with this. Now I've already got two confirmed-to-be-working XBox 360 codebases I can extract the best of!
Btw, did you compare the performance of your mod against the original code? Is there a noticeable difference? I'd be interested in seeing whether the impact of increased texture switching is negligible or whether it seriously hurts performance.
I'll do some tests myself when I get home this evening!
I don't have any benchmarks
I don't have any benchmarks for you, but I couldn't tell a difference... ;)
I'm not intimate with the plumbing of MDX/XNA/360 (I just started deving on it last night) but I wasn't aware there was a large penalty for texture switching (just updates a pointer, right?)...I was actually more concerned that I would be fragmenting memory with lots of tiny textures.
Also, the Bitmap->ARGB32 conversion I added should happen in an "unsafe" C# method so that fast int pointers and shifts/bit masks can be used...Right now it just does switcheroose at the byte level which isn't particularly fast/sexy. I'm sure there's a much better way to do it. Of course, the fact that textures are being cached alleviates this performance hit, since it's only be done one time for each GlyphBitmap object.
P.S. How far do you plan on taking this component? What you have so far is very, very cool and I was thinking it would be even cooler if it could be tweaked to project onto a (planar) surface...I might attempt this if you don't have the desire and/or care about it. :)
Post new comment