|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "framework.h" |
|
#include "texture.h" |
|
|
|
|
|
|
|
|
|
void raiseMipSizeError(NVDR_CTX_ARGS, const TextureKernelParams& p) |
|
{ |
|
char buf[1024]; |
|
int bufsz = 1024; |
|
|
|
std::string msg = "Mip-map size error - cannot downsample an odd extent greater than 1. Resize the texture so that both spatial extents are powers of two, or limit the number of mip maps using max_mip_level argument.\n"; |
|
|
|
int w = p.texWidth; |
|
int h = p.texHeight; |
|
bool ew = false; |
|
bool eh = false; |
|
|
|
msg += "Attempted mip stack construction:\n"; |
|
msg += "level width height\n"; |
|
msg += "----- ----- ------\n"; |
|
snprintf(buf, bufsz, "base %5d %5d\n", w, h); |
|
msg += buf; |
|
|
|
int mipTotal = 0; |
|
int level = 0; |
|
while ((w|h) > 1 && !(ew || eh)) |
|
{ |
|
|
|
level += 1; |
|
|
|
|
|
ew = ew || (w > 1 && (w & 1)); |
|
eh = eh || (h > 1 && (h & 1)); |
|
|
|
|
|
if (w > 1) w >>= 1; |
|
if (h > 1) h >>= 1; |
|
|
|
|
|
snprintf(buf, bufsz, "mip %-2d ", level); |
|
msg += buf; |
|
if (ew) snprintf(buf, bufsz, " err "); |
|
else snprintf(buf, bufsz, "%5d ", w); |
|
msg += buf; |
|
if (eh) snprintf(buf, bufsz, " err\n"); |
|
else snprintf(buf, bufsz, "%5d\n", h); |
|
msg += buf; |
|
} |
|
|
|
NVDR_CHECK(0, msg); |
|
} |
|
|
|
int calculateMipInfo(NVDR_CTX_ARGS, TextureKernelParams& p, int* mipOffsets) |
|
{ |
|
|
|
if (p.mipLevelLimit == 0) |
|
{ |
|
p.mipLevelMax = 0; |
|
return 0; |
|
} |
|
|
|
|
|
int w = p.texWidth; |
|
int h = p.texHeight; |
|
|
|
int mipTotal = 0; |
|
int level = 0; |
|
int c = (p.boundaryMode == TEX_BOUNDARY_MODE_CUBE) ? (p.channels * 6) : p.channels; |
|
mipOffsets[0] = 0; |
|
while ((w|h) > 1) |
|
{ |
|
|
|
level += 1; |
|
|
|
|
|
if ((w > 1 && (w & 1)) || (h > 1 && (h & 1))) |
|
raiseMipSizeError(NVDR_CTX_PARAMS, p); |
|
|
|
|
|
if (w > 1) w >>= 1; |
|
if (h > 1) h >>= 1; |
|
|
|
mipOffsets[level] = mipTotal; |
|
mipTotal += w * h * p.texDepth * c; |
|
|
|
|
|
if (p.mipLevelLimit >= 0 && level == p.mipLevelLimit) |
|
break; |
|
} |
|
|
|
p.mipLevelMax = level; |
|
return mipTotal; |
|
} |
|
|
|
|
|
|