bool GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) { // First we loop over all of the installed processors and collect coord transforms. These will // be sent to the GrGLPrimitiveProcessor in its emitCode function const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); int totalTextures = primProc.numTextures(); const int maxTextureUnits = fGpu->glCaps().maxFragmentTextureUnits(); for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) { const GrFragmentProcessor& processor = this->pipeline().getFragmentProcessor(i); if (!primProc.hasTransformedLocalCoords()) { SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back(); processor.gatherCoordTransforms(&procCoords); } totalTextures += processor.numTextures(); if (totalTextures >= maxTextureUnits) { GrCapsDebugf(fGpu->caps(), "Program would use too many texture units\n"); return false; } } this->emitAndInstallProc(primProc, inputColor, inputCoverage); fFragmentProcessors.reset(new GrGLInstalledFragProcs); int numProcs = this->pipeline().numFragmentProcessors(); this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors(), inputColor); this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs, inputCoverage); this->emitAndInstallXferProc(*this->pipeline().getXferProcessor(), *inputColor, *inputCoverage); return true; }
GrGLProgram* GrGLGpu::ProgramCache::refProgram(const GrGLGpu* gpu, const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc) { #ifdef PROGRAM_CACHE_STATS ++fTotalRequests; #endif // Get GrGLProgramDesc GrGLProgramDesc desc; if (!GrGLProgramDescBuilder::Build(&desc, primProc, pipeline, *gpu->glCaps().glslCaps())) { GrCapsDebugf(gpu->caps(), "Failed to gl program descriptor!\n"); return nullptr; } Entry* entry = nullptr; uint32_t hashIdx = desc.getChecksum(); hashIdx ^= hashIdx >> 16; if (kHashBits <= 8) { hashIdx ^= hashIdx >> 8; }
bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder, const GrPipelineOptimizations& optimizations, GrXferProcessor::DstTexture* dstTexture, const SkRect& batchBounds) { SkRect bounds = batchBounds; bounds.outset(0.5f, 0.5f); if (!pipelineBuilder.willXPNeedDstTexture(*this->caps(), optimizations)) { return true; } GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); if (this->caps()->textureBarrierSupport()) { if (GrTexture* rtTex = rt->asTexture()) { // The render target is a texture, so we can read from it directly in the shader. The XP // will be responsible to detect this situation and request a texture barrier. dstTexture->setTexture(rtTex); dstTexture->setOffset(0, 0); return true; } } SkIRect copyRect; pipelineBuilder.clip().getConservativeBounds(rt->width(), rt->height(), ©Rect); SkIRect drawIBounds; bounds.roundOut(&drawIBounds); if (!copyRect.intersect(drawIBounds)) { #ifdef SK_DEBUG GrCapsDebugf(this->caps(), "Missed an early reject. " "Bailing on draw from setupDstReadIfNecessary.\n"); #endif return false; } // MSAA consideration: When there is support for reading MSAA samples in the shader we could // have per-sample dst values by making the copy multisampled. GrSurfaceDesc desc; if (!fGpu->initCopySurfaceDstDesc(rt, &desc)) { desc.fOrigin = kDefault_GrSurfaceOrigin; desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fConfig = rt->config(); } desc.fWidth = copyRect.width(); desc.fHeight = copyRect.height(); static const uint32_t kFlags = 0; SkAutoTUnref<GrTexture> copy(fResourceProvider->createApproxTexture(desc, kFlags)); if (!copy) { SkDebugf("Failed to create temporary copy of destination texture.\n"); return false; } SkIPoint dstPoint = {0, 0}; this->copySurface(copy, rt, copyRect, dstPoint); dstTexture->setTexture(copy); dstTexture->setOffset(copyRect.fLeft, copyRect.fTop); return true; }
sk_sp<GrVkPipelineState> GrVkResourceProvider::PipelineStateCache::refPipelineState( const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, GrPrimitiveType primitiveType, const GrVkRenderPass& renderPass) { #ifdef GR_PIPELINE_STATE_CACHE_STATS ++fTotalRequests; #endif // Get GrVkProgramDesc GrVkPipelineState::Desc desc; if (!GrVkProgramDescBuilder::Build(&desc.fProgramDesc, primProc, pipeline, *fGpu->vkCaps().glslCaps())) { GrCapsDebugf(fGpu->caps(), "Failed to build vk program descriptor!\n"); return false; } // Get vulkan specific descriptor key GrVkPipelineState::BuildStateKey(pipeline, primitiveType, &desc.fStateKey); // Get checksum of entire PipelineDesc int keyLength = desc.fStateKey.count(); SkASSERT(0 == (keyLength % 4)); // Seed the checksum with the checksum of the programDesc then add the vulkan key to it. desc.fChecksum = SkChecksum::Murmur3(desc.fStateKey.begin(), keyLength, desc.fProgramDesc.getChecksum()); Entry* entry = nullptr; if (Entry** entryptr = fHashTable.find(desc)) { SkASSERT(*entryptr); entry = *entryptr; } if (!entry) { #ifdef GR_PIPELINE_STATE_CACHE_STATS ++fCacheMisses; #endif sk_sp<GrVkPipelineState> pipelineState( GrVkPipelineStateBuilder::CreatePipelineState(fGpu, pipeline, primProc, primitiveType, desc, renderPass)); if (nullptr == pipelineState) { return nullptr; } if (fCount < kMaxEntries) { entry = new Entry; fCount++; } else { SkASSERT(fCount == kMaxEntries); entry = fLRUList.head(); fLRUList.remove(entry); entry->fPipelineState->freeGPUResources(fGpu); fHashTable.remove(entry->fPipelineState->getDesc()); } entry->fPipelineState = std::move(pipelineState); fHashTable.set(entry); fLRUList.addToTail(entry); return entry->fPipelineState; } else { fLRUList.remove(entry); fLRUList.addToTail(entry); } return entry->fPipelineState; }