Spaces:
Runtime error
Runtime error
// Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. | |
// | |
// NVIDIA CORPORATION and its licensors retain all intellectual property | |
// and proprietary rights in and to this software, related documentation | |
// and any modifications thereto. Any use, reproduction, disclosure or | |
// distribution of this software and related documentation without an express | |
// license agreement from NVIDIA CORPORATION is strictly prohibited. | |
//------------------------------------------------------------------------ | |
// Mip stack construction and access helpers. | |
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)) // Stop at first impossible size. | |
{ | |
// Current level. | |
level += 1; | |
// Determine if downsampling fails. | |
ew = ew || (w > 1 && (w & 1)); | |
eh = eh || (h > 1 && (h & 1)); | |
// Downsample. | |
if (w > 1) w >>= 1; | |
if (h > 1) h >>= 1; | |
// Append level size to error message. | |
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) | |
{ | |
// No levels at all? | |
if (p.mipLevelLimit == 0) | |
{ | |
p.mipLevelMax = 0; | |
return 0; | |
} | |
// Current level size. | |
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) | |
{ | |
// Current level. | |
level += 1; | |
// Quit if cannot downsample. | |
if ((w > 1 && (w & 1)) || (h > 1 && (h & 1))) | |
raiseMipSizeError(NVDR_CTX_PARAMS, p); | |
// Downsample. | |
if (w > 1) w >>= 1; | |
if (h > 1) h >>= 1; | |
mipOffsets[level] = mipTotal; // Store the mip offset (#floats). | |
mipTotal += w * h * p.texDepth * c; | |
// Hit the level limit? | |
if (p.mipLevelLimit >= 0 && level == p.mipLevelLimit) | |
break; | |
} | |
p.mipLevelMax = level; | |
return mipTotal; | |
} | |
//------------------------------------------------------------------------ | |