aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-07-28 13:41:51 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-07-28 18:02:52 +0000
commitb17e63938fdd466e43c8f15ae19b051f3f2679bf (patch)
tree96493177e23b4ef6736063b3668fe4d7f63a1804
parenteee5183a322dd902de743ac02f33a5fd3181b0b6 (diff)
Add clone methods to unit test GrFragmentProcessor classes
Also adds testing of copying ImageStorageAccess and ref counts of proxies held by cloned FPs. Change-Id: Ia23220bf65b4df83d1c874b46d8525cc3540f716 Reviewed-on: https://skia-review.googlesource.com/28004 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
-rw-r--r--src/gpu/GrProcessor.h32
-rw-r--r--tests/GLProgramsTest.cpp7
-rw-r--r--tests/ImageStorageTest.cpp49
-rw-r--r--tests/ProcessorTest.cpp236
4 files changed, 214 insertions, 110 deletions
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index 2afebb72b1..e4bf5919ff 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -229,10 +229,14 @@ public:
, fVisibility(that.fVisibility) {}
TextureSampler(sk_sp<GrTextureProxy>, const GrSamplerParams&);
+
explicit TextureSampler(sk_sp<GrTextureProxy>,
GrSamplerParams::FilterMode = GrSamplerParams::kNone_FilterMode,
SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode,
GrShaderFlags visibility = kFragment_GrShaderFlag);
+
+ TextureSampler& operator=(const TextureSampler&) = delete;
+
void reset(sk_sp<GrTextureProxy>, const GrSamplerParams&,
GrShaderFlags visibility = kFragment_GrShaderFlag);
void reset(sk_sp<GrTextureProxy>,
@@ -279,7 +283,7 @@ private:
* Used to represent a texel buffer that will be read in a GrResourceIOProcessor. It holds a
* GrBuffer along with an associated offset and texel config.
*/
-class GrResourceIOProcessor::BufferAccess : public SkNoncopyable {
+class GrResourceIOProcessor::BufferAccess {
public:
BufferAccess() = default;
BufferAccess(GrPixelConfig texelConfig, GrBuffer* buffer,
@@ -287,6 +291,17 @@ public:
this->reset(texelConfig, buffer, visibility);
}
/**
+ * This copy constructor is used by GrFragmentProcessor::clone() implementations. The copy
+ * always takes a new ref on the buffer proxy as the new fragment processor will not yet be
+ * in pending execution state.
+ */
+ explicit BufferAccess(const BufferAccess& that) {
+ this->reset(that.fTexelConfig, that.fBuffer.get(), that.fVisibility);
+ }
+
+ BufferAccess& operator=(const BufferAccess&) = delete;
+
+ /**
* Must be initialized before adding to a GrProcessor's buffer access list.
*/
void reset(GrPixelConfig texelConfig, GrBuffer* buffer,
@@ -327,10 +342,23 @@ private:
* Currently the format of the load/store data in the shader is inferred from the texture config,
* though it could be made explicit.
*/
-class GrResourceIOProcessor::ImageStorageAccess : public SkNoncopyable {
+class GrResourceIOProcessor::ImageStorageAccess {
public:
ImageStorageAccess(sk_sp<GrTextureProxy>, GrIOType, GrSLMemoryModel, GrSLRestrict,
GrShaderFlags visibility = kFragment_GrShaderFlag);
+ /**
+ * This copy constructor is used by GrFragmentProcessor::clone() implementations. The copy
+ * always takes a new ref on the surface proxy as the new fragment processor will not yet be
+ * in pending execution state.
+ */
+ explicit ImageStorageAccess(const ImageStorageAccess& that)
+ : fProxyRef(sk_ref_sp(that.fProxyRef.get()), that.fProxyRef.ioType())
+ , fVisibility(that.fVisibility)
+ , fFormat(that.fFormat)
+ , fMemoryModel(that.fMemoryModel)
+ , fRestrict(that.fRestrict) {}
+
+ ImageStorageAccess& operator=(const ImageStorageAccess&) = delete;
bool operator==(const ImageStorageAccess& that) const {
return this->proxy() == that.proxy() && fVisibility == that.fVisibility;
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index 8b07568fdc..aca548cdf8 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -75,6 +75,8 @@ public:
return new GLBigKeyProcessor;
}
+ sk_sp<GrFragmentProcessor> clone() const override { return Make(); }
+
private:
BigKeyProcessor() : INHERITED(kNone_OptimizationFlags) { this->initClassID<BigKeyProcessor>(); }
virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
@@ -108,6 +110,11 @@ public:
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLFP; }
+ sk_sp<GrFragmentProcessor> clone() const override {
+ auto child = this->childProcessor(0).clone();
+ return child ? Make(std::move(child)) : nullptr;
+ }
+
private:
class GLFP : public GrGLSLFragmentProcessor {
public:
diff --git a/tests/ImageStorageTest.cpp b/tests/ImageStorageTest.cpp
index f55553c518..9a5f8962fb 100644
--- a/tests/ImageStorageTest.cpp
+++ b/tests/ImageStorageTest.cpp
@@ -27,6 +27,10 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) {
const char* name() const override { return "Image Load Test FP"; }
+ sk_sp<GrFragmentProcessor> clone() const override {
+ return sk_sp<GrFragmentProcessor>(new TestFP(*this));
+ }
+
private:
TestFP(sk_sp<GrTextureProxy> proxy, GrSLMemoryModel mm, GrSLRestrict restrict)
: INHERITED(kNone_OptimizationFlags)
@@ -35,6 +39,13 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) {
this->addImageStorageAccess(&fImageStorageAccess);
}
+ explicit TestFP(const TestFP& that)
+ : INHERITED(that.optimizationFlags())
+ , fImageStorageAccess(that.fImageStorageAccess) {
+ this->initClassID<TestFP>();
+ this->addImageStorageAccess(&fImageStorageAccess);
+ }
+
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
bool onIsEqual(const GrFragmentProcessor& that) const override { return true; }
@@ -134,22 +145,28 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) {
sk_sp<GrRenderTargetContext> rtContext =
context->makeDeferredRenderTargetContext(SkBackingFit::kExact, kS, kS,
kRGBA_8888_GrPixelConfig, nullptr);
- GrPaint paint;
- paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
- paint.addColorFragmentProcessor(TestFP::Make(imageStorageTexture, mm, restrict));
- rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
- std::unique_ptr<uint32_t[]> readData(new uint32_t[kS * kS]);
- SkImageInfo info = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType,
- kPremul_SkAlphaType);
- rtContext->readPixels(info, readData.get(), 0, 0, 0);
- int failed = false;
- for (int j = 0; j < kS && !failed; ++j) {
- for (int i = 0; i < kS && !failed; ++i) {
- uint32_t d = test.fData[j * kS + i];
- uint32_t rd = readData[j * kS + i];
- if (d != rd) {
- failed = true;
- ERRORF(reporter, "Expected 0x%08x, got 0x%08x at %d, %d.", d, rd, i, j);
+ // We make a clone to test that copying GrFragmentProcessor::ImageStorageAccess
+ // copying works.
+ auto testFP = TestFP::Make(imageStorageTexture, mm, restrict);
+ for (auto fp : {testFP, testFP->clone()}) {
+ GrPaint paint;
+ paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
+ paint.addColorFragmentProcessor(fp);
+ rtContext->drawPaint(GrNoClip(), std::move(paint), SkMatrix::I());
+ std::unique_ptr<uint32_t[]> readData(new uint32_t[kS * kS]);
+ SkImageInfo info = SkImageInfo::Make(kS, kS, kRGBA_8888_SkColorType,
+ kPremul_SkAlphaType);
+ rtContext->readPixels(info, readData.get(), 0, 0, 0);
+ int failed = false;
+ for (int j = 0; j < kS && !failed; ++j) {
+ for (int i = 0; i < kS && !failed; ++i) {
+ uint32_t d = test.fData[j * kS + i];
+ uint32_t rd = readData[j * kS + i];
+ if (d != rd) {
+ failed = true;
+ ERRORF(reporter, "Expected 0x%08x, got 0x%08x at %d, %d.",
+ d, rd, i, j);
+ }
}
}
}
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index ec157f9003..3bfd62e3a4 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -83,11 +83,24 @@ public:
b->add32(sk_atomic_inc(&gKey));
}
+ sk_sp<GrFragmentProcessor> clone() const override {
+ sk_sp<GrFragmentProcessor> child;
+ if (this->numChildProcessors()) {
+ SkASSERT(1 == this->numChildProcessors());
+ child = this->childProcessor(0).clone();
+ if (!child) {
+ return nullptr;
+ }
+ }
+ return sk_sp<GrFragmentProcessor> (new TestFP(*this, std::move(child)));
+ }
+
private:
TestFP(const SkTArray<sk_sp<GrTextureProxy>>& proxies,
const SkTArray<sk_sp<GrBuffer>>& buffers,
const SkTArray<Image>& images)
: INHERITED(kNone_OptimizationFlags), fSamplers(4), fBuffers(4), fImages(4) {
+ this->initClassID<TestFP>();
for (const auto& proxy : proxies) {
this->addTextureSampler(&fSamplers.emplace_back(proxy));
}
@@ -103,9 +116,30 @@ private:
TestFP(sk_sp<GrFragmentProcessor> child)
: INHERITED(kNone_OptimizationFlags), fSamplers(4), fBuffers(4), fImages(4) {
+ this->initClassID<TestFP>();
this->registerChildProcessor(std::move(child));
}
+ explicit TestFP(const TestFP& that, sk_sp<GrFragmentProcessor> child)
+ : INHERITED(that.optimizationFlags()), fSamplers(4), fBuffers(4), fImages(4) {
+ this->initClassID<TestFP>();
+ for (int i = 0; i < that.fSamplers.count(); ++i) {
+ fSamplers.emplace_back(that.fSamplers[i]);
+ this->addTextureSampler(&fSamplers.back());
+ }
+ for (int i = 0; i < that.fBuffers.count(); ++i) {
+ fBuffers.emplace_back(that.fBuffers[i]);
+ this->addBufferAccess(&fBuffers.back());
+ }
+ for (int i = 0; i < that.fImages.count(); ++i) {
+ fImages.emplace_back(that.fImages[i]);
+ this->addImageStorageAccess(&fImages.back());
+ }
+ if (child) {
+ this->registerChildProcessor(std::move(child));
+ }
+ }
+
virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
class TestGLSLFP : public GrGLSLFragmentProcessor {
public:
@@ -151,109 +185,127 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(ProcessorRefTest, reporter, ctxInfo) {
desc.fHeight = 10;
desc.fConfig = kRGBA_8888_GrPixelConfig;
- for (int parentCnt = 0; parentCnt < 2; parentCnt++) {
- sk_sp<GrRenderTargetContext> renderTargetContext(context->makeDeferredRenderTargetContext(
- SkBackingFit::kApprox, 1, 1, kRGBA_8888_GrPixelConfig, nullptr));
- {
- bool texelBufferSupport = context->caps()->shaderCaps()->texelBufferSupport();
- bool imageLoadStoreSupport = context->caps()->shaderCaps()->imageLoadStoreSupport();
- sk_sp<GrTextureProxy> proxy1(GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
- desc, SkBackingFit::kExact,
- SkBudgeted::kYes));
- sk_sp<GrTextureProxy> proxy2(GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
- desc, SkBackingFit::kExact,
- SkBudgeted::kYes));
- sk_sp<GrTextureProxy> proxy3(GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
- desc, SkBackingFit::kExact,
- SkBudgeted::kYes));
- sk_sp<GrTextureProxy> proxy4(GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
- desc, SkBackingFit::kExact,
- SkBudgeted::kYes));
- sk_sp<GrBuffer> buffer(texelBufferSupport
- ? context->resourceProvider()->createBuffer(
- 1024, GrBufferType::kTexel_GrBufferType,
- GrAccessPattern::kStatic_GrAccessPattern, 0)
- : nullptr);
+ for (bool makeClone : {false, true}) {
+ for (int parentCnt = 0; parentCnt < 2; parentCnt++) {
+ sk_sp<GrRenderTargetContext> renderTargetContext(
+ context->makeDeferredRenderTargetContext( SkBackingFit::kApprox, 1, 1,
+ kRGBA_8888_GrPixelConfig, nullptr));
{
- SkTArray<sk_sp<GrTextureProxy>> proxies;
- SkTArray<sk_sp<GrBuffer>> buffers;
- SkTArray<TestFP::Image> images;
- proxies.push_back(proxy1);
- if (texelBufferSupport) {
- buffers.push_back(buffer);
- }
- if (imageLoadStoreSupport) {
- images.emplace_back(proxy2, GrIOType::kRead_GrIOType);
- images.emplace_back(proxy3, GrIOType::kWrite_GrIOType);
- images.emplace_back(proxy4, GrIOType::kRW_GrIOType);
- }
- auto fp = TestFP::Make(std::move(proxies), std::move(buffers), std::move(images));
- for (int i = 0; i < parentCnt; ++i) {
- fp = TestFP::Make(std::move(fp));
+ bool texelBufferSupport = context->caps()->shaderCaps()->texelBufferSupport();
+ bool imageLoadStoreSupport = context->caps()->shaderCaps()->imageLoadStoreSupport();
+ sk_sp<GrTextureProxy> proxy1(
+ GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+ desc, SkBackingFit::kExact,
+ SkBudgeted::kYes));
+ sk_sp<GrTextureProxy> proxy2
+ (GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+ desc, SkBackingFit::kExact,
+ SkBudgeted::kYes));
+ sk_sp<GrTextureProxy> proxy3(
+ GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+ desc, SkBackingFit::kExact,
+ SkBudgeted::kYes));
+ sk_sp<GrTextureProxy> proxy4(
+ GrSurfaceProxy::MakeDeferred(context->resourceProvider(),
+ desc, SkBackingFit::kExact,
+ SkBudgeted::kYes));
+ sk_sp<GrBuffer> buffer(texelBufferSupport
+ ? context->resourceProvider()->createBuffer(
+ 1024, GrBufferType::kTexel_GrBufferType,
+ GrAccessPattern::kStatic_GrAccessPattern, 0)
+ : nullptr);
+ {
+ SkTArray<sk_sp<GrTextureProxy>> proxies;
+ SkTArray<sk_sp<GrBuffer>> buffers;
+ SkTArray<TestFP::Image> images;
+ proxies.push_back(proxy1);
+ if (texelBufferSupport) {
+ buffers.push_back(buffer);
+ }
+ if (imageLoadStoreSupport) {
+ images.emplace_back(proxy2, GrIOType::kRead_GrIOType);
+ images.emplace_back(proxy3, GrIOType::kWrite_GrIOType);
+ images.emplace_back(proxy4, GrIOType::kRW_GrIOType);
+ }
+ auto fp = TestFP::Make(std::move(proxies), std::move(buffers),
+ std::move(images));
+ for (int i = 0; i < parentCnt; ++i) {
+ fp = TestFP::Make(std::move(fp));
+ }
+ sk_sp<GrFragmentProcessor> clone;
+ if (makeClone) {
+ clone = fp->clone();
+ }
+ std::unique_ptr<GrDrawOp> op(TestOp::Make(std::move(fp)));
+ renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
+ if (clone) {
+ op = TestOp::Make(std::move(clone));
+ renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
+ }
}
- std::unique_ptr<GrDrawOp> op(TestOp::Make(std::move(fp)));
- renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
- }
- int refCnt, readCnt, writeCnt;
+ int refCnt, readCnt, writeCnt;
- testingOnly_getIORefCnts(proxy1.get(), &refCnt, &readCnt, &writeCnt);
- REPORTER_ASSERT(reporter, 1 == refCnt);
- REPORTER_ASSERT(reporter, 1 == readCnt);
- REPORTER_ASSERT(reporter, 0 == writeCnt);
-
- if (texelBufferSupport) {
- testingOnly_getIORefCnts(buffer.get(), &refCnt, &readCnt, &writeCnt);
- REPORTER_ASSERT(reporter, 1 == refCnt);
- REPORTER_ASSERT(reporter, 1 == readCnt);
- REPORTER_ASSERT(reporter, 0 == writeCnt);
- }
-
- if (imageLoadStoreSupport) {
- testingOnly_getIORefCnts(proxy2.get(), &refCnt, &readCnt, &writeCnt);
- REPORTER_ASSERT(reporter, 1 == refCnt);
- REPORTER_ASSERT(reporter, 1 == readCnt);
- REPORTER_ASSERT(reporter, 0 == writeCnt);
-
- testingOnly_getIORefCnts(proxy3.get(), &refCnt, &readCnt, &writeCnt);
+ testingOnly_getIORefCnts(proxy1.get(), &refCnt, &readCnt, &writeCnt);
+ // IO counts should be double if there is a clone of the FP.
+ int ioRefMul = makeClone ? 2 : 1;
REPORTER_ASSERT(reporter, 1 == refCnt);
- REPORTER_ASSERT(reporter, 0 == readCnt);
- REPORTER_ASSERT(reporter, 1 == writeCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 1 == readCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt);
- testingOnly_getIORefCnts(proxy4.get(), &refCnt, &readCnt, &writeCnt);
- REPORTER_ASSERT(reporter, 1 == refCnt);
- REPORTER_ASSERT(reporter, 1 == readCnt);
- REPORTER_ASSERT(reporter, 1 == writeCnt);
- }
-
- context->flush();
+ if (texelBufferSupport) {
+ testingOnly_getIORefCnts(buffer.get(), &refCnt, &readCnt, &writeCnt);
+ REPORTER_ASSERT(reporter, 1 == refCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 1 == readCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt);
+ }
- testingOnly_getIORefCnts(proxy1.get(), &refCnt, &readCnt, &writeCnt);
- REPORTER_ASSERT(reporter, 1 == refCnt);
- REPORTER_ASSERT(reporter, 0 == readCnt);
- REPORTER_ASSERT(reporter, 0 == writeCnt);
+ if (imageLoadStoreSupport) {
+ testingOnly_getIORefCnts(proxy2.get(), &refCnt, &readCnt, &writeCnt);
+ REPORTER_ASSERT(reporter, 1 == refCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 1 == readCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt);
+
+ testingOnly_getIORefCnts(proxy3.get(), &refCnt, &readCnt, &writeCnt);
+ REPORTER_ASSERT(reporter, 1 == refCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 1 == writeCnt);
+
+ testingOnly_getIORefCnts(proxy4.get(), &refCnt, &readCnt, &writeCnt);
+ REPORTER_ASSERT(reporter, 1 == refCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 1 == readCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 1 == writeCnt);
+ }
- if (texelBufferSupport) {
- testingOnly_getIORefCnts(buffer.get(), &refCnt, &readCnt, &writeCnt);
- REPORTER_ASSERT(reporter, 1 == refCnt);
- REPORTER_ASSERT(reporter, 0 == readCnt);
- REPORTER_ASSERT(reporter, 0 == writeCnt);
- }
+ context->flush();
- if (texelBufferSupport) {
- testingOnly_getIORefCnts(proxy2.get(), &refCnt, &readCnt, &writeCnt);
+ testingOnly_getIORefCnts(proxy1.get(), &refCnt, &readCnt, &writeCnt);
REPORTER_ASSERT(reporter, 1 == refCnt);
- REPORTER_ASSERT(reporter, 0 == readCnt);
- REPORTER_ASSERT(reporter, 0 == writeCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt);
- testingOnly_getIORefCnts(proxy3.get(), &refCnt, &readCnt, &writeCnt);
- REPORTER_ASSERT(reporter, 1 == refCnt);
- REPORTER_ASSERT(reporter, 0 == readCnt);
- REPORTER_ASSERT(reporter, 0 == writeCnt);
+ if (texelBufferSupport) {
+ testingOnly_getIORefCnts(buffer.get(), &refCnt, &readCnt, &writeCnt);
+ REPORTER_ASSERT(reporter, 1 == refCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt);
+ }
- testingOnly_getIORefCnts(proxy4.get(), &refCnt, &readCnt, &writeCnt);
- REPORTER_ASSERT(reporter, 1 == refCnt);
- REPORTER_ASSERT(reporter, 0 == readCnt);
- REPORTER_ASSERT(reporter, 0 == writeCnt);
+ if (texelBufferSupport) {
+ testingOnly_getIORefCnts(proxy2.get(), &refCnt, &readCnt, &writeCnt);
+ REPORTER_ASSERT(reporter, 1 == refCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt);
+
+ testingOnly_getIORefCnts(proxy3.get(), &refCnt, &readCnt, &writeCnt);
+ REPORTER_ASSERT(reporter, 1 == refCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt);
+
+ testingOnly_getIORefCnts(proxy4.get(), &refCnt, &readCnt, &writeCnt);
+ REPORTER_ASSERT(reporter, 1 == refCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == readCnt);
+ REPORTER_ASSERT(reporter, ioRefMul * 0 == writeCnt);
+ }
}
}
}