Last active
June 22, 2018 17:47
-
-
Save Triang3l/4cc2f5c2901cd4e3ad2926c79c4f6858 to your computer and use it in GitHub Desktop.
GetMipTailLevelOffsetCoords from XGraphics reversed for Xenia
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Interesting :) Thanks!