Add support for immuatable samplers in vulkan.
For ycbcr conversions we need add immutable samplers to the creation of
the VkPipeline via the descriptor set layout.
Bug: skia:
Change-Id: I5eea6037191fd34d26d49f58533035316158cacd
Reviewed-on: https://skia-review.googlesource.com/c/171642
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index 5c10b9f..aa84c98 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -50,7 +50,7 @@
}
static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrFragmentProcessor& fp,
- const GrShaderCaps& caps) {
+ GrGpu* gpu, const GrShaderCaps& caps) {
int numTextureSamplers = fp.numTextureSamplers();
// Need two bytes per key.
int word32Count = (numTextureSamplers + 1) / 2;
@@ -62,6 +62,16 @@
const GrFragmentProcessor::TextureSampler& sampler = fp.textureSampler(i);
const GrTexture* tex = sampler.peekTexture();
k16[i] = sampler_key(tex->texturePriv().textureType(), tex->config(), caps);
+ uint32_t extraSamplerKey = gpu->getExtraSamplerKeyForProgram(
+ sampler.samplerState(), sampler.proxy()->backendFormat());
+ if (extraSamplerKey) {
+ SkASSERT(sampler.proxy()->textureType() == GrTextureType::kExternal);
+ // We first mark the normal sampler key with last bit to flag that it has an extra
+ // sampler key. We then add all the extraSamplerKeys to the end of the normal ones.
+ SkASSERT((k16[i] & (1 << 15)) == 0);
+ k16[i] = k16[i] | (1 << 15);
+ b->add32(extraSamplerKey);
+ }
}
// zero the last 16 bits if the number of uniforms for samplers is odd.
if (numTextureSamplers & 0x1) {
@@ -70,7 +80,7 @@
}
static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrPrimitiveProcessor& pp,
- const GrShaderCaps& caps) {
+ const GrShaderCaps& caps) {
int numTextureSamplers = pp.numTextureSamplers();
// Need two bytes per key.
int word32Count = (numTextureSamplers + 1) / 2;
@@ -81,6 +91,15 @@
for (int i = 0; i < numTextureSamplers; ++i) {
const GrPrimitiveProcessor::TextureSampler& sampler = pp.textureSampler(i);
k16[i] = sampler_key(sampler.textureType(), sampler.config(), caps);
+ uint32_t extraSamplerKey = sampler.extraSamplerKey();
+ if (extraSamplerKey) {
+ SkASSERT(sampler.textureType() == GrTextureType::kExternal);
+ // We first mark the normal sampler key with last bit to flag that it has an extra
+ // sampler key. We then add all the extraSamplerKeys to the end of the normal ones.
+ SkASSERT((k16[i] & (1 << 15)) == 0);
+ k16[i] = k16[i] | (1 << 15);
+ b->add32(extraSamplerKey);
+ }
}
// zero the last 16 bits if the number of uniforms for samplers is odd.
if (numTextureSamplers & 0x1) {
@@ -98,6 +117,7 @@
* function because it is hairy, though FPs do not have attribs, and GPs do not have transforms
*/
static bool gen_meta_key(const GrFragmentProcessor& fp,
+ GrGpu* gpu,
const GrShaderCaps& shaderCaps,
uint32_t transformKey,
GrProcessorKeyBuilder* b) {
@@ -110,7 +130,7 @@
return false;
}
- add_sampler_keys(b, fp, shaderCaps);
+ add_sampler_keys(b, fp, gpu, shaderCaps);
uint32_t* key = b->add32n(2);
key[0] = (classID << 16) | SkToU32(processorKeySize);
@@ -157,30 +177,33 @@
static bool gen_frag_proc_and_meta_keys(const GrPrimitiveProcessor& primProc,
const GrFragmentProcessor& fp,
+ GrGpu* gpu,
const GrShaderCaps& shaderCaps,
GrProcessorKeyBuilder* b) {
for (int i = 0; i < fp.numChildProcessors(); ++i) {
- if (!gen_frag_proc_and_meta_keys(primProc, fp.childProcessor(i), shaderCaps, b)) {
+ if (!gen_frag_proc_and_meta_keys(primProc, fp.childProcessor(i), gpu, shaderCaps, b)) {
return false;
}
}
fp.getGLSLProcessorKey(shaderCaps, b);
- return gen_meta_key(fp, shaderCaps, primProc.getTransformKey(fp.coordTransforms(),
- fp.numCoordTransforms()), b);
+ return gen_meta_key(fp, gpu, shaderCaps, primProc.getTransformKey(fp.coordTransforms(),
+ fp.numCoordTransforms()), b);
}
bool GrProgramDesc::Build(GrProgramDesc* desc,
const GrPrimitiveProcessor& primProc,
bool hasPointSize,
const GrPipeline& pipeline,
- const GrShaderCaps& shaderCaps) {
+ GrGpu* gpu) {
// The descriptor is used as a cache key. Thus when a field of the
// descriptor will not affect program generation (because of the attribute
// bindings in use or other descriptor field settings) it should be set
// to a canonical value to avoid duplicate programs with different keys.
+ const GrShaderCaps& shaderCaps = *gpu->caps()->shaderCaps();
+
GR_STATIC_ASSERT(0 == kProcessorKeysOffset % sizeof(uint32_t));
// Make room for everything up to the effect keys.
desc->key().reset();
@@ -196,7 +219,7 @@
for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i);
- if (!gen_frag_proc_and_meta_keys(primProc, fp, shaderCaps, &b)) {
+ if (!gen_frag_proc_and_meta_keys(primProc, fp, gpu, shaderCaps, &b)) {
desc->key().reset();
return false;
}