Add SubresourceStorage::Fill(const T&)
This will be used to change the values in the subresource storage after
creation efficiently. Also adds tests.
Bug: 41497359
Change-Id: I575afb5f00a7c2d0c49a2a8cb10a7d03e01e4d27
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/173462
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/native/SubresourceStorage.h b/src/dawn/native/SubresourceStorage.h
index 34ad25c..3dccfc5 100644
--- a/src/dawn/native/SubresourceStorage.h
+++ b/src/dawn/native/SubresourceStorage.h
@@ -129,12 +129,16 @@
SubresourceStorage(Aspect aspects,
uint32_t arrayLayerCount,
uint32_t mipLevelCount,
- T initialValue = {});
+ const T& initialValue = {});
// Returns the data for a single subresource. Note that the reference returned might be the
// same for multiple subresources.
const T& Get(Aspect aspect, uint32_t arrayLayer, uint32_t mipLevel) const;
+ // Fill the storage with a single value for all subresources, resulting in a fully
+ // compressed storage.
+ void Fill(const T& value);
+
// Given an iterateFunc that's a function or function-like object that can be called with
// arguments of type (const SubresourceRange& range, const T& data) and returns either void or
// MaybeError, calls it with aggregate ranges if possible, such that each subresource is part of
@@ -247,17 +251,22 @@
SubresourceStorage<T>::SubresourceStorage(Aspect aspects,
uint32_t arrayLayerCount,
uint32_t mipLevelCount,
- T initialValue)
+ const T& initialValue)
: mAspects(aspects), mMipLevelCount(mipLevelCount), mArrayLayerCount(arrayLayerCount) {
DAWN_ASSERT(arrayLayerCount <= std::numeric_limits<decltype(mArrayLayerCount)>::max());
DAWN_ASSERT(mipLevelCount <= std::numeric_limits<decltype(mMipLevelCount)>::max());
- uint32_t aspectCount = GetAspectCount(aspects);
+ Fill(initialValue);
+}
+
+template <typename T>
+void SubresourceStorage<T>::Fill(const T& value) {
+ uint32_t aspectCount = GetAspectCount(mAspects);
DAWN_ASSERT(aspectCount <= kMaxAspects);
for (uint32_t aspectIndex = 0; aspectIndex < aspectCount; aspectIndex++) {
mAspectCompressed[aspectIndex] = true;
- DataInline(aspectIndex) = initialValue;
+ DataInline(aspectIndex) = value;
}
}
diff --git a/src/dawn/tests/unittests/SubresourceStorageTests.cpp b/src/dawn/tests/unittests/SubresourceStorageTests.cpp
index c1f6bb0..eeaa82a 100644
--- a/src/dawn/tests/unittests/SubresourceStorageTests.cpp
+++ b/src/dawn/tests/unittests/SubresourceStorageTests.cpp
@@ -25,6 +25,7 @@
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <algorithm>
#include <memory>
#include <string>
#include <vector>
@@ -46,12 +47,14 @@
FakeStorage(Aspect aspects,
uint32_t arrayLayerCount,
uint32_t mipLevelCount,
- T initialValue = {})
+ const T& initialValue = {})
: mAspects(aspects),
mArrayLayerCount(arrayLayerCount),
mMipLevelCount(mipLevelCount),
mData(GetAspectCount(aspects) * arrayLayerCount * mipLevelCount, initialValue) {}
+ void Fill(const T& value) { std::fill(mData.begin(), mData.end(), value); }
+
template <typename F>
void Update(const SubresourceRange& range, F&& updateFunc) {
for (Aspect aspect : IterateEnumMask(range.aspects)) {
@@ -710,6 +713,44 @@
EXPECT_EQ(3, s.Get(Aspect::Color, 0, 1));
}
+// Check that fill after creation overwrites whatever was passed as initial value.
+TEST(SubresourceStorageTest, FillAfterInitialization) {
+ const uint32_t kLayers = 2;
+ const uint32_t kLevels = 2;
+ SubresourceStorage<int> s(Aspect::Color, kLayers, kLevels, 3);
+ FakeStorage<int> f(Aspect::Color, kLayers, kLevels, 3);
+
+ s.Fill(42);
+ f.Fill(42);
+
+ f.CheckSameAs(s);
+ CheckAspectCompressed(s, Aspect::Color, true);
+}
+
+// Check that fill after some modification overwrites everything and recompresses.
+TEST(SubresourceStorageTest, FillAfterModificationRecompresses) {
+ const uint32_t kLayers = 2;
+ const uint32_t kLevels = 2;
+ SubresourceStorage<int> s(Aspect::Depth | Aspect::Stencil, kLayers, kLevels, 3);
+ FakeStorage<int> f(Aspect::Depth | Aspect::Stencil, kLayers, kLevels, 3);
+
+ // Cause decompression by writing to a single subresource.
+ {
+ SubresourceRange range = SubresourceRange::MakeSingle(Aspect::Stencil, 1, 1);
+ CallUpdateOnBoth(&s, &f, range, [](const SubresourceRange&, int* data) { *data = 0xCAFE; });
+ }
+ CheckAspectCompressed(s, Aspect::Depth, true);
+ CheckAspectCompressed(s, Aspect::Stencil, false);
+
+ // Fill with 42, aspects should be recompressed entirely.
+ s.Fill(42);
+ f.Fill(42);
+
+ f.CheckSameAs(s);
+ CheckAspectCompressed(s, Aspect::Depth, true);
+ CheckAspectCompressed(s, Aspect::Stencil, true);
+}
+
// Bugs found while testing:
// - mLayersCompressed not initialized to true.
// - DecompressLayer setting Compressed to true instead of false.