diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 30f176b5a6..b9f08a8303 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -22,11 +22,48 @@ using namespace gpu; // FIXME: Declare this to enable compression //#define COMPRESS_TEXTURES +#define SPARSE_PAGE_DIMENSION 128 + +static const uvec2 SPARSE_PAGE_SIZE(SPARSE_PAGE_DIMENSION); bool DEV_DECIMATE_TEXTURES = false; -QImage processSourceImage(const QImage& srcImage) { - if (DEV_DECIMATE_TEXTURES) { - return srcImage.scaled(srcImage.size() * 0.5f); + +bool needsSparseRectification(const 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; } + + // Don't rectify textures that are already an exact multiple of sparse page size + if (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; +} + +uvec2 rectifyToSparseSize(const uvec2& size) { + uvec2 pages = ((size / SPARSE_PAGE_SIZE) + glm::clamp(size % SPARSE_PAGE_SIZE, uvec2(0), uvec2(1))); + uvec2 result = pages * SPARSE_PAGE_SIZE; + return result; +} + +QImage processSourceImage(const QImage& srcImage) { + const uvec2 srcImageSize = toGlm(srcImage.size()); + uvec2 targetSize = srcImageSize; + + if (needsSparseRectification(srcImageSize)) { + targetSize = rectifyToSparseSize(srcImageSize); + } + + if (DEV_DECIMATE_TEXTURES && glm::all(glm::greaterThanEqual(targetSize / SPARSE_PAGE_SIZE, uvec2(2)))) { + targetSize /= 2; + } + + if (targetSize != srcImageSize) { + return srcImage.scaled(fromGlm(targetSize)); + } + return srcImage; } diff --git a/tests/gpu-test/src/main.cpp b/tests/gpu-test/src/main.cpp index 008f363e53..9608576a6f 100644 --- a/tests/gpu-test/src/main.cpp +++ b/tests/gpu-test/src/main.cpp @@ -164,11 +164,59 @@ class MyTestWindow : public TestWindow { } }; +extern bool needsSparseRectification(const uvec2& size); +extern uvec2 rectifyToSparseSize(const uvec2& size); -int main(int argc, char** argv) { +void testSparseRectify() { + std::vector> NEEDS_SPARSE_TESTS {{ + // Already sparse + { {1024, 1024 }, false }, + { { 128, 128 }, false }, + // 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> SPARSE_SIZE_TESTS { { + // 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); + Q_ASSERT(expected == result); + result = rectifyToSparseSize(uvec2(size.y, size.x)); + Q_ASSERT(expected == uvec2(result.y, result.x)); + } +} + +int main(int argc, char** argv) { + testSparseRectify(); + + // FIXME this test appears to be broken +#if 0 QGuiApplication app(argc, argv); MyTestWindow window; app.exec(); +#endif return 0; }