From 9ceff0a91b166ac7277368605152fb9bb869a5cd Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 8 Apr 2022 12:55:10 +0100 Subject: [PATCH] Fix handling of sub-page-sized mip tails with D3D-style wrapped set --- renderdoc/core/sparse_page_table.cpp | 114 +++++++++++++++++++++++++-- 1 file changed, 109 insertions(+), 5 deletions(-) diff --git a/renderdoc/core/sparse_page_table.cpp b/renderdoc/core/sparse_page_table.cpp index e7a5d14e7..5f42c8caf 100644 --- a/renderdoc/core/sparse_page_table.cpp +++ b/renderdoc/core/sparse_page_table.cpp @@ -162,8 +162,12 @@ uint64_t PageTable::setMipTailRange(uint64_t resourceByteOffset, ResourceId memo return m_MipTail.byteOffset + m_MipTail.totalPackedByteSize; } + const uint32_t numTailPages = + uint32_t((m_MipTail.totalPackedByteSize + m_PageByteSize - 1) / m_PageByteSize); + // if we're setting the whole mip tail at once, store it as a single page mapping - if(resourceByteOffset == 0 && byteSize == m_MipTail.totalPackedByteSize) + if(resourceByteOffset == 0 && + (byteSize == m_MipTail.totalPackedByteSize || byteSize == numTailPages * m_PageByteSize)) { for(size_t i = 0; i < m_MipTail.mappings.size(); i++) { @@ -188,9 +192,7 @@ uint64_t PageTable::setMipTailRange(uint64_t resourceByteOffset, ResourceId memo // referenced pages PageRangeMapping &mapping = m_MipTail.mappings[0]; - mapping.createPages( - uint32_t((m_MipTail.totalPackedByteSize + m_PageByteSize - 1) / m_PageByteSize), - m_PageByteSize); + mapping.createPages(numTailPages, m_PageByteSize); // iterate through each referenced resource page for(size_t @@ -410,9 +412,13 @@ rdcpair PageTable::setImageWrappedRange(uint32_t subresource, while(byteSize > 0 && (isSubresourceInMipTail(subresource) || subresource < m_Subresources.size())) { const Coord subresourcePageDim = calcSubresourcePageDim(subresource); + const uint32_t numMipTailPages = + uint32_t((m_MipTail.totalPackedByteSize / RDCMAX(1U, (uint32_t)m_MipTail.mappings.size())) + + m_PageByteSize - 1) / + m_PageByteSize; const uint32_t numSubresourcePages = isSubresourceInMipTail(subresource) - ? uint32_t(m_MipTail.totalPackedByteSize / m_MipTail.mappings.size()) / m_PageByteSize + ? numMipTailPages : subresourcePageDim.x * subresourcePageDim.y * subresourcePageDim.z; PageRangeMapping &sub = isSubresourceInMipTail(subresource) ? getMipTailMapping(subresource) @@ -1605,6 +1611,104 @@ TEST_CASE("Test sparse page table mapping", "[sparse]") CHECK(pageTable.getMipTail().mappings[0].pages[5] == Sparse::Page({ResourceId(), 0})); }; + SECTION("mip tails smaller than the page size") + { + ResourceId mip = ResourceIDGen::GetNewUniqueID(); + + SECTION("normal texture") + { + pageTable.Initialise({256, 256, 1}, 6, 1, 65536, {32, 32, 1}, 4, 0, 0, 8192); + + uint64_t nextTailOffset; + + nextTailOffset = pageTable.setMipTailRange(0, mip, 65536 * 3, 8192, false); + + CHECK(nextTailOffset == 8192); + CHECK(pageTable.getMipTail().mappings[0].hasSingleMapping()); + REQUIRE(pageTable.getMipTail().mappings[0].pages.size() == 0); + CHECK(pageTable.getMipTail().mappings[0].singleMapping == Sparse::Page({mip, 65536 * 3})); + + nextTailOffset = pageTable.setMipTailRange(0, mip, 65536 * 3, 65536, false); + + CHECK(nextTailOffset == 8192); + CHECK(pageTable.getMipTail().mappings[0].hasSingleMapping()); + REQUIRE(pageTable.getMipTail().mappings[0].pages.size() == 0); + CHECK(pageTable.getMipTail().mappings[0].singleMapping == Sparse::Page({mip, 65536 * 3})); + + rdcpair nextCoord; + // setImageWrappedRange doesn't support anything but page-sized byte sizes to set + nextCoord = pageTable.setImageWrappedRange(4, {0, 0, 0}, 65536, mip, 65536 * 10, false, true); + + CHECK(nextCoord.first == 6); + CHECK(nextCoord.second == Sparse::Coord({0, 0, 0})); + CHECK(pageTable.getMipTail().mappings[0].hasSingleMapping()); + REQUIRE(pageTable.getMipTail().mappings[0].pages.size() == 0); + CHECK(pageTable.getMipTail().mappings[0].singleMapping == Sparse::Page({mip, 65536 * 10})); + }; + + SECTION("texture that's all mip tail") + { + pageTable.Initialise({256, 256, 1}, 6, 1, 65536, {32, 32, 1}, 0, 0, 0, 8192); + + uint64_t nextTailOffset; + + nextTailOffset = pageTable.setMipTailRange(0, mip, 65536 * 3, 8192, false); + + CHECK(nextTailOffset == 8192); + CHECK(pageTable.getMipTail().mappings[0].hasSingleMapping()); + REQUIRE(pageTable.getMipTail().mappings[0].pages.size() == 0); + CHECK(pageTable.getMipTail().mappings[0].singleMapping == Sparse::Page({mip, 65536 * 3})); + + nextTailOffset = pageTable.setMipTailRange(0, mip, 65536 * 3, 65536, false); + + CHECK(nextTailOffset == 8192); + CHECK(pageTable.getMipTail().mappings[0].hasSingleMapping()); + REQUIRE(pageTable.getMipTail().mappings[0].pages.size() == 0); + CHECK(pageTable.getMipTail().mappings[0].singleMapping == Sparse::Page({mip, 65536 * 3})); + + rdcpair nextCoord; + // setImageWrappedRange doesn't support anything but page-sized byte sizes to set + nextCoord = pageTable.setImageWrappedRange(0, {0, 0, 0}, 65536, mip, 65536 * 10, false, true); + + CHECK(nextCoord.first == 6); + CHECK(nextCoord.second == Sparse::Coord({0, 0, 0})); + CHECK(pageTable.getMipTail().mappings[0].hasSingleMapping()); + REQUIRE(pageTable.getMipTail().mappings[0].pages.size() == 0); + CHECK(pageTable.getMipTail().mappings[0].singleMapping == Sparse::Page({mip, 65536 * 10})); + }; + + SECTION("small no-mips texture") + { + pageTable.Initialise({8, 8, 1}, 1, 1, 65536, {32, 32, 1}, 0, 0, 0, 8192); + + uint64_t nextTailOffset; + + nextTailOffset = pageTable.setMipTailRange(0, mip, 65536 * 3, 8192, false); + + CHECK(nextTailOffset == 8192); + CHECK(pageTable.getMipTail().mappings[0].hasSingleMapping()); + REQUIRE(pageTable.getMipTail().mappings[0].pages.size() == 0); + CHECK(pageTable.getMipTail().mappings[0].singleMapping == Sparse::Page({mip, 65536 * 3})); + + nextTailOffset = pageTable.setMipTailRange(0, mip, 65536 * 3, 65536, false); + + CHECK(nextTailOffset == 8192); + CHECK(pageTable.getMipTail().mappings[0].hasSingleMapping()); + REQUIRE(pageTable.getMipTail().mappings[0].pages.size() == 0); + CHECK(pageTable.getMipTail().mappings[0].singleMapping == Sparse::Page({mip, 65536 * 3})); + + rdcpair nextCoord; + // setImageWrappedRange doesn't support anything but page-sized byte sizes to set + nextCoord = pageTable.setImageWrappedRange(0, {0, 0, 0}, 65536, mip, 65536 * 10, false, true); + + CHECK(nextCoord.first == 1); + CHECK(nextCoord.second == Sparse::Coord({0, 0, 0})); + CHECK(pageTable.getMipTail().mappings[0].hasSingleMapping()); + REQUIRE(pageTable.getMipTail().mappings[0].pages.size() == 0); + CHECK(pageTable.getMipTail().mappings[0].singleMapping == Sparse::Page({mip, 65536 * 10})); + }; + }; + SECTION("2D texture being set with unbounded range") { ResourceId whole = ResourceIDGen::GetNewUniqueID();