Fix sparse rectification for small textures

This commit is contained in:
Atlante45 2017-10-23 14:48:25 -07:00 committed by Stephen Birarda
parent a5e671e0fd
commit a4b3180271
2 changed files with 37 additions and 56 deletions

View file

@ -19,15 +19,6 @@
#include <QBuffer>
#include <QImageReader>
#if defined(Q_OS_ANDROID)
#define CPU_MIPMAPS 0
#else
#define CPU_MIPMAPS 1
#include <nvtt/nvtt.h>
#endif
#include <Finally.h>
#include <Profile.h>
#include <StatTracker.h>
@ -37,6 +28,12 @@
using namespace gpu;
#if defined(Q_OS_ANDROID)
#define CPU_MIPMAPS 0
#else
#define CPU_MIPMAPS 1
#include <nvtt/nvtt.h>
#endif
static const glm::uvec2 SPARSE_PAGE_SIZE(128);
static const glm::uvec2 MAX_TEXTURE_SIZE(4096);
@ -51,25 +48,21 @@ static std::atomic<bool> compressNormalTextures { false };
static std::atomic<bool> compressGrayscaleTextures { false };
static std::atomic<bool> compressCubeTextures { false };
bool needsSparseRectification(const glm::uvec2& size) {
// Don't attempt to rectify small textures (textures less than the sparse page size in any dimension)
if (glm::any(glm::lessThan(size, SPARSE_PAGE_SIZE))) {
return false;
uint rectifyDimension(const uint& dimension) {
if (dimension < SPARSE_PAGE_SIZE.x) {
uint newSize = SPARSE_PAGE_SIZE.x;
while (dimension <= newSize / 2) {
newSize /= 2;
}
return newSize;
} else {
uint pages = (dimension / SPARSE_PAGE_SIZE.x) + (dimension % SPARSE_PAGE_SIZE.x == 0 ? 0 : 1);
return pages * SPARSE_PAGE_SIZE.x;
}
// Don't rectify textures that are already an exact multiple of sparse page size
if (glm::uvec2(0) == (size % SPARSE_PAGE_SIZE)) {
return false;
}
// Texture is not sparse compatible, but is bigger than the sparse page size in both dimensions, rectify!
return true;
}
glm::uvec2 rectifyToSparseSize(const glm::uvec2& size) {
glm::uvec2 pages = ((size / SPARSE_PAGE_SIZE) + glm::clamp(size % SPARSE_PAGE_SIZE, glm::uvec2(0), glm::uvec2(1)));
glm::uvec2 result = pages * SPARSE_PAGE_SIZE;
return result;
glm::uvec2 rectifySize(const glm::uvec2& size) {
return { rectifyDimension(size.x), rectifyDimension(size.y) };
}
@ -307,9 +300,12 @@ QImage processSourceImage(const QImage& srcImage, bool cubemap) {
++DECIMATED_TEXTURE_COUNT;
}
if (!cubemap && needsSparseRectification(targetSize)) {
++RECTIFIED_TEXTURE_COUNT;
targetSize = rectifyToSparseSize(targetSize);
if (!cubemap) {
auto rectifiedSize = rectifySize(targetSize);
if (rectifiedSize != targetSize) {
++RECTIFIED_TEXTURE_COUNT;
targetSize = rectifiedSize;
}
}
if (DEV_DECIMATE_TEXTURES && glm::all(glm::greaterThanEqual(targetSize / SPARSE_PAGE_SIZE, glm::uvec2(2)))) {

View file

@ -163,46 +163,31 @@ class MyTestWindow : public TestWindow {
}
};
extern bool needsSparseRectification(const uvec2& size);
extern uvec2 rectifyToSparseSize(const uvec2& size);
extern uvec2 rectifySize(const uvec2& size);
void testSparseRectify() {
std::vector<std::pair<uvec2, bool>> NEEDS_SPARSE_TESTS {{
std::vector<std::pair<uvec2, uvec2>> SPARSE_SIZE_TESTS {
// Already sparse
{ {1024, 1024 }, false },
{ { 128, 128 }, false },
{ {1024, 1024 }, { 1024, 1024 } },
{ { 128, 128 }, { 128, 128 } },
// Too small in one dimension
{ { 127, 127 }, false },
{ { 1, 1 }, false },
{ { 1000, 1 }, false },
{ { 1024, 1 }, false },
{ { 100, 100 }, false },
// needs rectification
{ { 1000, 1000 }, true },
{ { 1024, 1000 }, true },
} };
for (const auto& test : NEEDS_SPARSE_TESTS) {
const auto& size = test.first;
const auto& expected = test.second;
auto result = needsSparseRectification(size);
Q_ASSERT(expected == result);
result = needsSparseRectification(uvec2(size.y, size.x));
Q_ASSERT(expected == result);
}
std::vector<std::pair<uvec2, uvec2>> SPARSE_SIZE_TESTS { {
{ { 127, 127 }, { 128, 128 } },
{ { 1, 1 }, { 1, 1 } },
{ { 1000, 1 }, { 1024, 1 } },
{ { 1024, 1 }, { 1024, 1 } },
{ { 100, 100 }, { 128, 128 } },
{ { 57, 510 }, { 64, 512 } },
// needs rectification
{ { 1000, 1000 }, { 1024, 1024 } },
{ { 1024, 1000 }, { 1024, 1024 } },
} };
};
for (const auto& test : SPARSE_SIZE_TESTS) {
const auto& size = test.first;
const auto& expected = test.second;
auto result = rectifyToSparseSize(size);
auto result = rectifySize(size);
Q_ASSERT(expected == result);
result = rectifyToSparseSize(uvec2(size.y, size.x));
result = rectifySize(uvec2(size.y, size.x));
Q_ASSERT(expected == uvec2(result.y, result.x));
}
}