Compare commits

..

No commits in common. "feature/explicit-mips" and "main" have entirely different histories.

View file

@ -41,20 +41,20 @@ const std::map<std::string, std::tuple<std::string, int, vk::Format>> formats =
{"BC7_SRGB", {"8 bit RGBA - Good general purpose. 16 bytes per block.", 16, vk::Format::eBc7SrgbBlock}}
};
const std::string usage = "[cube|array] <input> [input2, input3...] <output> <format> [fast|normal|slow|veryslow] [explicitmips]";
const std::string usage = "[cube|array] <input> [input2, input3...] <output> <format> [fast|normal|slow|veryslow]";
int main(int argc, char ** argv)
{
ISPCInit();
if (argc < 4) {
std::cerr << "Usage: " << argv[0] << " " << usage << std::endl;
std::cerr << "Formats:" << std::endl;
std::cout << "Usage: " << argv[0] << " " << usage << std::endl;
std::cout << "Formats:" << std::endl;
for (auto & formatName : formatOrder) {
auto format = formats.at(formatName);
std::cerr << " " << formatName << " - " << std::get<0>(format) << std::endl;
std::cout << " " << formatName << " - " << std::get<0>(format) << std::endl;
}
return -1;
return 1;
}
int numInputs = argc - 3;
@ -72,20 +72,10 @@ int main(int argc, char ** argv)
std::string speedString(argv[argc - 1]);
std::string formatString;
int speed = 2;
bool explicitmips = false;
int formatPosition = -1;
if (speedString == "explicitmips") {
speedString = std::string(argv[argc - 2]);
numInputs -= 1;
formatPosition -= 1;
explicitmips = true;
}
if (speedString == "fast" || speedString == "normal" || speedString == "slow" || speedString == "veryslow") {
formatString = std::string(argv[argc - 2]);
numInputs -= 1;
formatPosition -= 1;
if (speedString == "slow") {
speed = 1;
@ -96,41 +86,29 @@ int main(int argc, char ** argv)
} else {
speed = 2;
}
} else {
formatString = std::string(argv[argc - 1]);
}
formatString = std::string(argv[argc + formatPosition]);
if (numInputs < 1) {
std::cerr << "Usage: " << argv[0] << usage << " " << std::endl;
return -1;
std::cout << "Usage: " << argv[0] << usage << " " << std::endl;
return 1;
}
if (explicitmips) {
if (option == "cube" && numInputs % 6 != 0) {
std::cerr << "Cube maps must have a multiple of 6 inputs." << std::endl;
return -1;
}
} else {
if (option == "cube" && numInputs != 6) {
std::cerr << "Cube maps must have 6 inputs." << std::endl;
return -1;
}
std::cout << "Cube maps must have 6 inputs." << std::endl;
return 1;
}
if (option == "array" && numInputs < 2) {
std::cerr << "Array maps must have at least 2 inputs." << std::endl;
return -1;
}
if (option == "array" && explicitmips) {
std::cerr << "Explicit mips are not supported for arrays." << std::endl;
return -1;
std::cout << "Array maps must have at least 2 inputs." << std::endl;
return 1;
}
if (formats.find(formatString) == formats.end()) {
std::cerr << "Invalid format: " << formatString << std::endl;
std::cerr << usage << std::endl;
std::cerr << "Formats:" << std::endl;
std::cout << "Invalid format: " << formatString << std::endl;
std::cout << usage << std::endl;
std::cout << "Formats:" << std::endl;
for (auto & formatName : formatOrder) {
auto format = formats.at(formatName);
std::cout << " " << formatName << " - " << std::get<0>(format) << std::endl;
@ -210,58 +188,8 @@ int main(int argc, char ** argv)
ldrLevelBlocks.resize(numInputs);
}
unsigned int levelCount;
int numFaces = 1;
uint32_t levelCount;
int topLevelWidth, topLevelHeight;
if (option == "cube") {
numFaces = 6;
}
if (explicitmips) {
levelCount = numInputs / numFaces;
for (int face = 0; face < numFaces; face++) {
int levelWidth = 0, levelHeight = 0;
for (unsigned int level = 0; level < levelCount; level++) {
std::cout << "Loading/scaling face " << face << ", level " << level << ", " << inputs[face * levelCount + level] << std::endl;
if (hdr) {
hdrBufferA = stbi_loadf(inputs[face * levelCount + level].c_str(), &width, &height, &channels, forcedChannels);
} else {
ldrBufferA = stbi_load(inputs[face * levelCount + level].c_str(), &width, &height, &channels, forcedChannels);
}
if (level == 0) {
levelWidth = width;
levelHeight = height;
topLevelWidth = width;
topLevelHeight = height;
} else {
if (width != levelWidth || height != levelHeight) {
std::cout << "Input " << inputs[face * levelCount + level] << " for face " << face << ", level " << level << "dimensions " << width << "x" << height << " do not match expected " << levelWidth << "x" << levelHeight << std::endl;
return -1;
}
}
if (hdr) {
hdrLevels[face].push_back(std::vector<float>(hdrBufferA, hdrBufferA + width * height * forcedChannels));
stbi_image_free(hdrBufferA);
} else {
ldrLevels[face].push_back(std::vector<uint8_t>(ldrBufferA, ldrBufferA + width * height * forcedChannels));
stbi_image_free(ldrBufferA);
}
levelWidth = std::max(1, (int)floorf((float)levelWidth / 2));
levelHeight = std::max(1, (int)floorf((float)levelHeight / 2));
}
}
width = topLevelWidth;
height = topLevelHeight;
} else {
for (int input = 0; input < numInputs; input++) {
int level = 0;
@ -339,6 +267,9 @@ int main(int argc, char ** argv)
level++;
}
oldWidth = width;
oldHeight = height;
level = 0;
if (hdr) {
free(hdrBufferA);
delete[] hdrBufferB;
@ -347,7 +278,6 @@ int main(int argc, char ** argv)
delete[] ldrBufferB;
}
}
}
bc6h_enc_settings bc6henc;
bc7_enc_settings bc7enc;
@ -386,19 +316,19 @@ int main(int argc, char ** argv)
std::tuple<std::string, int, vk::Format> format = formats.find(formatString)->second;
size_t blockSize = std::get<1>(format);
for (int face = 0; face < numFaces; face++) {
for (int input = 0; input < numInputs; input++) {
if (numInputs > 1) {
if (option == "cube") {
std::cout << "Face " << face << std::endl;
std::cout << "Face " << input << std::endl;
} else {
std::cout << "Layer " << face << std::endl;
std::cout << "Layer " << input << std::endl;
}
}
if (hdr) {
hdrLevelBlocks[face].resize(levelCount);
hdrLevelBlocks[input].resize(levelCount);
} else {
ldrLevelBlocks[face].resize(levelCount);
ldrLevelBlocks[input].resize(levelCount);
}
int level = 0;
@ -410,7 +340,7 @@ int main(int argc, char ** argv)
unsigned int blocksHeight = (oldHeight + 3) / 4;
if (hdr) {
hdrLevelBlocks[face][level].resize(blocksWidth * blocksHeight);
hdrLevelBlocks[input][level].resize(blocksWidth * blocksHeight);
for (unsigned int y = 0; y < blocksHeight; y++) {
for (unsigned int x = 0; x < blocksWidth; x++) {
@ -422,7 +352,7 @@ int main(int argc, char ** argv)
unsigned int clampedX = std::min(pixelX, (unsigned int)oldWidth - 1);
for (int channel = 0; channel < copyChannels; channel++) {
float value = hdrLevels[face][level][(clampedY * oldWidth + clampedX) * forcedChannels + channel];
float value = hdrLevels[input][level][(clampedY * oldWidth + clampedX) * forcedChannels + channel];
if (value < 0.0f) {
value = 0.0f;
}
@ -436,11 +366,11 @@ int main(int argc, char ** argv)
}
}
hdrLevelBlocks[face][level][blocksWidth * y + x] = block;
hdrLevelBlocks[input][level][blocksWidth * y + x] = block;
}
}
} else {
ldrLevelBlocks[face][level].resize(blocksWidth * blocksHeight);
ldrLevelBlocks[input][level].resize(blocksWidth * blocksHeight);
for (unsigned int y = 0; y < blocksHeight; y++) {
for (unsigned int x = 0; x < blocksWidth; x++) {
@ -452,12 +382,12 @@ int main(int argc, char ** argv)
unsigned int clampedX = std::min(pixelX, (unsigned int)oldWidth - 1);
for (int channel = 0; channel < copyChannels; channel++) {
block[((pixelY % 4) * 4 + (pixelX % 4)) * copyChannels + channel] = ldrLevels[face][level][(clampedY * oldWidth + clampedX) * forcedChannels + channel];
block[((pixelY % 4) * 4 + (pixelX % 4)) * copyChannels + channel] = ldrLevels[input][level][(clampedY * oldWidth + clampedX) * forcedChannels + channel];
}
}
}
ldrLevelBlocks[face][level][blocksWidth * y + x] = block;
ldrLevelBlocks[input][level][blocksWidth * y + x] = block;
}
}
}
@ -469,19 +399,16 @@ int main(int argc, char ** argv)
oldWidth = std::max(1, (int)floorf((float)oldWidth / 2));
oldHeight = std::max(1, (int)floorf((float)oldHeight / 2));
level++;
}
if (level >= levelCount) {
break;
}
}
/* Compress */
levelBlocksCompressed[face].resize(levelCount);
levelBlocksCompressed[input].resize(levelCount);
for (unsigned int l = 0; l < levelCount; l++) {
if (hdr) {
levelBlocksCompressed[face][l].resize(hdrLevelBlocks[face][l].size() * blockSize);
levelBlocksCompressed[input][l].resize(hdrLevelBlocks[input][l].size() * blockSize);
} else {
levelBlocksCompressed[face][l].resize(ldrLevelBlocks[face][l].size() * blockSize);
levelBlocksCompressed[input][l].resize(ldrLevelBlocks[input][l].size() * blockSize);
}
}
@ -496,49 +423,49 @@ int main(int argc, char ** argv)
for (unsigned int l = 0; l < levelCount; l++) {
unsigned int blocksPerThread;
if (hdr) {
blocksPerThread = hdrLevelBlocks[face][l].size() / numThreads;
blocksPerThread = hdrLevelBlocks[input][l].size() / numThreads;
} else {
blocksPerThread = ldrLevelBlocks[face][l].size() / numThreads;
blocksPerThread = ldrLevelBlocks[input][l].size() / numThreads;
}
unsigned int startBlock = t * blocksPerThread;
unsigned int endBlock = startBlock + blocksPerThread;
if (hdr) {
if (t == numThreads - 1) {
endBlock = hdrLevelBlocks[face][l].size();
endBlock = hdrLevelBlocks[input][l].size();
}
} else {
if (t == numThreads - 1) {
endBlock = ldrLevelBlocks[face][l].size();
endBlock = ldrLevelBlocks[input][l].size();
}
}
for (unsigned int b = startBlock; b < endBlock; b++) {
if (formatString == "BC6H") {
rgba_surface surface;
surface.ptr = (uint8_t *)hdrLevelBlocks[face][l][b].data();
surface.ptr = (uint8_t *)hdrLevelBlocks[input][l][b].data();
surface.width = 4;
surface.height = 4;
surface.stride = copyChannels * 4 * 2;
CompressBlocksBC6H(&surface, &levelBlocksCompressed[face][l][b * blockSize], &bc6henc);
CompressBlocksBC6H(&surface, &levelBlocksCompressed[input][l][b * blockSize], &bc6henc);
} else {
rgba_surface surface;
surface.ptr = ldrLevelBlocks[face][l][b].data();
surface.ptr = ldrLevelBlocks[input][l][b].data();
surface.width = 4;
surface.height = 4;
surface.stride = copyChannels * 4;
if (formatString == "BC1" || formatString == "BC1_SRGB") {
CompressBlocksBC1(&surface, &levelBlocksCompressed[face][l][b * blockSize]);
CompressBlocksBC1(&surface, &levelBlocksCompressed[input][l][b * blockSize]);
} else if (formatString == "BC3" || formatString == "BC3_SRGB") {
CompressBlocksBC3(&surface, &levelBlocksCompressed[face][l][b * blockSize]);
CompressBlocksBC3(&surface, &levelBlocksCompressed[input][l][b * blockSize]);
} else if (formatString == "BC4") {
CompressBlocksBC4(&surface, &levelBlocksCompressed[face][l][b * blockSize]);
CompressBlocksBC4(&surface, &levelBlocksCompressed[input][l][b * blockSize]);
} else if (formatString == "BC5") {
CompressBlocksBC5(&surface, &levelBlocksCompressed[face][l][b * blockSize]);
CompressBlocksBC5(&surface, &levelBlocksCompressed[input][l][b * blockSize]);
} else if (formatString == "BC7" || formatString == "BC7_SRGB") {
CompressBlocksBC7(&surface, &levelBlocksCompressed[face][l][b * blockSize], &bc7enc);
CompressBlocksBC7(&surface, &levelBlocksCompressed[input][l][b * blockSize], &bc7enc);
}
}
@ -549,9 +476,9 @@ int main(int argc, char ** argv)
if (l == maxLevel) {
float progress;
if (hdr) {
progress = (float)completedBlocks[l] / hdrLevelBlocks[face][l].size();
progress = (float)completedBlocks[l] / hdrLevelBlocks[input][l].size();
} else {
progress = (float)completedBlocks[l] / ldrLevelBlocks[face][l].size();
progress = (float)completedBlocks[l] / ldrLevelBlocks[input][l].size();
}
int barWidth = 70;
@ -576,9 +503,9 @@ int main(int argc, char ** argv)
}
if (hdr) {
hdrLevelBlocks[face].clear();
hdrLevelBlocks[input].clear();
} else {
ldrLevelBlocks[face].clear();
ldrLevelBlocks[input].clear();
}
int barWidth = 70;
@ -685,13 +612,13 @@ int main(int argc, char ** argv)
fh.seekp(levelOffsetBytePosition + (std::ofstream::pos_type)(level * 24));
uint64_t byteOffset = levelBytePosition;
fh.write((char *)&byteOffset, sizeof(byteOffset));
uint64_t byteLength = levelBlocksCompressed[0][level].size() * faceCount;
uint64_t byteLength = levelBlocksCompressed[0][level].size() * numInputs;
fh.write((char *)&byteLength, sizeof(byteLength));
fh.write((char *)&byteLength, sizeof(byteLength));
fh.seekp(levelBytePosition);
for (int face = 0; face < faceCount; face++) {
fh.write((char *)levelBlocksCompressed[face][level].data(), levelBlocksCompressed[face][level].size());
for (int input = 0; input < numInputs; input++) {
fh.write((char *)levelBlocksCompressed[input][level].data(), levelBlocksCompressed[input][level].size());
}
}