Skip to content

Instantly share code, notes, and snippets.

@Triang3l
Last active June 22, 2018 17:47
Show Gist options
  • Save Triang3l/4cc2f5c2901cd4e3ad2926c79c4f6858 to your computer and use it in GitHub Desktop.
Save Triang3l/4cc2f5c2901cd4e3ad2926c79c4f6858 to your computer and use it in GitHub Desktop.
GetMipTailLevelOffsetCoords from XGraphics reversed for Xenia
// Reconstructed for Xenia by Triang3l.
DWORD D3D::AlignTextureDimensions(DWORD * pWidth, DWORD * pHeight, DWORD * pDepth,
DWORD BitsPerPixel, DWORD GpuFormat, DWORD GpuDimension, BOOL Tiled) {
DWORD widthAlignmentBlocks = 32;
DWORD heightAlignmentBlocks = (GpuDimension == GPU_DIMENSION_1D ? 1 : 32);
DWORD depthAlignment = (GpuDimension == GPU_DIMENSION_3D ? 4 : 1);
DWORD blockWidth, blockHeight;
D3D::BlockSizeOfGpuFormat(GpuFormat, &blockWidth, &blockHeight);
if (!Tiled) {
widthAlignmentBlocks = std::max(256 / (blockWidth * blockHeight * BitsPerPixel / 8), (DWORD) 32);
}
DWORD widthAlignment = widthAlignmentBlocks * blockWidth;
DWORD heightAlignment = heightAlignmentBlocks * blockHeight;
DWORD widthAligned = (*pWidth + widthAlignment - 1) & (widthAlignment - 1);
DWORD heightAligned = (*pHeight + heightAlignment - 1) & (heightAlignment - 1);
DWORD depthAligned = (*pDepth + depthAlignment - 1) & (depthAlignment - 1);
*pWidth = widthAligned;
*pHeight = heightAligned;
*pDepth = depthAligned;
DWORD textureSize = widthAligned * BitsPerPixel / 8 * heightAligned;
if (GpuDimension == GPU_DIMENSION_3D) {
// Page-align the whole 3D texture.
textureSize = ((textureSize * depthAligned) + 4095) & ~((DWORD) 4095);
} else {
// Page-align each slice.
textureSize = ((textureSize + 4095) & ~((DWORD) 4095)) * depthAligned;
}
return textureSize;
}
DWORD D3D::GetMipTailLevelOffsetCoords(DWORD Level, DWORD Width, DWORD Height, DWORD Depth,
DWORD TailRowPitch, DWORD TailSlicePitch, DWORD GpuFormat,
UINT * pOffsetX, UINT * pOffsetY, UINT * pOffsetZ) {
DWORD offsets[3] = { 0 };
DWORD blockWidth, blockHeight;
D3D::BlockSizeOfGpuFormat(GpuFormat, &blockWidth, &blockHeight);
DWORD bitsPerPixel = (BYTE) D3D::g_FormatTable[GpuFormat];
int logWidth = 32 - __lzcnt(Width - 1);
int logHeight = 32 - __lzcnt(Height - 1);
int logDepth = 32 - __lzcnt(Depth - 1);
DWORD shortestAxis = logWidth > logHeight;
DWORD packSize[2] = { (DWORD) 1 << logWidth, (DWORD) 1 << logHeight };
if (Level >= 3) {
DWORD longestAxis = !shortestAxis;
offsets[longestAxis] = packSize[longestAxis] >> (Level - 2);
if (offsets[longestAxis] < 4) {
// Never reached for 2D textures - 16x16, the pack size, has the max mip level of 4.
// At level 3, packSize[longestAxis] >> (Level - 2) will be 8, at level 4, it will be 4.
offsets[2] = std::max(logDepth - Level, 1) * 4;
}
// Z offset is 0 otherwise.
} else {
offsets[shortestAxis] = 16 >> Level;
// Z offset is 0.
}
*pOffsetX = offsets[0] / blockWidth;
*pOffsetY = offsets[1] / blockHeight;
*pOffsetZ = offsets[2];
return (offsets[2] * TailSlicePitch) + (offsets[1] * TailRowPitch) + (offsets[0] * blockWidth * bitsPerPixel / 8);
}
DWORD XGRAPHICS::GetMipTailLevelOffsetCoords(UINT Width, UINT Height, UINT Depth,
UINT Level, DWORD GpuFormat, BOOL Tiled, BOOL Border, XGPOINT3D * pOffset) {
int borderSize = Border ? 1 : 0;
int logWidth = (borderSize - __lzcnt(Width - borderSize * 2 - 1)) + 32;
int logHeight = (borderSize - __lzcnt(Height - borderSize * 2 - 1)) + 32
int tailLevel = std::max(std::max(logWidth, logHeight) - 4, 0);
if (Level < tailLevel) {
pOffset->X = pOffset->Y = pOffset->Z = 0;
return 0;
}
int logDepth = (Depth > 1 ? ((borderSize - __lzcnt(Depth - borderSize * 2 - 1)) + 32) : 0);
DWORD tailWidth = (DWORD) 1 << (logWidth - tailLevel);
DWORD tailHeight = (DWORD) 1 << (logHeight - tailLevel);
DWORD tailDepth = (DWORD) 1 << std::max(logDepth - tailLevel, 0);
DWORD bitsPerPixel = (BYTE) D3D::g_FormatTable[GpuFormat];
D3D::AlignTextureDimensions(&tailWidth, &tailHeight, &tailDepth,
bitsPerPixel, GpuFormat, GPU_DIMENSION_2D, Tiled);
DWORD tailRowPitch = tailWidth * bitsPerPixel / 8;
DWORD tailSlicePitch = tailHeight * tailRowPitch;
if (Depth <= 1) {
tailSlicePitch = (tailSlicePitch + 4095) & ~((DWORD) 4095);
}
UINT offsetX, offsetY, offsetZ;
DWORD offset = D3D::GetMipTailLevelOffsetCoords(Level - tailLevel, tailWidth, tailHeight, tailDepth,
tailRowPitch, tailSlicePitch, GpuFormat, &offsetX, &offsetY, &offsetZ);
pOffset->X = offsetX;
pOffset->Y = offsetY;
pOffset->Z = offsetZ;
return offset;
}
@Parovozik
Copy link

Interesting :) Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment