aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/gpu/GrContext.h1
-rw-r--r--include/gpu/GrContextOptions.h7
-rw-r--r--src/gpu/GrContext.cpp1
-rw-r--r--src/gpu/GrContextPriv.h1
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp1
-rw-r--r--src/gpu/vk/GrVkPipelineStateBuilder.cpp3
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.cpp8
-rw-r--r--src/sksl/SkSLSPIRVCodeGenerator.cpp12
-rw-r--r--src/sksl/ir/SkSLProgram.h2
-rw-r--r--tests/SkSLGLSLTest.cpp56
10 files changed, 90 insertions, 2 deletions
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index aac0d8dc5a..4d937c727e 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -370,6 +370,7 @@ private:
std::unique_ptr<GrTextBlobCache> fTextBlobCache;
bool fDisableGpuYUVConversion;
+ bool fSharpenMipmappedTextures;
bool fDidTestPMConversions;
// true if the PM/UPM conversion succeeded; false otherwise
bool fPMUPMConversionsRoundTrip;
diff --git a/include/gpu/GrContextOptions.h b/include/gpu/GrContextOptions.h
index 338c538963..84863f50a6 100644
--- a/include/gpu/GrContextOptions.h
+++ b/include/gpu/GrContextOptions.h
@@ -135,6 +135,13 @@ struct GrContextOptions {
bool fAvoidStencilBuffers = false;
/**
+ * If true, texture fetches from mip-mapped textures will be biased to read larger MIP levels.
+ * This has the effect of sharpening those textures, at the cost of some aliasing, and possible
+ * performance impact.
+ */
+ bool fSharpenMipmappedTextures = false;
+
+ /**
* Enables driver workaround to use draws instead of glClear. This only applies to
* kOpenGL_GrBackend.
*/
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 8a5417ed17..09985e6f79 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -255,6 +255,7 @@ bool GrContext::init(const GrContextOptions& options) {
options));
fDisableGpuYUVConversion = options.fDisableGpuYUVConversion;
+ fSharpenMipmappedTextures = options.fSharpenMipmappedTextures;
fDidTestPMConversions = false;
GrPathRendererChain::Options prcOptions;
diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h
index e0074252d8..93c1c17dc9 100644
--- a/src/gpu/GrContextPriv.h
+++ b/src/gpu/GrContextPriv.h
@@ -67,6 +67,7 @@ public:
const SkSurfaceProps* = nullptr);
bool disableGpuYUVConversion() const { return fContext->fDisableGpuYUVConversion; }
+ bool sharpenMipmappedTextures() const { return fContext->fSharpenMipmappedTextures; }
/**
* Call to ensure all drawing to the context has been issued to the
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 7ae63a262c..ed6386b7f3 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -152,6 +152,7 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
SkSL::Program::Settings settings;
settings.fCaps = this->gpu()->glCaps().shaderCaps();
settings.fFlipY = this->pipeline().proxy()->origin() != kTopLeft_GrSurfaceOrigin;
+ settings.fSharpenTextures = this->gpu()->getContext()->contextPriv().sharpenMipmappedTextures();
SkSL::Program::Inputs inputs;
SkTDArray<GrGLuint> shadersToDelete;
bool cached = nullptr != fCached.get();
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
index 9b9b070073..a263b776d1 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
@@ -7,6 +7,8 @@
#include "vk/GrVkPipelineStateBuilder.h"
+#include "GrContext.h"
+#include "GrContextPriv.h"
#include "GrShaderCaps.h"
#include "vk/GrVkDescriptorSetManager.h"
#include "vk/GrVkGpu.h"
@@ -141,6 +143,7 @@ GrVkPipelineState* GrVkPipelineStateBuilder::finalize(const GrStencilSettings& s
SkSL::Program::Settings settings;
settings.fCaps = this->caps()->shaderCaps();
settings.fFlipY = this->pipeline().proxy()->origin() != kTopLeft_GrSurfaceOrigin;
+ settings.fSharpenTextures = this->gpu()->getContext()->contextPriv().sharpenMipmappedTextures();
SkAssertResult(this->createVkShaderModule(VK_SHADER_STAGE_VERTEX_BIT,
fVS,
&vertShaderModule,
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index d02948f388..f94cc4ca0b 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -505,12 +505,14 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
fHeader.writeText(" : require\n");
fFoundDerivatives = true;
}
+ bool isTextureFunctionWithBias = false;
if (c.fFunction.fName == "texture" && c.fFunction.fBuiltin) {
const char* dim = "";
bool proj = false;
switch (c.fArguments[0]->fType.dimensions()) {
case SpvDim1D:
dim = "1D";
+ isTextureFunctionWithBias = true;
if (c.fArguments[1]->fType == *fContext.fFloat_Type) {
proj = false;
} else {
@@ -520,6 +522,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
break;
case SpvDim2D:
dim = "2D";
+ isTextureFunctionWithBias = true;
if (c.fArguments[1]->fType == *fContext.fFloat2_Type) {
proj = false;
} else {
@@ -529,6 +532,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
break;
case SpvDim3D:
dim = "3D";
+ isTextureFunctionWithBias = true;
if (c.fArguments[1]->fType == *fContext.fFloat3_Type) {
proj = false;
} else {
@@ -538,6 +542,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
break;
case SpvDimCube:
dim = "Cube";
+ isTextureFunctionWithBias = true;
proj = false;
break;
case SpvDimRect:
@@ -573,6 +578,9 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
separator = ", ";
this->writeExpression(*arg, kSequence_Precedence);
}
+ if (fProgram.fSettings.fSharpenTextures && isTextureFunctionWithBias) {
+ this->write(", -0.5");
+ }
this->write(")");
}
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index cb8b388521..d01a82dae2 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -824,8 +824,16 @@ SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIn
out);
} else {
ASSERT(c.fArguments.size() == 2);
- this->writeInstruction(op, type, result, sampler, uv,
- out);
+ if (fProgram.fSettings.fSharpenTextures) {
+ FloatLiteral lodBias(fContext, -1, -0.5);
+ this->writeInstruction(op, type, result, sampler, uv,
+ SpvImageOperandsBiasMask,
+ this->writeFloatLiteral(lodBias),
+ out);
+ } else {
+ this->writeInstruction(op, type, result, sampler, uv,
+ out);
+ }
}
break;
}
diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h
index 3184547476..a63cd237ac 100644
--- a/src/sksl/ir/SkSLProgram.h
+++ b/src/sksl/ir/SkSLProgram.h
@@ -76,6 +76,8 @@ struct Program {
bool fReplaceSettings = true;
// if true, all halfs are forced to be floats
bool fForceHighPrecision = false;
+ // if true, add -0.5 bias to LOD of all texture lookups
+ bool fSharpenTextures = false;
std::unordered_map<String, Value> fArgs;
};
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index 62c5cd6955..e63719781d 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -983,6 +983,62 @@ DEF_TEST(SkSLTexture, r) {
"}\n");
}
+DEF_TEST(SkSLSharpen, r) {
+ SkSL::Program::Settings settings;
+ settings.fSharpenTextures = true;
+ sk_sp<GrShaderCaps> caps = SkSL::ShaderCapsFactory::Default();
+ settings.fCaps = caps.get();
+ SkSL::Program::Inputs inputs;
+ test(r,
+ "uniform sampler1D one;"
+ "uniform sampler2D two;"
+ "void main() {"
+ "float4 a = texture(one, 0);"
+ "float4 b = texture(two, float2(0));"
+ "float4 c = texture(one, float2(0));"
+ "float4 d = texture(two, float3(0));"
+ "sk_FragColor = half4(a.x, b.x, c.x, d.x);"
+ "}",
+ settings,
+ "#version 400\n"
+ "out vec4 sk_FragColor;\n"
+ "uniform sampler1D one;\n"
+ "uniform sampler2D two;\n"
+ "void main() {\n"
+ " vec4 a = texture(one, 0.0, -0.5);\n"
+ " vec4 b = texture(two, vec2(0.0), -0.5);\n"
+ " vec4 c = textureProj(one, vec2(0.0), -0.5);\n"
+ " vec4 d = textureProj(two, vec3(0.0), -0.5);\n"
+ " sk_FragColor = vec4(a.x, b.x, c.x, d.x);\n"
+ "}\n",
+ &inputs);
+
+ caps = SkSL::ShaderCapsFactory::Version110();
+ settings.fCaps = caps.get();
+ test(r,
+ "uniform sampler1D one;"
+ "uniform sampler2D two;"
+ "void main() {"
+ "float4 a = texture(one, 0);"
+ "float4 b = texture(two, float2(0));"
+ "float4 c = texture(one, float2(0));"
+ "float4 d = texture(two, float3(0));"
+ "sk_FragColor = half4(a.x, b.x, c.x, d.x);"
+ "}",
+ settings,
+ "#version 110\n"
+ "uniform sampler1D one;\n"
+ "uniform sampler2D two;\n"
+ "void main() {\n"
+ " vec4 a = texture1D(one, 0.0, -0.5);\n"
+ " vec4 b = texture2D(two, vec2(0.0), -0.5);\n"
+ " vec4 c = texture1DProj(one, vec2(0.0), -0.5);\n"
+ " vec4 d = texture2DProj(two, vec3(0.0), -0.5);\n"
+ " gl_FragColor = vec4(a.x, b.x, c.x, d.x);\n"
+ "}\n",
+ &inputs);
+}
+
DEF_TEST(SkSLOffset, r) {
test(r,
"struct Test {"