Imagination PowerVR SDK Blog

BC3/DXT within PVR3 container format.


#1

From the PVR file format specification, the texture data part (after the header and the metadata) is said to be;


for each MIP-Map Level in MIP-Map Count<br />
for each Surface in Num. Surfaces<br />
for each Face in Num. Faces<br />
for each Slice in Depth<br />
for each Row in Height<br />
for each Pixel in Width<br />
Byte data[Size_Based_On_PixelFormat]<br />
end<br />
end<br />
end<br />
end<br />
end<br />
end
```<br />
<br />
Is there anything more specific than this or worth noting about when the texture might be in BC3 format (or really, any DXT format)?  In moving from the PVR2 container format to this I am iterating through mip-mips in the above way (and mipmaps/faces for cubemaps) and just getting complete garbage despite the fact that the texture is okay within the TexTool.<br />
<br />
Thanks<br />

#2

Hi Chump,



So for all compressed data the layout is a little different, though still effectively the same. All compressed data formats have a “minimum width/height” which is the lowest number of pixels than can be represented by any given block/region in a compressed image. There is a function in our tools, “PVRTGetFormatMinDims” which lists these dimensions for each format if you need a reference.



The first step is to align the width and heigh values to these minimum width/heights, so for a min width/height of 4, a 511x511 image becomes 512x512. This constitutes any texture padding done to meet the compression format’s requirements, and is essentially garbage data, but it needs to exist for the format to be valid. All you then need to do is work out the number of blocks/regions from this, and copy that many. At this point there are only 2D compression formats, so depth will function as a number of individual slices, and can for now be treated normally.



For each individual block/region, the bits per pixel are listed in another function; “PVRTGetBitsPerPixel” which helps determine the block/region size.



So to update the specification, it looks like this:

for each MIP-Map Level in MIP-Map Count

for each Surface in Num. Surfaces

for each Face in Num. Faces

for each Block/Region by aligned Depth (Based_On_PixelFormat)

for each Block/Region by aligned Height (Based_On_PixelFormat)

for each Block/Region by aligned Width (Based_On_PixelFormat)

Byte data[Size_Based_On_PixelFormat]

end

end

end

end

end

end



I hope that makes sense?



Let me know if you need further clarification. I’ll also file a bug to update the documentation with an explanation.



Regards,

Tobias


#3

Maybe I should have been clearer in the original post and mentioned 'is there anything more specific than this, but for the exception of the three inner loops which wouldn’t really apply being block based.



Or putting it another way, this is what I’m having a problem with.



for each MIP-Map Level in MIP-Map Count

for each Surface in Num. Surfaces

for each Face in Num. Faces

glCompressedTeximage2D(Level, etc)

end

end

end





Only in my case, I have no Surfaces and only have faces for Cube maps. In the cases of a plain old 2d textures only the outer loop is relevant, which still isn’t working for me.



Naturally in iterating through the above logic there’s a pointer being adjusted to step through the data but the size of the adjustment looks to be correct and actually based on a prior PVR2 and DDS implementation to calculate.



In fact, this new PVR3 version is very similar to the prior version, it looks at the header, moves the pointer beyond that and the meta data to get to the texture data and then goes through the loops as above. If I understand correctly, past the header and meta the only difference between PVR2 and PVR3 is that the ordering of those for each loops has changed. IIRC the ‘for each MIP-Map Level in MIP-Map Count’ used to be the inner loop in PVR2.



So I have almost the same code as before for when it gets the texture data part of the PVR3 format, but with the loops switched round - all size calculations have not changed and appear to be correct for DXT given they work in the DDS and PVR2 implementations and appear to be the correct size in debugging/single stepping.



But I’m getting garbage of course.



Has any additional padding/alignment been put in outside of that for non pow2 textures (and the textures I’m processing are pow2 anyway)?



#4

Hi Chump,



Ah ok, you’re right when you say that the MIP Map part has moved outward - it’s to be more in line with OpenGL, since it’s easier to load into GL this way around, and no harder to load it into DirectX. Have you looked at how the PVRtools code handles this?



As for NPOT padding etc., there’s no padding beyond what’s needed to fill out the blocks themselves, hence what I mentioned above. PVR files continue to be tightly packed with no support for additional padding. If you want to post some code/pseudo code, either here (or dm me, or to DevTech@imgtec.com) I can have a look at it if you want?



Thanks,

Tobias