Add texture filtering precision hint
A new extension will be added to SwiftShader in order to allow
Chromium to trigger high precision filtering when necessary.
This extension is documented in:
extensions/CHROMIUM_texture_filtering_hint.txt
Bug swiftshader:76
Change-Id: I7c5b5c5fd01afbd7079e7949ecbd9c18fc539f2b
Reviewed-on: https://swiftshader-review.googlesource.com/10708
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/extensions/CHROMIUM_texture_filtering_hint.txt b/extensions/CHROMIUM_texture_filtering_hint.txt
new file mode 100644
index 0000000..38af6e0
--- /dev/null
+++ b/extensions/CHROMIUM_texture_filtering_hint.txt
@@ -0,0 +1,85 @@
+Name
+
+ CHROMIUM_texture_filtering_hint
+
+Name Strings
+
+ GL_CHROMIUM_texture_filtering_hint
+
+Contributors
+
+ Alexis Hetu, Google Inc.
+ Nicolas Capens, Google Inc.
+ Shannon Woods, Google Inc.
+
+Contact
+
+ Alexis Hetu, Google Inc. (sugoi 'at' chromium 'dot' org)
+
+Version
+
+ Last Modifed Date: July 18, 2017
+
+Dependencies
+
+ This extension is written against the OpenGL ES 2.0 specification.
+
+ OpenGL ES 2.0 is required.
+
+Overview
+
+ This extension defines a way to request high precision texture filtering
+ using a new value to Hint.
+
+ When this extension is enabled, TEXTURE_FILTERING_HINT_CHROMIUM can be used
+ by the implementation as a means to distinguish between a performance
+ focused implementation, using FASTEST, or a precision focused
+ implementation, using NICEST.
+
+ Like other hints, either option is spec compliant and the behavior of
+ DONT_CARE is implementation specific.
+
+New Tokens
+
+ Accepted by the <pname> parameter of GetIntegerv, GetFloatv and GetBooleanv
+ and by the <target> parameter of Hint:
+
+ TEXTURE_FILTERING_HINT_CHROMIUM 0x8AF0
+
+New Procedures and Functions
+
+ None.
+
+Errors
+
+ None.
+
+New State
+
+ None.
+
+Issues
+
+ 1) When does the hint take effect?
+
+ At the time of the next draw call, and all subsequent draw calls.
+
+ 2) Does the first draw call after the filtering hint is changed use the
+ updated filtering method?
+
+ Yes
+
+ 3) Can I switch it back and forth between every draw call, multiple times
+ during a single frame?
+
+ Yes
+
+ 4) Do program objects which were created before the filtering hint was
+ changed and which contain sampling instructions use the filtering method
+ from when they were created, or the method at the time of draw call?
+
+ At the time of draw call.
+
+Revision History
+
+ 2/7/2014 Documented the extension
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 2265aa6..c139068 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -100,6 +100,7 @@
mState.rasterizerDiscardEnabled = false;
mState.generateMipmapHint = GL_DONT_CARE;
mState.fragmentShaderDerivativeHint = GL_DONT_CARE;
+ mState.textureFilteringHint = GL_DONT_CARE;
mState.lineWidth = 1.0f;
@@ -682,6 +683,11 @@
// Ignore for now. It is valid for implementations to ignore hint.
}
+void Context::setTextureFilteringHint(GLenum hint)
+{
+ mState.textureFilteringHint = hint;
+}
+
void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
{
mState.viewportX = x;
@@ -1890,6 +1896,7 @@
case GL_UNPACK_ALIGNMENT: *params = mState.unpackInfo.alignment; return true;
case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; return true;
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; return true;
+ case GL_TEXTURE_FILTERING_HINT_CHROMIUM: *params = mState.textureFilteringHint; return true;
case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); return true;
case GL_STENCIL_FUNC: *params = mState.stencilFunc; return true;
case GL_STENCIL_REF: *params = mState.stencilRef; return true;
@@ -2425,6 +2432,7 @@
case GL_UNPACK_ALIGNMENT:
case GL_GENERATE_MIPMAP_HINT:
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+ case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
case GL_RED_BITS:
case GL_GREEN_BITS:
case GL_BLUE_BITS:
@@ -3058,6 +3066,7 @@
device->setTextureFilter(samplerType, samplerIndex, es2sw::ConvertTextureFilter(minFilter, magFilter, maxAnisotropy));
device->setMipmapFilter(samplerType, samplerIndex, es2sw::ConvertMipMapFilter(minFilter));
device->setMaxAnisotropy(samplerType, samplerIndex, maxAnisotropy);
+ device->setHighPrecisionFiltering(samplerType, samplerIndex, mState.textureFilteringHint == GL_NICEST);
applyTexture(samplerType, samplerIndex, texture);
}
@@ -4324,6 +4333,7 @@
"GL_ANGLE_texture_compression_dxt3",
"GL_ANGLE_texture_compression_dxt5",
#endif
+ "GL_CHROMIUM_texture_filtering_hint",
"GL_NV_fence",
"GL_NV_framebuffer_blit",
"GL_NV_read_depth",
diff --git a/src/OpenGL/libGLESv2/Context.h b/src/OpenGL/libGLESv2/Context.h
index bbe6ddd..16e0aa2 100644
--- a/src/OpenGL/libGLESv2/Context.h
+++ b/src/OpenGL/libGLESv2/Context.h
@@ -156,6 +156,8 @@
#endif
};
+const GLenum GL_TEXTURE_FILTERING_HINT_CHROMIUM = 0x8AF0;
+
const GLint NUM_COMPRESSED_TEXTURE_FORMATS = sizeof(compressedTextureFormats) / sizeof(compressedTextureFormats[0]);
const GLint multisampleCount[] = {4, 2, 1};
@@ -376,6 +378,7 @@
GLenum generateMipmapHint;
GLenum fragmentShaderDerivativeHint;
+ GLenum textureFilteringHint;
GLint viewportX;
GLint viewportY;
@@ -489,6 +492,7 @@
void setGenerateMipmapHint(GLenum hint);
void setFragmentShaderDerivativeHint(GLenum hint);
+ void setTextureFilteringHint(GLenum hint);
void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index 920e1a0..dfe5959 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -4247,6 +4247,9 @@
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
if(context) context->setFragmentShaderDerivativeHint(mode);
break;
+ case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
+ if(context) context->setTextureFilteringHint(mode);
+ break;
default:
return error(GL_INVALID_ENUM);
}
diff --git a/src/Renderer/PixelProcessor.cpp b/src/Renderer/PixelProcessor.cpp
index 172e8ef..db11aed 100644
--- a/src/Renderer/PixelProcessor.cpp
+++ b/src/Renderer/PixelProcessor.cpp
@@ -444,6 +444,15 @@
else ASSERT(false);
}
+ void PixelProcessor::setHighPrecisionFiltering(unsigned int sampler, bool highPrecisionFiltering)
+ {
+ if(sampler < TEXTURE_IMAGE_UNITS)
+ {
+ context->sampler[sampler].setHighPrecisionFiltering(highPrecisionFiltering);
+ }
+ else ASSERT(false);
+ }
+
void PixelProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR)
{
if(sampler < TEXTURE_IMAGE_UNITS)
diff --git a/src/Renderer/PixelProcessor.hpp b/src/Renderer/PixelProcessor.hpp
index 94d52d3..dd54b72 100644
--- a/src/Renderer/PixelProcessor.hpp
+++ b/src/Renderer/PixelProcessor.hpp
@@ -231,6 +231,7 @@
void setMipmapLOD(unsigned int sampler, float bias);
void setBorderColor(unsigned int sampler, const Color<float> &borderColor);
void setMaxAnisotropy(unsigned int sampler, float maxAnisotropy);
+ void setHighPrecisionFiltering(unsigned int sampler, bool highPrecisionFiltering);
void setSwizzleR(unsigned int sampler, SwizzleType swizzleR);
void setSwizzleG(unsigned int sampler, SwizzleType swizzleG);
void setSwizzleB(unsigned int sampler, SwizzleType swizzleB);
diff --git a/src/Renderer/Renderer.cpp b/src/Renderer/Renderer.cpp
index a84423d..a67ba22 100644
--- a/src/Renderer/Renderer.cpp
+++ b/src/Renderer/Renderer.cpp
@@ -2314,6 +2314,18 @@
}
}
+ void Renderer::setHighPrecisionFiltering(SamplerType type, int sampler, bool highPrecisionFiltering)
+ {
+ if(type == SAMPLER_PIXEL)
+ {
+ PixelProcessor::setHighPrecisionFiltering(sampler, highPrecisionFiltering);
+ }
+ else
+ {
+ VertexProcessor::setHighPrecisionFiltering(sampler, highPrecisionFiltering);
+ }
+ }
+
void Renderer::setSwizzleR(SamplerType type, int sampler, SwizzleType swizzleR)
{
if(type == SAMPLER_PIXEL)
diff --git a/src/Renderer/Renderer.hpp b/src/Renderer/Renderer.hpp
index c59dd31..c29020f 100644
--- a/src/Renderer/Renderer.hpp
+++ b/src/Renderer/Renderer.hpp
@@ -345,6 +345,7 @@
void setMipmapLOD(SamplerType type, int sampler, float bias);
void setBorderColor(SamplerType type, int sampler, const Color<float> &borderColor);
void setMaxAnisotropy(SamplerType type, int sampler, float maxAnisotropy);
+ void setHighPrecisionFiltering(SamplerType type, int sampler, bool highPrecisionFiltering);
void setSwizzleR(SamplerType type, int sampler, SwizzleType swizzleR);
void setSwizzleG(SamplerType type, int sampler, SwizzleType swizzleG);
void setSwizzleB(SamplerType type, int sampler, SwizzleType swizzleB);
diff --git a/src/Renderer/Sampler.cpp b/src/Renderer/Sampler.cpp
index e2447e0..7d7d47c 100644
--- a/src/Renderer/Sampler.cpp
+++ b/src/Renderer/Sampler.cpp
@@ -60,6 +60,7 @@
mipmapFilterState = MIPMAP_NONE;
sRGB = false;
gather = false;
+ highPrecisionFiltering = false;
swizzleR = SWIZZLE_RED;
swizzleG = SWIZZLE_GREEN;
@@ -97,6 +98,7 @@
state.swizzleG = swizzleG;
state.swizzleB = swizzleB;
state.swizzleA = swizzleA;
+ state.highPrecisionFiltering = highPrecisionFiltering;
#if PERF_PROFILE
state.compressedFormat = Surface::isCompressed(externalTextureFormat);
@@ -298,6 +300,11 @@
texture.maxAnisotropy = maxAnisotropy;
}
+ void Sampler::setHighPrecisionFiltering(bool highPrecisionFiltering)
+ {
+ this->highPrecisionFiltering = highPrecisionFiltering;
+ }
+
void Sampler::setSwizzleR(SwizzleType swizzleR)
{
this->swizzleR = swizzleR;
diff --git a/src/Renderer/Sampler.hpp b/src/Renderer/Sampler.hpp
index 4c4973d..288f179 100644
--- a/src/Renderer/Sampler.hpp
+++ b/src/Renderer/Sampler.hpp
@@ -140,6 +140,7 @@
SwizzleType swizzleG : BITS(SWIZZLE_LAST);
SwizzleType swizzleB : BITS(SWIZZLE_LAST);
SwizzleType swizzleA : BITS(SWIZZLE_LAST);
+ bool highPrecisionFiltering : 1;
#if PERF_PROFILE
bool compressedFormat : 1;
@@ -163,6 +164,7 @@
void setReadSRGB(bool sRGB);
void setBorderColor(const Color<float> &borderColor);
void setMaxAnisotropy(float maxAnisotropy);
+ void setHighPrecisionFiltering(bool highPrecisionFiltering);
void setSwizzleR(SwizzleType swizzleR);
void setSwizzleG(SwizzleType swizzleG);
void setSwizzleB(SwizzleType swizzleB);
@@ -202,6 +204,7 @@
MipmapType mipmapFilterState;
bool sRGB;
bool gather;
+ bool highPrecisionFiltering;
SwizzleType swizzleR;
SwizzleType swizzleG;
diff --git a/src/Renderer/VertexProcessor.cpp b/src/Renderer/VertexProcessor.cpp
index 91c4d34..6972d94 100644
--- a/src/Renderer/VertexProcessor.cpp
+++ b/src/Renderer/VertexProcessor.cpp
@@ -602,6 +602,15 @@
else ASSERT(false);
}
+ void VertexProcessor::setHighPrecisionFiltering(unsigned int sampler, bool highPrecisionFiltering)
+ {
+ if(sampler < TEXTURE_IMAGE_UNITS)
+ {
+ context->sampler[sampler].setHighPrecisionFiltering(highPrecisionFiltering);
+ }
+ else ASSERT(false);
+ }
+
void VertexProcessor::setSwizzleR(unsigned int sampler, SwizzleType swizzleR)
{
if(sampler < VERTEX_TEXTURE_IMAGE_UNITS)
diff --git a/src/Renderer/VertexProcessor.hpp b/src/Renderer/VertexProcessor.hpp
index 278c9b1..3552f84 100644
--- a/src/Renderer/VertexProcessor.hpp
+++ b/src/Renderer/VertexProcessor.hpp
@@ -258,6 +258,7 @@
void setMipmapLOD(unsigned int sampler, float bias);
void setBorderColor(unsigned int sampler, const Color<float> &borderColor);
void setMaxAnisotropy(unsigned int stage, float maxAnisotropy);
+ void setHighPrecisionFiltering(unsigned int sampler, bool highPrecisionFiltering);
void setSwizzleR(unsigned int sampler, SwizzleType swizzleR);
void setSwizzleG(unsigned int sampler, SwizzleType swizzleG);
void setSwizzleB(unsigned int sampler, SwizzleType swizzleB);
diff --git a/src/Shader/SamplerCore.cpp b/src/Shader/SamplerCore.cpp
index 8c20f58..9bd977e 100644
--- a/src/Shader/SamplerCore.cpp
+++ b/src/Shader/SamplerCore.cpp
@@ -314,7 +314,7 @@
}
else
{
- if(hasFloatTexture()) // FIXME: Mostly identical to integer sampling
+ if(hasFloatTexture() || state.highPrecisionFiltering) // FIXME: Mostly identical to integer sampling
{
Float4 uuuu = u;
Float4 vvvv = v;