skia2/tests/ImageStorageTest.cpp

162 lines
6.6 KiB
C++
Raw Normal View History

/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "Test.h"
#if SK_SUPPORT_GPU
#include "GrFragmentProcessor.h"
#include "GrInvariantOutput.h"
#include "GrRenderTargetContext.h"
#include "GrTexture.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ImageStorageLoad, reporter, ctxInfo) {
class TestFP : public GrFragmentProcessor {
public:
static sk_sp<GrFragmentProcessor> Make(sk_sp<GrTexture> texture, GrSLMemoryModel mm,
GrSLRestrict restrict) {
return sk_sp<GrFragmentProcessor>(new TestFP(std::move(texture), mm, restrict));
}
const char* name() const override { return "Image Load Test FP"; }
private:
TestFP(sk_sp<GrTexture> texture, GrSLMemoryModel mm, GrSLRestrict restrict)
Revert "Start of rewrite of GrFragmentProcessor optimizations." This reverts commit 85eb4226a4cd8c10a0e3f3ba2f3a60efbb2dd61b. Reason for revert: test failures on Windows, e.g. https://chromium-swarm.appspot.com/task?id=33f9527484414110&refresh=10 Original change's description: > Start of rewrite of GrFragmentProcessor optimizations. > > This adds a replacement for computeInvariantOutput buts does not use it yet. The replacement allows for three types of optimizations: > > * known input color -> known output color for GrFP elimination > * tracking of whether all color processors modulate their input for the "tweak alpha" optimziation > * opaqueness tracking > > This loses some of the generality of computInvariantOutput. It does not track the known output status of individual color components (other than opaque alpha). It does not track whether GrFragmentProcessors read their input color. It doesn't allow a processor that will receive non-constant output to advertise that it produces a constant output. These could probably be added back in the unlikely case that they prove valuable. > > Unlike computeInvariantOutput the optimizations are decided at instantiation time and constant colors are expressed as GrColor4f rather than GrColor. > > Change-Id: I684d3f9050693dde2d28154fa695e049ed8cf61a > Reviewed-on: https://skia-review.googlesource.com/7481 > Reviewed-by: Greg Daniel <egdaniel@google.com> > Commit-Queue: Brian Salomon <bsalomon@google.com> > TBR=egdaniel@google.com,bsalomon@google.com,brianosman@google.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Change-Id: I2390df257456013fa74137cb5d7b5a93820c291e Reviewed-on: https://skia-review.googlesource.com/7652 Commit-Queue: Ethan Nicholas <ethannicholas@google.com> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
2017-01-27 15:34:34 +00:00
: fImageStorageAccess(std::move(texture), kRead_GrIOType, mm, restrict) {
this->initClassID<TestFP>();
this->addImageStorageAccess(&fImageStorageAccess);
}
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
inout->setToUnknown();
}
bool onIsEqual(const GrFragmentProcessor& that) const override { return true; }
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
class GLSLProcessor : public GrGLSLFragmentProcessor {
public:
GLSLProcessor() = default;
void emitCode(EmitArgs& args) override {
const TestFP& tfp = args.fFp.cast<TestFP>();
GrGLSLFPFragmentBuilder* fb = args.fFragBuilder;
SkString imageLoadStr;
fb->codeAppend("highp vec2 coord = sk_FragCoord.xy;");
fb->appendImageStorageLoad(&imageLoadStr, args.fImageStorages[0],
"ivec2(coord)");
if (GrPixelConfigIsSint(tfp.fImageStorageAccess.texture()->config())) {
// Map the signed bytes so that when then get read back as unorm values they
// will have their original bit pattern.
fb->codeAppendf("highp ivec4 ivals = %s;", imageLoadStr.c_str());
// NV gives a linker error for this:
// fb->codeAppend("ivals +=
// "mix(ivec4(0), ivec4(256), lessThan(ivals, ivec4(0)));");
fb->codeAppend("if (ivals.r < 0) { ivals.r += 256; }");
fb->codeAppend("if (ivals.g < 0) { ivals.g += 256; }");
fb->codeAppend("if (ivals.b < 0) { ivals.b += 256; }");
fb->codeAppend("if (ivals.a < 0) { ivals.a += 256; }");
fb->codeAppendf("%s = vec4(ivals)/255;", args.fOutputColor);
} else {
fb->codeAppendf("%s = %s;", args.fOutputColor, imageLoadStr.c_str());
}
}
};
return new GLSLProcessor;
}
ImageStorageAccess fImageStorageAccess;
};
static constexpr int kS = 256;
GrContext* context = ctxInfo.grContext();
if (context->caps()->shaderCaps()->maxFragmentImageStorages() < 1) {
return;
}
std::unique_ptr<uint32_t[]> data(new uint32_t[kS * kS]);
for (int j = 0; j < kS; ++j) {
for (int i = 0; i < kS; ++i) {
data[i + kS * j] = GrColorPackRGBA(i, j, 0, 0);
}
}
std::unique_ptr<uint32_t[]> idata(new uint32_t[kS * kS]);
for (int j = 0; j < kS; ++j) {
for (int i = 0; i < kS; ++i) {
int8_t r = i - 128;
int8_t g = j - 128;
int8_t b = -128;
int8_t a = -128;
idata[i + kS * j] = ((uint8_t)a << 24) | ((uint8_t)b << 16) |
((uint8_t)g << 8) | (uint8_t)r;
}
}
// Currently image accesses always have "top left" semantics.
GrSurfaceDesc desc;
desc.fOrigin = kTopLeft_GrSurfaceOrigin;
desc.fWidth = kS;
desc.fHeight = kS;
struct {
GrPixelConfig fConfig;
std::unique_ptr<uint32_t[]> fData;
} tests[] = {
{
kRGBA_8888_GrPixelConfig,
std::move(data)
},
{
kRGBA_8888_sint_GrPixelConfig,
std::move(idata)
},
};
for (const auto& test : tests) {
// This test should work with any memory model and with or without restrict
for (auto mm : {GrSLMemoryModel::kNone,
GrSLMemoryModel::kCoherent,
GrSLMemoryModel::kVolatile}) {
for (auto restrict : {GrSLRestrict::kNo, GrSLRestrict::kYes}) {
if (!context->caps()->canConfigBeImageStorage(test.fConfig)) {
continue;
}
desc.fConfig = test.fConfig;
sk_sp<GrTexture> imageStorageTexture(context->textureProvider()->createTexture(desc,
SkBudgeted::kYes, test.fData.get(), 0));
sk_sp<GrRenderTargetContext> rtContext =
context->makeRenderTargetContext(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);
}
}
}
}
}
}
}
#endif