void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp, const char* outColor, const char* outCoverage) { SkASSERT(!fGeometryProcessor); fGeometryProcessor = new GrGLInstalledGeoProc; fGeometryProcessor->fGLProc.reset(gp.createGLSLInstance(*fGpu->glCaps().glslCaps())); SkSTArray<4, GrGLSLTextureSampler> samplers(gp.numTextures()); this->emitSamplers(gp, &samplers, fGeometryProcessor); GrGLSLGeometryProcessor::EmitArgs args(this, &fVS, &fFS, &fVaryingHandler, this->glslCaps(), gp, outColor, outCoverage, samplers, fCoordTransforms, &fOutCoords); fGeometryProcessor->fGLProc->emitCode(args); // We have to check that effects and the code they emit are consistent, ie if an effect // asks for dst color, then the emit code needs to follow suit verify(gp); }
void GrGLPathProgram::onSetRenderTargetState(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { SkASSERT(!primProc.willUseGeoShader() && primProc.numAttribs() == 0); const GrRenderTarget* rt = pipeline.getRenderTarget(); SkISize size; size.set(rt->width(), rt->height()); const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>(); fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(), size, rt->origin()); }
virtual void setData(const GrGLProgramDataManager& pdman, const GrPrimitiveProcessor& processor, const GrBatchTracker& bt) override { SkASSERT(fDistanceAdjustUni.isValid()); const GrDistanceFieldLCDTextureEffect& dfTexEffect = processor.cast<GrDistanceFieldLCDTextureEffect>(); GrDistanceFieldLCDTextureEffect::DistanceAdjust wa = dfTexEffect.getDistanceAdjust(); if (wa != fDistanceAdjust) { pdman.set3f(fDistanceAdjustUni, wa.fR, wa.fG, wa.fB); fDistanceAdjust = wa; } this->setUniformViewMatrix(pdman, processor.viewMatrix()); const DistanceFieldLCDBatchTracker& local = bt.cast<DistanceFieldLCDBatchTracker>(); if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { GrGLfloat c[4]; GrColorToRGBAFloat(local.fColor, c); pdman.set4fv(fColorUniform, 1, c); fColor = local.fColor; } }
void GrGLNormalPathProcessor::setTransformData( const GrPrimitiveProcessor& primProc, int index, const SkTArray<const GrCoordTransform*, true>& coordTransforms, GrGLPathRendering* glpr, GrGLuint programID) { SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index]; int numTransforms = transforms.count(); for (int t = 0; t < numTransforms; ++t) { SkASSERT(transforms[t].fHandle.isValid()); const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *coordTransforms[t]); if (transforms[t].fCurrentValue.cheapEqualTo(transform)) { continue; } transforms[t].fCurrentValue = transform; const SeparableVaryingInfo& fragmentInput = fSeparableVaryingInfos[transforms[t].fHandle.handle()]; SkASSERT(transforms[t].fType == kVec2f_GrSLType || transforms[t].fType == kVec3f_GrSLType); unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3; glpr->setProgramPathFragmentInputTransform(programID, fragmentInput.fLocation, GR_GL_OBJECT_LINEAR, components, transform); } }
bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m, const GrPrimitiveProcessor& that, const GrBatchTracker& t) const { if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)) { return false; } const GrPathProcessor& other = that.cast<GrPathProcessor>(); if (!this->viewMatrix().cheapEqualTo(other.viewMatrix())) { return false; } const PathBatchTracker& mine = m.cast<PathBatchTracker>(); const PathBatchTracker& theirs = t.cast<PathBatchTracker>(); if (mine.fColor != theirs.fColor) { return false; } if (mine.fUsesLocalCoords != theirs.fUsesLocalCoords) { return false; } if (mine.fUsesLocalCoords && !this->localMatrix().cheapEqualTo(other.localMatrix())) { return false; } return true; }
void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { // Load the RT height uniform if it is needed to y-flip gl_FragCoord. if (fBuiltinUniformHandles.fRTHeightUni.isValid() && fRenderTargetState.fRenderTargetSize.fHeight != pipeline.getRenderTarget()->height()) { fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(pipeline.getRenderTarget()->height())); } // set RT adjustment const GrRenderTarget* rt = pipeline.getRenderTarget(); SkISize size; size.set(rt->width(), rt->height()); if (!primProc.isPathRendering()) { if (fRenderTargetState.fRenderTargetOrigin != rt->origin() || fRenderTargetState.fRenderTargetSize != size) { fRenderTargetState.fRenderTargetSize = size; fRenderTargetState.fRenderTargetOrigin = rt->origin(); float rtAdjustmentVec[4]; fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec); fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec); } } else { SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport()); const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>(); fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(), size, rt->origin()); } }
virtual void setData(const GrGLProgramDataManager& pdman, const GrPrimitiveProcessor& proc, const GrBatchTracker& bt) override { SkASSERT(fTextureSizeUni.isValid()); GrTexture* texture = proc.texture(0); if (texture->width() != fTextureSize.width() || texture->height() != fTextureSize.height()) { fTextureSize = SkISize::Make(texture->width(), texture->height()); pdman.set2f(fTextureSizeUni, SkIntToScalar(fTextureSize.width()), SkIntToScalar(fTextureSize.height())); } const GrDistanceFieldPathGeoProc& dfpgp = proc.cast<GrDistanceFieldPathGeoProc>(); if (!dfpgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfpgp.viewMatrix())) { fViewMatrix = dfpgp.viewMatrix(); GrGLfloat viewMatrix[3 * 3]; GrGLGetMatrix<3>(viewMatrix, fViewMatrix); pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); } if (dfpgp.color() != fColor) { GrGLfloat c[4]; GrColorToRGBAFloat(dfpgp.color(), c); pdman.set4fv(fColorUniform, 1, c); fColor = dfpgp.color(); } }
void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc, GrGLSLExpr4* outputColor, GrGLSLExpr4* outputCoverage) { // Program builders have a bit of state we need to clear with each effect AutoStageAdvance adv(this); this->nameExpression(outputColor, "outputColor"); this->nameExpression(outputCoverage, "outputCoverage"); // Enclose custom code in a block to avoid namespace conflicts SkString openBrace; openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); fFS.codeAppend(openBrace.c_str()); fVS.codeAppendf("// Primitive Processor %s\n", proc.name()); this->emitAndInstallProc(proc, outputColor->c_str(), outputCoverage->c_str()); fFS.codeAppend("}"); }
bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m, const GrPrimitiveProcessor& that, const GrBatchTracker& t) const { if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)) { return false; } if (!this->viewMatrix().cheapEqualTo(that.viewMatrix())) { return false; } const PathBatchTracker& mine = m.cast<PathBatchTracker>(); const PathBatchTracker& theirs = t.cast<PathBatchTracker>(); return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, that, theirs.fUsesLocalCoords) && CanCombineOutput(mine.fInputColorType, mine.fColor, theirs.fInputColorType, theirs.fColor) && CanCombineOutput(mine.fInputCoverageType, 0xff, theirs.fInputCoverageType, 0xff); }
bool GrGpuCommandBuffer::draw(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, const GrMesh* mesh, int meshCount) { if (primProc.numAttribs() > this->gpu()->caps()->maxVertexAttributes()) { this->gpu()->stats()->incNumFailedDraws(); return false; } this->onDraw(pipeline, primProc, mesh, meshCount); return true; }
static void setup_vertex_input_state(const GrPrimitiveProcessor& primProc, VkPipelineVertexInputStateCreateInfo* vertexInputInfo, VkVertexInputBindingDescription* bindingDesc, int maxBindingDescCount, VkVertexInputAttributeDescription* attributeDesc, int maxAttributeDescCount) { // for now we have only one vertex buffer and one binding memset(bindingDesc, 0, sizeof(VkVertexInputBindingDescription)); bindingDesc->binding = 0; bindingDesc->stride = (uint32_t)primProc.getVertexStride(); bindingDesc->inputRate = VK_VERTEX_INPUT_RATE_VERTEX; // setup attribute descriptions int vaCount = primProc.numAttribs(); SkASSERT(vaCount < maxAttributeDescCount); if (vaCount > 0) { size_t offset = 0; for (int attribIndex = 0; attribIndex < vaCount; attribIndex++) { const GrGeometryProcessor::Attribute& attrib = primProc.getAttrib(attribIndex); GrVertexAttribType attribType = attrib.fType; VkVertexInputAttributeDescription& vkAttrib = attributeDesc[attribIndex]; vkAttrib.location = attribIndex; // for now assume location = attribIndex vkAttrib.binding = 0; // for now only one vertex buffer & binding vkAttrib.format = attrib_type_to_vkformat(attribType); vkAttrib.offset = static_cast<uint32_t>(offset); offset += attrib.fOffset; } } memset(vertexInputInfo, 0, sizeof(VkPipelineVertexInputStateCreateInfo)); vertexInputInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertexInputInfo->pNext = nullptr; vertexInputInfo->flags = 0; vertexInputInfo->vertexBindingDescriptionCount = 1; vertexInputInfo->pVertexBindingDescriptions = bindingDesc; vertexInputInfo->vertexAttributeDescriptionCount = vaCount; vertexInputInfo->pVertexAttributeDescriptions = attributeDesc; }
virtual void setData(const GrGLProgramDataManager& pdman, const GrPrimitiveProcessor& gp, const GrBatchTracker& bt) override { this->setUniformViewMatrix(pdman, gp.viewMatrix()); const BitmapTextBatchTracker& local = bt.cast<BitmapTextBatchTracker>(); if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { GrGLfloat c[4]; GrColorToRGBAFloat(local.fColor, c); pdman.set4fv(fColorUniform, 1, c); fColor = local.fColor; } }
void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& proc, GrGLSLExpr4* outputColor, GrGLSLExpr4* outputCoverage) { // Program builders have a bit of state we need to clear with each effect AutoStageAdvance adv(this); this->nameExpression(outputColor, "outputColor"); this->nameExpression(outputCoverage, "outputCoverage"); // Enclose custom code in a block to avoid namespace conflicts SkString openBrace; openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name()); fFS.codeAppend(openBrace.c_str()); fVS.codeAppendf("// Primitive Processor %s\n", proc.name()); SkASSERT(!fGeometryProcessor); fGeometryProcessor = proc.createGLSLInstance(*this->glslCaps()); SkSTArray<4, SamplerHandle> texSamplers(proc.numTextures()); SkSTArray<2, SamplerHandle> bufferSamplers(proc.numBuffers()); this->emitSamplers(proc, &texSamplers, &bufferSamplers); GrGLSLGeometryProcessor::EmitArgs args(&fVS, &fFS, this->varyingHandler(), this->uniformHandler(), this->glslCaps(), proc, outputColor->c_str(), outputCoverage->c_str(), texSamplers.begin(), bufferSamplers.begin(), fCoordTransforms, &fOutCoords); fGeometryProcessor->emitCode(args); // We have to check that effects and the code they emit are consistent, ie if an effect // asks for dst color, then the emit code needs to follow suit SkDEBUGCODE(verify(proc);)
void GrGLProgram::generateMipmaps(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { this->generateMipmaps(primProc, pipeline.getAllowSRGBInputs()); GrFragmentProcessor::Iter iter(pipeline); while (const GrFragmentProcessor* fp = iter.next()) { this->generateMipmaps(*fp, pipeline.getAllowSRGBInputs()); } if (primProc.getPixelLocalStorageState() != GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) { const GrXferProcessor& xp = pipeline.getXferProcessor(); this->generateMipmaps(xp, pipeline.getAllowSRGBInputs()); } }
virtual void setData(const GrGLProgramDataManager& pdman, const GrPrimitiveProcessor& proc, const GrBatchTracker& bt) override { SkASSERT(fTextureSizeUni.isValid()); GrTexture* texture = proc.texture(0); if (texture->width() != fTextureSize.width() || texture->height() != fTextureSize.height()) { fTextureSize = SkISize::Make(texture->width(), texture->height()); pdman.set2f(fTextureSizeUni, SkIntToScalar(fTextureSize.width()), SkIntToScalar(fTextureSize.height())); } this->setUniformViewMatrix(pdman, proc.viewMatrix()); const DistanceFieldNoGammaBatchTracker& local = bt.cast<DistanceFieldNoGammaBatchTracker>(); if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { GrGLfloat c[4]; GrColorToRGBAFloat(local.fColor, c); pdman.set4fv(fColorUniform, 1, c); fColor = local.fColor; } }
static bool gen_frag_proc_and_meta_keys(const GrPrimitiveProcessor& primProc, const GrFragmentProcessor& fp, const GrGLSLCaps& glslCaps, GrProcessorKeyBuilder* b) { for (int i = 0; i < fp.numChildProcessors(); ++i) { if (!gen_frag_proc_and_meta_keys(primProc, fp.childProcessor(i), glslCaps, b)) { return false; } } fp.getGLSLProcessorKey(glslCaps, b); return gen_meta_key(fp, glslCaps, primProc.getTransformKey(fp.coordTransforms(), fp.numTransformsExclChildren()), b); }
void GrGLGeometryProcessor::setTransformData(const GrPrimitiveProcessor& primProc, const GrGLProgramDataManager& pdman, int index, const SkTArray<const GrCoordTransform*, true>& transforms) { SkSTArray<2, Transform, true>& procTransforms = fInstalledTransforms[index]; int numTransforms = transforms.count(); for (int t = 0; t < numTransforms; ++t) { SkASSERT(procTransforms[t].fHandle.isValid()); const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]); if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) { pdman.setSkMatrix(procTransforms[t].fHandle.convertToUniformHandle(), transform); procTransforms[t].fCurrentValue = transform; } } }
void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { this->setRenderTargetState(primProc, pipeline); // we set the textures, and uniforms for installed processors in a generic way, but subclasses // of GLProgram determine how to set coord transforms int nextSamplerIdx = 0; fGeometryProcessor->setData(fProgramDataManager, primProc); this->bindTextures(primProc, pipeline.getAllowSRGBInputs(), &nextSamplerIdx); this->setFragmentData(primProc, pipeline, &nextSamplerIdx); if (primProc.getPixelLocalStorageState() != GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) { const GrXferProcessor& xp = pipeline.getXferProcessor(); fXferProcessor->setData(fProgramDataManager, xp); this->bindTextures(xp, pipeline.getAllowSRGBInputs(), &nextSamplerIdx); } }
void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, SkTArray<const GrTextureAccess*>* textureBindings) { this->setRenderTargetState(primProc, pipeline); // we set the textures, and uniforms for installed processors in a generic way, but subclasses // of GLProgram determine how to set coord transforms fGeometryProcessor->setData(fProgramDataManager, primProc); append_texture_bindings(primProc, textureBindings); this->setFragmentData(primProc, pipeline, textureBindings); if (primProc.getPixelLocalStorageState() != GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) { const GrXferProcessor& xp = pipeline.getXferProcessor(); fXferProcessor->setData(fProgramDataManager, xp); append_texture_bindings(xp, textureBindings); } }
void GrGLLegacyPathProcessor::setTransformData( const GrPrimitiveProcessor& primProc, int index, const SkTArray<const GrCoordTransform*, true>& transforms, GrGLPathRendering* glpr, GrGLuint) { // We've hidden the texcoord index in the first entry of the transforms array for each // effect int texCoordIndex = fInstalledTransforms[index][0].fHandle.handle(); for (int t = 0; t < transforms.count(); ++t) { const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]); GrGLPathRendering::PathTexGenComponents components = GrGLPathRendering::kST_PathTexGenComponents; if (transform.hasPerspective()) { components = GrGLPathRendering::kSTR_PathTexGenComponents; } glpr->enablePathTexGen(texCoordIndex++, components, transform); } }
void setup_multisample_state(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, const GrCaps* caps, VkPipelineMultisampleStateCreateInfo* multisampleInfo) { memset(multisampleInfo, 0, sizeof(VkPipelineMultisampleStateCreateInfo)); multisampleInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampleInfo->pNext = nullptr; multisampleInfo->flags = 0; int numSamples = pipeline.getRenderTarget()->numColorSamples(); SkAssertResult(GrSampleCountToVkSampleCount(numSamples, &multisampleInfo->rasterizationSamples)); float sampleShading = primProc.getSampleShading(); SkASSERT(sampleShading == 0.0f || caps->sampleShadingSupport()); multisampleInfo->sampleShadingEnable = sampleShading > 0.0f; multisampleInfo->minSampleShading = sampleShading; multisampleInfo->pSampleMask = nullptr; multisampleInfo->alphaToCoverageEnable = VK_FALSE; multisampleInfo->alphaToOneEnable = VK_FALSE; }
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc, FPCoordTransformIter&& transformIter) override { SkASSERT(fTextureSizeUni.isValid()); GrTexture* texture = proc.texture(0); if (texture->width() != fTextureSize.width() || texture->height() != fTextureSize.height()) { fTextureSize = SkISize::Make(texture->width(), texture->height()); pdman.set2f(fTextureSizeUni, SkIntToScalar(fTextureSize.width()), SkIntToScalar(fTextureSize.height())); } const GrDistanceFieldPathGeoProc& dfpgp = proc.cast<GrDistanceFieldPathGeoProc>(); if (!dfpgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dfpgp.viewMatrix())) { fViewMatrix = dfpgp.viewMatrix(); float viewMatrix[3 * 3]; GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix); pdman.setMatrix3f(fViewMatrixUniform, viewMatrix); } this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter); }
virtual void setData(const GrGLProgramDataManager& pdman, const GrPrimitiveProcessor& proc, const GrBatchTracker& bt) override { #ifdef SK_GAMMA_APPLY_TO_A8 const GrDistanceFieldTextureEffect& dfTexEffect = proc.cast<GrDistanceFieldTextureEffect>(); float distanceAdjust = dfTexEffect.getDistanceAdjust(); if (distanceAdjust != fDistanceAdjust) { pdman.set1f(fDistanceAdjustUni, distanceAdjust); fDistanceAdjust = distanceAdjust; } #endif this->setUniformViewMatrix(pdman, proc.viewMatrix()); const DistanceFieldBatchTracker& local = bt.cast<DistanceFieldBatchTracker>(); if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) { GrGLfloat c[4]; GrColorToRGBAFloat(local.fColor, c); pdman.set4fv(fColorUniform, 1, c); fColor = local.fColor; } }
bool GrVkProgramDescBuilder::Build(GrProgramDesc* desc, const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, const GrGLSLCaps& glslCaps) { // 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. GrVkProgramDesc* vkDesc = (GrVkProgramDesc*)desc; GR_STATIC_ASSERT(0 == kProcessorKeysOffset % sizeof(uint32_t)); // Make room for everything up to the effect keys. vkDesc->key().reset(); vkDesc->key().push_back_n(kProcessorKeysOffset); GrProcessorKeyBuilder b(&vkDesc->key()); primProc.getGLSLProcessorKey(glslCaps, &b); if (!gen_meta_key(primProc, glslCaps, 0, &b)) { vkDesc->key().reset(); return false; } GrProcessor::RequiredFeatures requiredFeatures = primProc.requiredFeatures(); for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) { const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i); if (!gen_frag_proc_and_meta_keys(primProc, fp, glslCaps, &b)) { vkDesc->key().reset(); return false; } requiredFeatures |= fp.requiredFeatures(); } const GrXferProcessor& xp = pipeline.getXferProcessor(); xp.getGLSLProcessorKey(glslCaps, &b); if (!gen_meta_key(xp, glslCaps, 0, &b)) { vkDesc->key().reset(); return false; } requiredFeatures |= xp.requiredFeatures(); // --------DO NOT MOVE HEADER ABOVE THIS LINE-------------------------------------------------- // Because header is a pointer into the dynamic array, we can't push any new data into the key // below here. KeyHeader* header = vkDesc->atOffset<KeyHeader, kHeaderOffset>(); // make sure any padding in the header is zeroed. memset(header, 0, kHeaderSize); GrRenderTarget* rt = pipeline.getRenderTarget(); if (requiredFeatures & (GrProcessor::kFragmentPosition_RequiredFeature | GrProcessor::kSampleLocations_RequiredFeature)) { header->fSurfaceOriginKey = GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(rt->origin()); } else { header->fSurfaceOriginKey = 0; } if (requiredFeatures & GrProcessor::kSampleLocations_RequiredFeature) { SkASSERT(pipeline.isHWAntialiasState()); header->fSamplePatternKey = rt->renderTargetPriv().getMultisampleSpecs(pipeline.getStencil()).fUniqueID; } else { header->fSamplePatternKey = 0; } header->fOutputSwizzle = glslCaps.configOutputSwizzle(rt->config()).asKey(); if (pipeline.ignoresCoverage()) { header->fIgnoresCoverage = 1; } else { header->fIgnoresCoverage = 0; } header->fSnapVerticesToPixelCenters = pipeline.snapVerticesToPixelCenters(); header->fColorEffectCnt = pipeline.numColorFragmentProcessors(); header->fCoverageEffectCnt = pipeline.numCoverageFragmentProcessors(); vkDesc->finalize(); return true; }
void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) { SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition()); }
void GrVkPipelineState::setAndBindTextures(GrVkGpu* gpu, const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, const GrTextureProxy* const primProcTextures[], GrVkCommandBuffer* commandBuffer) { SkASSERT(primProcTextures || !primProc.numTextureSamplers()); struct SamplerBindings { GrSamplerState fState; GrVkTexture* fTexture; }; SkAutoSTMalloc<8, SamplerBindings> samplerBindings(fNumSamplers); int currTextureBinding = 0; fGeometryProcessor->setData(fDataManager, primProc, GrFragmentProcessor::CoordTransformIter(pipeline)); for (int i = 0; i < primProc.numTextureSamplers(); ++i) { const auto& sampler = primProc.textureSampler(i); auto texture = static_cast<GrVkTexture*>(primProcTextures[i]->peekTexture()); samplerBindings[currTextureBinding++] = {sampler.samplerState(), texture}; } GrFragmentProcessor::Iter iter(pipeline); GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt); const GrFragmentProcessor* fp = iter.next(); GrGLSLFragmentProcessor* glslFP = glslIter.next(); while (fp && glslFP) { for (int i = 0; i < fp->numTextureSamplers(); ++i) { const auto& sampler = fp->textureSampler(i); samplerBindings[currTextureBinding++] = {sampler.samplerState(), static_cast<GrVkTexture*>(sampler.peekTexture())}; } fp = iter.next(); glslFP = glslIter.next(); } SkASSERT(!fp && !glslFP); if (GrTextureProxy* dstTextureProxy = pipeline.dstTextureProxy()) { samplerBindings[currTextureBinding++] = { GrSamplerState::ClampNearest(), static_cast<GrVkTexture*>(dstTextureProxy->peekTexture())}; } // Get new descriptor set SkASSERT(fNumSamplers == currTextureBinding); if (fNumSamplers) { if (fSamplerDescriptorSet) { fSamplerDescriptorSet->recycle(gpu); } fSamplerDescriptorSet = gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle); int samplerDSIdx = GrVkUniformHandler::kSamplerDescSet; fDescriptorSets[samplerDSIdx] = fSamplerDescriptorSet->descriptorSet(); for (int i = 0; i < fNumSamplers; ++i) { const GrSamplerState& state = samplerBindings[i].fState; GrVkTexture* texture = samplerBindings[i].fTexture; const GrVkImageView* textureView = texture->textureView(); const GrVkSampler* sampler = nullptr; if (fImmutableSamplers[i]) { sampler = fImmutableSamplers[i]; } else { sampler = gpu->resourceProvider().findOrCreateCompatibleSampler( state, texture->ycbcrConversionInfo()); } SkASSERT(sampler); VkDescriptorImageInfo imageInfo; memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo)); imageInfo.sampler = sampler->sampler(); imageInfo.imageView = textureView->imageView(); imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; VkWriteDescriptorSet writeInfo; memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet)); writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeInfo.pNext = nullptr; writeInfo.dstSet = fDescriptorSets[GrVkUniformHandler::kSamplerDescSet]; writeInfo.dstBinding = i; writeInfo.dstArrayElement = 0; writeInfo.descriptorCount = 1; writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; writeInfo.pImageInfo = &imageInfo; writeInfo.pBufferInfo = nullptr; writeInfo.pTexelBufferView = nullptr; GR_VK_CALL(gpu->vkInterface(), UpdateDescriptorSets(gpu->device(), 1, &writeInfo, 0, nullptr)); commandBuffer->addResource(sampler); if (!fImmutableSamplers[i]) { sampler->unref(gpu); } commandBuffer->addResource(samplerBindings[i].fTexture->textureView()); commandBuffer->addResource(samplerBindings[i].fTexture->resource()); } commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, samplerDSIdx, 1, &fDescriptorSets[samplerDSIdx], 0, nullptr); commandBuffer->addRecycledResource(fSamplerDescriptorSet); } }
void GrVkGpuRTCommandBuffer::onDraw(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, const GrPipeline::FixedDynamicState* fixedDynamicState, const GrPipeline::DynamicStateArrays* dynamicStateArrays, const GrMesh meshes[], int meshCount, const SkRect& bounds) { if (!meshCount) { return; } CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo]; auto prepareSampledImage = [&](GrTexture* texture, GrSamplerState::Filter filter) { GrVkTexture* vkTexture = static_cast<GrVkTexture*>(texture); // We may need to resolve the texture first if it is also a render target GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(vkTexture->asRenderTarget()); if (texRT) { fGpu->resolveRenderTargetNoFlush(texRT); } // Check if we need to regenerate any mip maps if (GrSamplerState::Filter::kMipMap == filter && (vkTexture->width() != 1 || vkTexture->height() != 1)) { SkASSERT(vkTexture->texturePriv().mipMapped() == GrMipMapped::kYes); if (vkTexture->texturePriv().mipMapsAreDirty()) { fGpu->regenerateMipMapLevels(vkTexture); } } cbInfo.fSampledTextures.push_back(vkTexture); }; if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) { for (int m = 0, i = 0; m < meshCount; ++m) { for (int s = 0; s < primProc.numTextureSamplers(); ++s, ++i) { auto texture = dynamicStateArrays->fPrimitiveProcessorTextures[i]->peekTexture(); prepareSampledImage(texture, primProc.textureSampler(s).samplerState().filter()); } } } else { for (int i = 0; i < primProc.numTextureSamplers(); ++i) { auto texture = fixedDynamicState->fPrimitiveProcessorTextures[i]->peekTexture(); prepareSampledImage(texture, primProc.textureSampler(i).samplerState().filter()); } } GrFragmentProcessor::Iter iter(pipeline); while (const GrFragmentProcessor* fp = iter.next()) { for (int i = 0; i < fp->numTextureSamplers(); ++i) { const GrFragmentProcessor::TextureSampler& sampler = fp->textureSampler(i); prepareSampledImage(sampler.peekTexture(), sampler.samplerState().filter()); } } if (GrTexture* dstTexture = pipeline.peekDstTexture()) { cbInfo.fSampledTextures.push_back(sk_ref_sp(static_cast<GrVkTexture*>(dstTexture))); } GrPrimitiveType primitiveType = meshes[0].primitiveType(); GrVkPipelineState* pipelineState = this->prepareDrawState(primProc, pipeline, fixedDynamicState, dynamicStateArrays, primitiveType); if (!pipelineState) { return; } bool dynamicScissor = pipeline.isScissorEnabled() && dynamicStateArrays && dynamicStateArrays->fScissorRects; bool dynamicTextures = dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures; for (int i = 0; i < meshCount; ++i) { const GrMesh& mesh = meshes[i]; if (mesh.primitiveType() != primitiveType) { SkDEBUGCODE(pipelineState = nullptr); primitiveType = mesh.primitiveType(); pipelineState = this->prepareDrawState(primProc, pipeline, fixedDynamicState, dynamicStateArrays, primitiveType); if (!pipelineState) { return; } } if (dynamicScissor) { GrVkPipeline::SetDynamicScissorRectState(fGpu, cbInfo.currentCmdBuf(), fRenderTarget, fOrigin, dynamicStateArrays->fScissorRects[i]); } if (dynamicTextures) { GrTextureProxy* const* meshProxies = dynamicStateArrays->fPrimitiveProcessorTextures + primProc.numTextureSamplers() * i; pipelineState->setAndBindTextures(fGpu, primProc, pipeline, meshProxies, cbInfo.currentCmdBuf()); } SkASSERT(pipelineState); mesh.sendToGpu(this); } cbInfo.fBounds.join(bounds); cbInfo.fIsEmpty = false; }
bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc, const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, const GrGLGpu* gpu, const GrBatchTracker& batchTracker) { // 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. GrGLProgramDesc* glDesc = (GrGLProgramDesc*) desc; GR_STATIC_ASSERT(0 == kProcessorKeysOffset % sizeof(uint32_t)); // Make room for everything up to the effect keys. glDesc->key().reset(); glDesc->key().push_back_n(kProcessorKeysOffset); GrProcessorKeyBuilder b(&glDesc->key()); primProc.getGLProcessorKey(batchTracker, gpu->glCaps(), &b); if (!get_meta_key(primProc, gpu->glCaps(), 0, &b)) { glDesc->key().reset(); return false; } for (int s = 0; s < pipeline.numFragmentStages(); ++s) { const GrPendingFragmentStage& fps = pipeline.getFragmentStage(s); const GrFragmentProcessor& fp = *fps.processor(); fp.getGLProcessorKey(gpu->glCaps(), &b); if (!get_meta_key(fp, gpu->glCaps(), primProc.getTransformKey(fp.coordTransforms()), &b)) { glDesc->key().reset(); return false; } } const GrXferProcessor& xp = *pipeline.getXferProcessor(); xp.getGLProcessorKey(gpu->glCaps(), &b); if (!get_meta_key(xp, gpu->glCaps(), 0, &b)) { glDesc->key().reset(); return false; } // --------DO NOT MOVE HEADER ABOVE THIS LINE-------------------------------------------------- // Because header is a pointer into the dynamic array, we can't push any new data into the key // below here. KeyHeader* header = glDesc->atOffset<KeyHeader, kHeaderOffset>(); // make sure any padding in the header is zeroed. memset(header, 0, kHeaderSize); if (pipeline.readsFragPosition()) { header->fFragPosKey = GrGLFragmentShaderBuilder::KeyForFragmentPosition(pipeline.getRenderTarget(), gpu->glCaps()); } else { header->fFragPosKey = 0; } header->fColorEffectCnt = pipeline.numColorFragmentStages(); header->fCoverageEffectCnt = pipeline.numCoverageFragmentStages(); glDesc->finalize(); return true; }