Infer sampler precision from pixel config

Adds a "samplerPrecision" method to GrGLSLCaps and updates
GrGLSLProgramBuilder to infer a sampler's precision based on its
config and visibility.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1846963004

Review URL: https://codereview.chromium.org/1846963004
This commit is contained in:
cdalton 2016-04-11 12:03:08 -07:00 committed by Commit bot
parent 21a465d7f4
commit a6b92ad1f7
9 changed files with 114 additions and 39 deletions

View File

@ -30,30 +30,25 @@ public:
explicit GrTextureAccess(GrTexture*,
GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode,
SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode,
GrShaderFlags visibility = kFragment_GrShaderFlag,
GrSLPrecision = kDefault_GrSLPrecision);
GrShaderFlags visibility = kFragment_GrShaderFlag);
void reset(GrTexture*, const GrTextureParams&,
GrShaderFlags visibility = kFragment_GrShaderFlag,
GrSLPrecision = kDefault_GrSLPrecision);
GrShaderFlags visibility = kFragment_GrShaderFlag);
void reset(GrTexture*,
GrTextureParams::FilterMode = GrTextureParams::kNone_FilterMode,
SkShader::TileMode tileXAndY = SkShader::kClamp_TileMode,
GrShaderFlags visibility = kFragment_GrShaderFlag,
GrSLPrecision = kDefault_GrSLPrecision);
GrShaderFlags visibility = kFragment_GrShaderFlag);
bool operator==(const GrTextureAccess& that) const {
return this->getTexture() == that.getTexture() &&
fParams == that.fParams &&
fVisibility == that.fVisibility &&
fPrecision == that.fPrecision;
fVisibility == that.fVisibility;
}
bool operator!=(const GrTextureAccess& other) const { return !(*this == other); }
GrTexture* getTexture() const { return fTexture.get(); }
GrShaderFlags getVisibility() const { return fVisibility; }
GrSLPrecision getPrecision() const { return fPrecision; }
/**
* For internal use by GrProcessor.
@ -69,7 +64,6 @@ private:
ProgramTexture fTexture;
GrTextureParams fParams;
GrShaderFlags fVisibility;
GrSLPrecision fPrecision;
typedef SkNoncopyable INHERITED;
};

View File

@ -18,30 +18,25 @@ GrTextureAccess::GrTextureAccess(GrTexture* texture, const GrTextureParams& para
GrTextureAccess::GrTextureAccess(GrTexture* texture,
GrTextureParams::FilterMode filterMode,
SkShader::TileMode tileXAndY,
GrShaderFlags visibility,
GrSLPrecision precision) {
this->reset(texture, filterMode, tileXAndY, visibility, precision);
GrShaderFlags visibility) {
this->reset(texture, filterMode, tileXAndY, visibility);
}
void GrTextureAccess::reset(GrTexture* texture,
const GrTextureParams& params,
GrShaderFlags visibility,
GrSLPrecision precision) {
GrShaderFlags visibility) {
SkASSERT(texture);
fTexture.set(SkRef(texture), kRead_GrIOType);
fParams = params;
fVisibility = visibility;
fPrecision = precision;
}
void GrTextureAccess::reset(GrTexture* texture,
GrTextureParams::FilterMode filterMode,
SkShader::TileMode tileXAndY,
GrShaderFlags visibility,
GrSLPrecision precision) {
GrShaderFlags visibility) {
SkASSERT(texture);
fTexture.set(SkRef(texture), kRead_GrIOType);
fParams.reset(tileXAndY, filterMode);
fVisibility = visibility;
fPrecision = precision;
}

View File

@ -1197,6 +1197,7 @@ void GrGLCaps::initShaderPrecisionTable(const GrGLContextInfo& ctxInfo,
glslCaps->fFloatPrecisions[kVertex_GrShaderType][p];
}
}
glslCaps->initSamplerPrecisionTable();
}
bool GrGLCaps::bgraIsInternalFormat() const {

View File

@ -17,24 +17,27 @@
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLCaps.h"
static uint8_t texture_target_key(GrGLenum target) {
switch (target) {
case GR_GL_TEXTURE_2D:
return 0;
case GR_GL_TEXTURE_EXTERNAL:
return 1;
case GR_GL_TEXTURE_RECTANGLE:
return 2;
default:
SkFAIL("Unexpected texture target.");
return 0;
}
static uint16_t texture_key(GrSLType samplerType, GrPixelConfig config, GrShaderFlags visibility,
const GrGLSLCaps& caps) {
enum {
kFirstSamplerType = kSampler2D_GrSLType,
kLastSamplerType = kSampler2DRect_GrSLType,
kSamplerTypeKeyBits = 4
};
GR_STATIC_ASSERT(kLastSamplerType - kFirstSamplerType < (1 << kSamplerTypeKeyBits));
SkASSERT((int)samplerType >= kFirstSamplerType && (int)samplerType <= kLastSamplerType);
int samplerTypeKey = samplerType - kFirstSamplerType;
return SkToU16(caps.configTextureSwizzle(config).asKey() |
(samplerTypeKey << 8) |
(caps.samplerPrecision(config, visibility) << (8 + kSamplerTypeKeyBits)));
}
static void add_texture_key(GrProcessorKeyBuilder* b, const GrProcessor& proc,
const GrGLSLCaps& caps) {
int numTextures = proc.numTextures();
// Need two bytes per key (swizzle and target).
// Need two bytes per key (swizzle, sampler type, and precision).
int word32Count = (proc.numTextures() + 1) / 2;
if (0 == word32Count) {
return;
@ -42,9 +45,8 @@ static void add_texture_key(GrProcessorKeyBuilder* b, const GrProcessor& proc,
uint16_t* k16 = SkTCast<uint16_t*>(b->add32n(word32Count));
for (int i = 0; i < numTextures; ++i) {
const GrTextureAccess& access = proc.textureAccess(i);
GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture());
k16[i] = SkToU16(caps.configTextureSwizzle(texture->config()).asKey() |
(texture_target_key(texture->target()) << 8));
const GrTexture* tex = access.getTexture();
k16[i] = texture_key(tex->samplerType(), tex->config(), access.getVisibility(), caps);
}
// zero the last 16 bits if the number of textures is odd.
if (numTextures & 0x1) {

View File

@ -92,5 +92,60 @@ SkString GrGLSLCaps::dump() const {
return r;
}
void GrGLSLCaps::initSamplerPrecisionTable() {
// Determine the largest precision qualifiers that are effectively the same as lowp/mediump.
// e.g. if lowp == mediump, then use mediump instead of lowp.
GrSLPrecision effectiveMediumP[kGrShaderTypeCount];
GrSLPrecision effectiveLowP[kGrShaderTypeCount];
for (int s = 0; s < kGrShaderTypeCount; ++s) {
const PrecisionInfo* info = fFloatPrecisions[s];
effectiveMediumP[s] = info[kHigh_GrSLPrecision] == info[kMedium_GrSLPrecision] ?
kHigh_GrSLPrecision : kMedium_GrSLPrecision;
effectiveLowP[s] = info[kMedium_GrSLPrecision] == info[kLow_GrSLPrecision] ?
effectiveMediumP[s] : kLow_GrSLPrecision;
}
// Determine which precision qualifiers should be used with samplers.
for (int visibility = 0; visibility < (1 << kGrShaderTypeCount); ++visibility) {
GrSLPrecision mediump = kHigh_GrSLPrecision;
GrSLPrecision lowp = kHigh_GrSLPrecision;
for (int s = 0; s < kGrShaderTypeCount; ++s) {
if (visibility & (1 << s)) {
mediump = SkTMin(mediump, effectiveMediumP[s]);
lowp = SkTMin(lowp, effectiveLowP[s]);
}
GR_STATIC_ASSERT(0 == kLow_GrSLPrecision);
GR_STATIC_ASSERT(1 == kMedium_GrSLPrecision);
GR_STATIC_ASSERT(2 == kHigh_GrSLPrecision);
GR_STATIC_ASSERT((1 << kVertex_GrShaderType) == kVertex_GrShaderFlag);
GR_STATIC_ASSERT((1 << kGeometry_GrShaderType) == kGeometry_GrShaderFlag);
GR_STATIC_ASSERT((1 << kFragment_GrShaderType) == kFragment_GrShaderFlag);
GR_STATIC_ASSERT(3 == kGrShaderTypeCount);
}
uint8_t* table = fSamplerPrecisions[visibility];
table[kUnknown_GrPixelConfig] = kDefault_GrSLPrecision;
table[kAlpha_8_GrPixelConfig] = lowp;
table[kIndex_8_GrPixelConfig] = lowp;
table[kRGB_565_GrPixelConfig] = lowp;
table[kRGBA_4444_GrPixelConfig] = lowp;
table[kRGBA_8888_GrPixelConfig] = lowp;
table[kBGRA_8888_GrPixelConfig] = lowp;
table[kSRGBA_8888_GrPixelConfig] = lowp;
table[kSBGRA_8888_GrPixelConfig] = lowp;
table[kETC1_GrPixelConfig] = lowp;
table[kLATC_GrPixelConfig] = lowp;
table[kR11_EAC_GrPixelConfig] = lowp;
table[kASTC_12x12_GrPixelConfig] = lowp;
table[kRGBA_float_GrPixelConfig] = kHigh_GrSLPrecision;
table[kAlpha_half_GrPixelConfig] = mediump;
table[kRGBA_half_GrPixelConfig] = mediump;
GR_STATIC_ASSERT(16 == kGrPixelConfigCnt);
}
}
void GrGLSLCaps::onApplyOptionsOverrides(const GrContextOptions& options) {
}

View File

@ -162,6 +162,11 @@ public:
return fConfigOutputSwizzle[config];
}
/** Precision qualifier that should be used with a sampler, given its config and visibility. */
GrSLPrecision samplerPrecision(GrPixelConfig config, GrShaderFlags visibility) const {
return static_cast<GrSLPrecision>(fSamplerPrecisions[visibility][config]);
}
GrGLSLGeneration generation() const { return fGLSLGeneration; }
/**
@ -170,6 +175,9 @@ public:
SkString dump() const override;
private:
/** GrCaps subclasses must call this after filling in the shader precision table. */
void initSamplerPrecisionTable();
void onApplyOptionsOverrides(const GrContextOptions& options) override;
GrGLSLGeneration fGLSLGeneration;
@ -216,6 +224,8 @@ private:
GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt];
GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt];
uint8_t fSamplerPrecisions[(1 << kGrShaderTypeCount)][kGrPixelConfigCnt];
friend class GrGLCaps; // For initialization.
friend class GrVkCaps;

View File

@ -241,10 +241,12 @@ void GrGLSLProgramBuilder::emitSamplers(const GrProcessor& processor,
1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature,
externalFeatureString);
}
GrSLPrecision precision = this->glslCaps()->samplerPrecision(access.getTexture()->config(),
visibility);
name.printf("Sampler%d", t);
localSamplerUniforms[t] = this->uniformHandler()->addUniform(access.getVisibility(),
localSamplerUniforms[t] = this->uniformHandler()->addUniform(visibility,
samplerType,
access.getPrecision(),
precision,
name.c_str());
outSamplers->emplace_back(localSamplerUniforms[t], access);
}

View File

@ -154,6 +154,21 @@ void GrVkCaps::initGLSLCaps(const VkPhysicalDeviceProperties& properties,
glslCaps->fIntegerSupport = true;
// Assume the minimum precisions mandated by the SPIR-V spec.
glslCaps->fShaderPrecisionVaries = true;
for (int s = 0; s < kGrShaderTypeCount; ++s) {
auto& highp = glslCaps->fFloatPrecisions[s][kHigh_GrSLPrecision];
highp.fLogRangeLow = highp.fLogRangeHigh = 127;
highp.fBits = 23;
auto& mediump = glslCaps->fFloatPrecisions[s][kMedium_GrSLPrecision];
mediump.fLogRangeLow = mediump.fLogRangeHigh = 14;
mediump.fBits = 10;
glslCaps->fFloatPrecisions[s][kLow_GrSLPrecision] = mediump;
}
glslCaps->initSamplerPrecisionTable();
glslCaps->fMaxVertexSamplers =
glslCaps->fMaxGeometrySamplers =
glslCaps->fMaxFragmentSamplers = SkTMin(properties.limits.maxPerStageDescriptorSampledImages,

View File

@ -22,7 +22,7 @@
static void add_texture_key(GrProcessorKeyBuilder* b, const GrProcessor& proc,
const GrGLSLCaps& caps) {
int numTextures = proc.numTextures();
// Need two bytes per key (swizzle and target).
// Need two bytes per key (swizzle, sampler type, and precision).
int word32Count = (proc.numTextures() + 1) / 2;
if (0 == word32Count) {
return;
@ -31,7 +31,8 @@ static void add_texture_key(GrProcessorKeyBuilder* b, const GrProcessor& proc,
for (int i = 0; i < numTextures; ++i) {
const GrTextureAccess& access = proc.textureAccess(i);
GrTexture* texture = access.getTexture();
k16[i] = SkToU16(caps.configTextureSwizzle(texture->config()).asKey());
k16[i] = SkToU16(caps.configTextureSwizzle(texture->config()).asKey() |
(caps.samplerPrecision(texture->config(), access.getVisibility()) << 8));
}
// zero the last 16 bits if the number of textures is odd.
if (numTextures & 0x1) {