Remove use of texture swizzle in GL backend.

This has always been a potential source of a bug. If the same texture is
used twice in a shader with different swizzles we would overwrite the
swizzle for the first use by that of the second use since there is
only one fixed function swizzle per texture. It's not part of the
sampler state.

We set the swizzle when it is a feature, but always to RGBA.

Also, highly speculative that this may improve ANGLE D3D11 ES3
performance compared to ES2.

Bug: skia:10644
Change-Id: I8877afc3043c5ddaafd26ea9f9bd372303328c71
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/313682
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Brian Salomon 2020-08-27 17:16:49 -04:00 committed by Skia Commit-Bot
parent e7f7158900
commit 280fa3d303
14 changed files with 35 additions and 55 deletions

View File

@ -48,9 +48,9 @@ public:
NonsamplerState();
void invalidate();
uint32_t fSwizzleKey;
GrGLint fBaseMipMapLevel;
GrGLint fMaxMipmapLevel;
bool fSwizzleIsRGBA;
};
void invalidate();

View File

@ -49,10 +49,7 @@ static uint32_t sampler_key(GrTextureType textureType, const GrSwizzle& swizzle,
int samplerTypeKey = texture_type_key(textureType);
static_assert(2 == sizeof(swizzle.asKey()));
uint16_t swizzleKey = 0;
if (caps.shaderCaps()->textureSwizzleAppliedInShader()) {
swizzleKey = swizzle.asKey();
}
uint16_t swizzleKey = swizzle.asKey();
return SkToU32(samplerTypeKey | swizzleKey << kSamplerOrImageTypeKeyBits);
}

View File

@ -56,9 +56,6 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fHalfIs32Bits = false;
fHasLowFragmentPrecision = false;
fColorSpaceMathNeedsFloat = false;
// Backed API support is required to be able to make swizzle-neutral shaders (e.g.
// GL_ARB_texture_swizzle).
fTextureSwizzleAppliedInShader = true;
fBuiltinFMASupport = false;
fCanUseDoLoops = true;
@ -140,7 +137,6 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("half == fp32", fHalfIs32Bits);
writer->appendBool("Has poor fragment precision", fHasLowFragmentPrecision);
writer->appendBool("Color space math needs float", fColorSpaceMathNeedsFloat);
writer->appendBool("Texture swizzle applied in shader", fTextureSwizzleAppliedInShader);
writer->appendBool("Builtin fma() support", fBuiltinFMASupport);
writer->appendBool("Can use do-while loops", fCanUseDoLoops);

View File

@ -251,8 +251,6 @@ public:
bool tessellationSupport() const { return SkToBool(fMaxTessellationSegments);}
bool textureSwizzleAppliedInShader() const { return fTextureSwizzleAppliedInShader; }
GrGLSLGeneration generation() const { return fGLSLGeneration; }
private:
@ -280,7 +278,6 @@ private:
bool fFloatIs32Bits : 1;
bool fHalfIs32Bits : 1;
bool fHasLowFragmentPrecision : 1;
bool fTextureSwizzleAppliedInShader : 1;
// Used by SkSL to know when to generate polyfills.
bool fBuiltinFMASupport : 1;

View File

@ -66,6 +66,7 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
fProgramBinarySupport = false;
fProgramParameterSupport = false;
fSamplerObjectSupport = false;
fTextureSwizzleSupport = false;
fTiledRenderingSupport = false;
fFBFetchRequiresEnablePerSample = false;
fSRGBWriteControl = false;
@ -266,11 +267,11 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
if (GR_IS_GR_GL(standard)) {
if (version >= GR_GL_VER(3,3) || ctxInfo.hasExtension("GL_ARB_texture_swizzle")) {
this->fShaderCaps->fTextureSwizzleAppliedInShader = false;
fTextureSwizzleSupport = true;
}
} else if (GR_IS_GR_GL_ES(standard)) {
if (version >= GR_GL_VER(3,0)) {
this->fShaderCaps->fTextureSwizzleAppliedInShader = false;
fTextureSwizzleSupport = true;
}
} // no WebGL support
@ -731,8 +732,7 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
&formatWorkarounds);
}
// Requires fTextureSwizzleSupport, msaa support, ES compatibility have
// already been detected.
// Requires msaa support, ES compatibility have already been detected.
this->initFormatTable(ctxInfo, gli, formatWorkarounds);
this->finishInitialization(contextOptions);
@ -1216,6 +1216,7 @@ void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Program binary support", fProgramBinarySupport);
writer->appendBool("Program parameters support", fProgramParameterSupport);
writer->appendBool("Sampler object support", fSamplerObjectSupport);
writer->appendBool("Texture swizzle support", fTextureSwizzleSupport);
writer->appendBool("Tiled rendering support", fTiledRenderingSupport);
writer->appendBool("FB fetch requires enable per sample", fFBFetchRequiresEnablePerSample);
writer->appendBool("sRGB Write Control", fSRGBWriteControl);

View File

@ -431,6 +431,8 @@ public:
bool samplerObjectSupport() const { return fSamplerObjectSupport; }
bool textureSwizzleSupport() const { return fTextureSwizzleSupport; }
bool tiledRenderingSupport() const { return fTiledRenderingSupport; }
bool fbFetchRequiresEnablePerSample() const { return fFBFetchRequiresEnablePerSample; }
@ -541,6 +543,7 @@ private:
bool fProgramBinarySupport : 1;
bool fProgramParameterSupport : 1;
bool fSamplerObjectSupport : 1;
bool fTextureSwizzleSupport : 1;
bool fTiledRenderingSupport : 1;
bool fFBFetchRequiresEnablePerSample : 1;
bool fSRGBWriteControl : 1;

View File

@ -2563,20 +2563,6 @@ void GrGLGpu::flushBlendAndColorWrite(
this->flushColorWrite(blendInfo.fWriteColor);
}
static void get_gl_swizzle_values(const GrSwizzle& swizzle, GrGLenum glValues[4]) {
for (int i = 0; i < 4; ++i) {
switch (swizzle[i]) {
case 'r': glValues[i] = GR_GL_RED; break;
case 'g': glValues[i] = GR_GL_GREEN; break;
case 'b': glValues[i] = GR_GL_BLUE; break;
case 'a': glValues[i] = GR_GL_ALPHA; break;
case '0': glValues[i] = GR_GL_ZERO; break;
case '1': glValues[i] = GR_GL_ONE; break;
default: SK_ABORT("Unsupported component");
}
}
}
void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwizzle& swizzle,
GrGLTexture* texture) {
SkASSERT(texture);
@ -2680,25 +2666,29 @@ void GrGLGpu::bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwiz
GrGLTextureParameters::NonsamplerState newNonsamplerState;
newNonsamplerState.fBaseMipMapLevel = 0;
newNonsamplerState.fMaxMipmapLevel = texture->maxMipmapLevel();
newNonsamplerState.fSwizzleIsRGBA = true;
const GrGLTextureParameters::NonsamplerState& oldNonsamplerState =
texture->parameters()->nonsamplerState();
if (!this->caps()->shaderCaps()->textureSwizzleAppliedInShader()) {
newNonsamplerState.fSwizzleKey = swizzle.asKey();
if (setAll || swizzle.asKey() != oldNonsamplerState.fSwizzleKey) {
GrGLenum glValues[4];
get_gl_swizzle_values(swizzle, glValues);
if (this->glCaps().textureSwizzleSupport()) {
if (setAll || !oldNonsamplerState.fSwizzleIsRGBA) {
static constexpr GrGLenum kRGBA[4] {
GR_GL_RED,
GR_GL_GREEN,
GR_GL_BLUE,
GR_GL_ALPHA
};
this->setTextureUnit(unitIdx);
if (GR_IS_GR_GL(this->glStandard())) {
static_assert(sizeof(glValues[0]) == sizeof(GrGLint));
static_assert(sizeof(kRGBA[0]) == sizeof(GrGLint));
GL_CALL(TexParameteriv(target, GR_GL_TEXTURE_SWIZZLE_RGBA,
reinterpret_cast<const GrGLint*>(glValues)));
reinterpret_cast<const GrGLint*>(kRGBA)));
} else if (GR_IS_GR_GL_ES(this->glStandard())) {
// ES3 added swizzle support but not GL_TEXTURE_SWIZZLE_RGBA.
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, glValues[0]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, glValues[1]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, glValues[2]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, glValues[3]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_R, kRGBA[0]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_G, kRGBA[1]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_B, kRGBA[2]));
GL_CALL(TexParameteri(target, GR_GL_TEXTURE_SWIZZLE_A, kRGBA[3]));
}
}
}

View File

@ -32,10 +32,10 @@ void GrGLTextureParameters::SamplerOverriddenState::invalidate() {
GrGLTextureParameters::NonsamplerState::NonsamplerState()
// These are the OpenGL defaults.
: fSwizzleKey(GrSwizzle::RGBA().asKey()), fBaseMipMapLevel(0), fMaxMipmapLevel(1000) {}
: fBaseMipMapLevel(0), fMaxMipmapLevel(1000), fSwizzleIsRGBA(true) {}
void GrGLTextureParameters::NonsamplerState::invalidate() {
fSwizzleKey = ~0U;
fSwizzleIsRGBA = false;
fBaseMipMapLevel = ~0;
fMaxMipmapLevel = ~0;
}

View File

@ -83,10 +83,8 @@ GrGLSLUniformHandler::SamplerHandle GrGLUniformHandler::addSampler(
-1
});
if (shaderCaps->textureSwizzleAppliedInShader()) {
fSamplerSwizzles.push_back(swizzle);
SkASSERT(fSamplers.count() == fSamplerSwizzles.count());
}
return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);
}

View File

@ -66,11 +66,8 @@ public:
}
GrSwizzle samplerSwizzle(SamplerHandle handle) const {
if (this->caps()->shaderCaps()->textureSwizzleAppliedInShader()) {
return this->uniformHandler()->samplerSwizzle(handle);
}
return GrSwizzle::RGBA();
}
// Used to add a uniform for the RenderTarget width (used for sk_Width) without mangling
// the name of the uniform inside of a stage.

View File

@ -108,7 +108,7 @@ protected:
private:
virtual const char * samplerVariable(SamplerHandle) const = 0;
// Only called if GrShaderCaps(:textureSwizzleAppliedInShader() == true.
virtual GrSwizzle samplerSwizzle(SamplerHandle) const = 0;
virtual SamplerHandle addSampler(const GrBackendFormat&, GrSamplerState, const GrSwizzle&,

View File

@ -270,7 +270,6 @@ GrGLSLUniformHandler::SamplerHandle GrMtlUniformHandler::addSampler(
0
});
SkASSERT(caps->textureSwizzleAppliedInShader());
fSamplerSwizzles.push_back(swizzle);
SkASSERT(fSamplerSwizzles.count() == fSamplers.count());
return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);

View File

@ -287,7 +287,6 @@ GrGLSLUniformHandler::SamplerHandle GrVkUniformHandler::addSampler(
SkASSERT(info.fImmutableSampler);
}
SkASSERT(shaderCaps->textureSwizzleAppliedInShader());
fSamplerSwizzles.push_back(swizzle);
SkASSERT(fSamplerSwizzles.count() == fSamplers.count());
return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);

View File

@ -29,9 +29,12 @@ static bool sampler_params_invalid(const GrGLTextureParameters& parameters) {
}
static bool nonsampler_params_invalid(const GrGLTextureParameters& parameters) {
GrGLTextureParameters::NonsamplerState nsState = parameters.nonsamplerState();
GrGLTextureParameters::NonsamplerState invalidNSState;
invalidNSState.invalidate();
return 0 == memcmp(&parameters.nonsamplerState(), &invalidNSState, sizeof(invalidNSState));
return nsState.fBaseMipMapLevel == invalidNSState.fBaseMipMapLevel &&
nsState.fMaxMipmapLevel == invalidNSState.fMaxMipmapLevel &&
nsState.fSwizzleIsRGBA == invalidNSState.fSwizzleIsRGBA;
}
static bool params_invalid(const GrGLTextureParameters& parameters) {