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:
parent
21a465d7f4
commit
a6b92ad1f7
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1197,6 +1197,7 @@ void GrGLCaps::initShaderPrecisionTable(const GrGLContextInfo& ctxInfo,
|
||||
glslCaps->fFloatPrecisions[kVertex_GrShaderType][p];
|
||||
}
|
||||
}
|
||||
glslCaps->initSamplerPrecisionTable();
|
||||
}
|
||||
|
||||
bool GrGLCaps::bgraIsInternalFormat() const {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user