/** * A function which emits a meta key into the key builder. This is required because shader code may * be dependent on properties of the effect that the effect itself doesn't use * in its key (e.g. the pixel format of textures used). So we create a meta-key for * every effect using this function. It is also responsible for inserting the effect's class ID * which must be different for every GrProcessor subclass. It can fail if an effect uses too many * textures, transforms, etc, for the space allotted in the meta-key. NOTE, both FPs and GPs share * this function because it is hairy, though FPs do not have attribs, and GPs do not have transforms */ static bool get_meta_key(const GrProcessor& proc, const GrGLCaps& caps, uint32_t transformKey, uint32_t attribKey, GrProcessorKeyBuilder* b, uint16_t* processorKeySize) { const GrBackendProcessorFactory& factory = proc.getFactory(); factory.getGLProcessorKey(proc, caps, b); size_t size = b->size(); if (size > SK_MaxU16) { *processorKeySize = 0; // suppresses a warning. return false; } *processorKeySize = SkToU16(size); uint32_t textureKey = gen_texture_key(proc, caps); uint32_t classID = proc.getFactory().classID(); // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they // don't fit. static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16); if ((textureKey | transformKey | classID) & kMetaKeyInvalidMask) { return false; } uint32_t* key = b->add32n(2); key[0] = (textureKey << 16 | transformKey); key[1] = (classID << 16); return true; }
static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrProcessor& proc, const GrGLSLCaps& caps) { int numTextures = proc.numTextures(); int numSamplers = numTextures + proc.numBuffers(); // Need two bytes per key (swizzle, sampler type, and precision). int word32Count = (numSamplers + 1) / 2; if (0 == word32Count) { return; } uint16_t* k16 = SkTCast<uint16_t*>(b->add32n(word32Count)); int i = 0; for (; i < numTextures; ++i) { const GrTextureAccess& access = proc.textureAccess(i); const GrTexture* tex = access.getTexture(); k16[i] = sampler_key(tex->samplerType(), tex->config(), access.getVisibility(), caps); } for (; i < numSamplers; ++i) { const GrBufferAccess& access = proc.bufferAccess(i - numTextures); k16[i] = sampler_key(kSamplerBuffer_GrSLType, access.texelConfig(), access.visibility(), caps); } // zero the last 16 bits if the number of samplers is odd. if (numSamplers & 0x1) { k16[numSamplers] = 0; } }
static void prepare_sampled_images(const GrProcessor& processor, GrVkGpu* gpu) { for (int i = 0; i < processor.numTextures(); ++i) { const GrTextureAccess& texAccess = processor.textureAccess(i); GrVkTexture* vkTexture = static_cast<GrVkTexture*>(processor.texture(i)); SkASSERT(vkTexture); // We may need to resolve the texture first if it is also a render target GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(vkTexture->asRenderTarget()); if (texRT) { gpu->onResolveRenderTarget(texRT); } const GrTextureParams& params = texAccess.getParams(); // Check if we need to regenerate any mip maps if (GrTextureParams::kMipMap_FilterMode == params.filterMode()) { if (vkTexture->texturePriv().mipMapsAreDirty()) { gpu->generateMipmap(vkTexture); vkTexture->texturePriv().dirtyMipMaps(false); } } // TODO: If we ever decide to create the secondary command buffers ahead of time before we // are actually going to submit them, we will need to track the sampled images and delay // adding the layout change/barrier until we are ready to submit. vkTexture->setImageLayout(gpu, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, false); } }
void GrGLProgram::generateMipmaps(const GrProcessor& processor, bool allowSRGBInputs) { for (int i = 0; i < processor.numTextures(); ++i) { const GrTextureAccess& access = processor.textureAccess(i); fGpu->generateMipmaps(access.getParams(), allowSRGBInputs, static_cast<GrGLTexture*>(access.getTexture())); } }
static void append_texture_bindings(const GrProcessor& processor, SkTArray<const GrTextureAccess*>* textureBindings) { if (int numTextures = processor.numTextures()) { const GrTextureAccess** bindings = textureBindings->push_back_n(numTextures); int i = 0; do { bindings[i] = &processor.textureAccess(i); } while (++i < numTextures); } }
bool GrProcessor::hasSameTextureAccesses(const GrProcessor& that) const { if (this->numTextures() != that.numTextures()) { return false; } for (int i = 0; i < this->numTextures(); ++i) { if (this->textureAccess(i) != that.textureAccess(i)) { return false; } } return true; }
static uint32_t gen_texture_key(const GrProcessor& proc, const GrGLCaps& caps) { uint32_t key = 0; int numTextures = proc.numTextures(); for (int t = 0; t < numTextures; ++t) { const GrTextureAccess& access = proc.textureAccess(t); uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config()); if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) { key |= 1 << t; } } return key; }
void GrGLProgram::bindTextures(const GrGLInstalledProc* ip, const GrProcessor& processor) { const SkTArray<GrGLInstalledProc::Sampler, true>& samplers = ip->fSamplers; int numSamplers = samplers.count(); SkASSERT(numSamplers == processor.numTextures()); for (int s = 0; s < numSamplers; ++s) { SkASSERT(samplers[s].fTextureUnit >= 0); const GrTextureAccess& textureAccess = processor.textureAccess(s); fGpu->bindTexture(samplers[s].fTextureUnit, textureAccess.getParams(), static_cast<GrGLTexture*>(textureAccess.getTexture())); } }
void GrGLProgram::bindTextures(const GrProcessor& processor, bool allowSRGBInputs, int* nextSamplerIdx) { for (int i = 0; i < processor.numTextures(); ++i) { const GrTextureAccess& access = processor.textureAccess(i); fGpu->bindTexture((*nextSamplerIdx)++, access.getParams(), allowSRGBInputs, static_cast<GrGLTexture*>(access.getTexture())); } for (int i = 0; i < processor.numBuffers(); ++i) { const GrBufferAccess& access = processor.bufferAccess(i); fGpu->bindTexelBuffer((*nextSamplerIdx)++, access.offsetInBytes(), access.texelConfig(), static_cast<GrGLBuffer*>(access.buffer())); } }
void GrVkProgramBuilder::emitSamplers(const GrProcessor& processor, GrGLSLTextureSampler::TextureSamplerArray* outSamplers) { int numTextures = processor.numTextures(); UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures); SkString name; for (int t = 0; t < numTextures; ++t) { name.printf("%d", t); localSamplerUniforms[t] = fUniformHandler.addUniform(kFragment_GrShaderFlag, kSampler2D_GrSLType, kDefault_GrSLPrecision, name.c_str()); outSamplers->emplace_back(localSamplerUniforms[t], processor.textureAccess(t)); } }
void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, GrGLProcessor::TextureSamplerArray* outSamplers, GrGLInstalledProc<Proc>* ip) { int numTextures = processor.numTextures(); ip->fSamplers.push_back_n(numTextures); SkString name; for (int t = 0; t < numTextures; ++t) { name.printf("Sampler%d", t); ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility, kSampler2D_GrSLType, kDefault_GrSLPrecision, name.c_str()); SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler, (ip->fSamplers[t].fUniform, processor.textureAccess(t))); } }
static uint32_t gen_texture_key(const GrProcessor& proc, const GrGLCaps& caps) { uint32_t key = 0; int numTextures = proc.numTextures(); int shift = 0; for (int t = 0; t < numTextures; ++t) { const GrTextureAccess& access = proc.textureAccess(t); if (swizzle_requires_alpha_remapping(*caps.glslCaps(), access.getTexture()->config())) { key |= 1 << shift; } if (GR_GL_TEXTURE_EXTERNAL == static_cast<GrGLTexture*>(access.getTexture())->target()) { key |= 2 << shift; } shift += 2; } return key; }
void GrGLBicubicEffect::onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& processor) { const GrBicubicEffect& bicubicEffect = processor.cast<GrBicubicEffect>(); const GrTexture& texture = *processor.texture(0); float imageIncrement[2]; imageIncrement[0] = 1.0f / texture.width(); imageIncrement[1] = 1.0f / texture.height(); pdman.set2fv(fImageIncrementUni, 1, imageIncrement); pdman.setMatrix4f(fCoefficientsUni, bicubicEffect.coefficients()); fDomain.setData(pdman, bicubicEffect.domain(), texture.origin()); }
static void add_texture_key(GrProcessorKeyBuilder* b, const GrProcessor& proc, const GrGLSLCaps& caps) { int numTextures = proc.numTextures(); SkASSERT(0 == proc.numBuffers()); // Need two bytes per key (swizzle, sampler type, and precision). int word32Count = (proc.numTextures() + 1) / 2; if (0 == word32Count) { return; } uint16_t* k16 = SkTCast<uint16_t*>(b->add32n(word32Count)); 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() | (caps.samplerPrecision(texture->config(), access.getVisibility()) << 8)); } // zero the last 16 bits if the number of textures is odd. if (numTextures & 0x1) { k16[numTextures] = 0; } }
void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor, GrGLSLTextureSampler::TextureSamplerArray* outSamplers) { int numTextures = processor.numTextures(); UniformHandle* localSamplerUniforms = fSamplerUniforms.push_back_n(numTextures); SkString name; for (int t = 0; t < numTextures; ++t) { name.printf("Sampler%d", t); GrSLType samplerType = get_sampler_type(processor.textureAccess(t)); localSamplerUniforms[t] = fUniformHandler.addUniform(GrGLSLUniformHandler::kFragment_Visibility, samplerType, kDefault_GrSLPrecision, name.c_str()); SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLSLTextureSampler, (localSamplerUniforms[t], processor.textureAccess(t))); if (kSamplerExternal_GrSLType == samplerType) { const char* externalFeatureString = this->glslCaps()->externalTextureExtensionString(); // We shouldn't ever create a GrGLTexture that requires external sampler type SkASSERT(externalFeatureString); fFS.addFeature(1 << GrGLSLFragmentShaderBuilder::kExternalTexture_GLSLPrivateFeature, externalFeatureString); } } }
/** * A function which emits a meta key into the key builder. This is required because shader code may * be dependent on properties of the effect that the effect itself doesn't use * in its key (e.g. the pixel format of textures used). So we create a meta-key for * every effect using this function. It is also responsible for inserting the effect's class ID * which must be different for every GrProcessor subclass. It can fail if an effect uses too many * transforms, etc, for the space allotted in the meta-key. NOTE, both FPs and GPs share this * function because it is hairy, though FPs do not have attribs, and GPs do not have transforms */ static bool gen_meta_key(const GrProcessor& proc, const GrGLSLCaps& glslCaps, uint32_t transformKey, GrProcessorKeyBuilder* b) { size_t processorKeySize = b->size(); uint32_t classID = proc.classID(); // Currently we allow 16 bits for the class id and the overall processor key size. static const uint32_t kMetaKeyInvalidMask = ~((uint32_t)SK_MaxU16); if ((processorKeySize | classID) & kMetaKeyInvalidMask) { return false; } add_texture_key(b, proc, glslCaps); uint32_t* key = b->add32n(2); key[0] = (classID << 16) | SkToU32(processorKeySize); key[1] = transformKey; return true; }
/** * A function which emits a meta key into the key builder. This is required because shader code may * be dependent on properties of the effect that the effect itself doesn't use * in its key (e.g. the pixel format of textures used). So we create a meta-key for * every effect using this function. It is also responsible for inserting the effect's class ID * which must be different for every GrProcessor subclass. It can fail if an effect uses too many * textures, transforms, etc, for the space allotted in the meta-key. NOTE, both FPs and GPs share * this function because it is hairy, though FPs do not have attribs, and GPs do not have transforms */ static bool get_meta_key(const GrProcessor& proc, const GrGLCaps& caps, uint32_t transformKey, GrProcessorKeyBuilder* b) { size_t processorKeySize = b->size(); uint32_t textureKey = gen_texture_key(proc, caps); uint32_t classID = proc.classID(); // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they // don't fit. static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16); if ((textureKey | transformKey | classID) & kMetaKeyInvalidMask) { return false; } if (processorKeySize > SK_MaxU16) { return false; } uint32_t* key = b->add32n(2); key[0] = (textureKey << 16 | transformKey); key[1] = (classID << 16 | SkToU16(processorKeySize)); return true; }