void GrVkProgram::setData(const GrVkGpu* gpu, const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { // This is here to protect against someone calling setData multiple times in a row without // freeing the tempData between calls. this->freeTempResources(gpu); this->setRenderTargetState(pipeline); SkSTArray<8, const GrTextureAccess*> textureBindings; fGeometryProcessor->setData(fProgramDataManager, primProc); append_texture_bindings(primProc, &textureBindings); for (int i = 0; i < fFragmentProcessors.count(); ++i) { const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i); fFragmentProcessors[i]->setData(fProgramDataManager, processor); fGeometryProcessor->setTransformData(primProc, fProgramDataManager, i, processor.coordTransforms()); append_texture_bindings(processor, &textureBindings); } fXferProcessor->setData(fProgramDataManager, pipeline.getXferProcessor()); append_texture_bindings(pipeline.getXferProcessor(), &textureBindings); this->writeUniformBuffers(gpu); this->writeSamplers(gpu, textureBindings); }
bool GrPipeline::AreEqual(const GrPipeline& a, const GrPipeline& b, bool ignoreCoordTransforms) { SkASSERT(&a != &b); if (a.getRenderTarget() != b.getRenderTarget() || a.fFragmentProcessors.count() != b.fFragmentProcessors.count() || a.fNumColorProcessors != b.fNumColorProcessors || a.fScissorState != b.fScissorState || a.fFlags != b.fFlags || a.fStencilSettings != b.fStencilSettings || a.fDrawFace != b.fDrawFace) { return false; } // Most of the time both are nullptr if (a.fXferProcessor.get() || b.fXferProcessor.get()) { if (!a.getXferProcessor().isEqual(b.getXferProcessor())) { return false; } } for (int i = 0; i < a.numFragmentProcessors(); i++) { if (!a.getFragmentProcessor(i).isEqual(b.getFragmentProcessor(i), ignoreCoordTransforms)) { return false; } } return true; }
void GrVkPipelineState::setData(GrVkGpu* gpu, const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { // This is here to protect against someone calling setData multiple times in a row without // freeing the tempData between calls. this->freeTempResources(gpu); this->setRenderTargetState(pipeline); SkSTArray<8, const GrTextureAccess*> textureBindings; fGeometryProcessor->setData(fDataManager, primProc); append_texture_bindings(primProc, &textureBindings); for (int i = 0; i < fFragmentProcessors.count(); ++i) { const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i); fFragmentProcessors[i]->setData(fDataManager, processor); fGeometryProcessor->setTransformData(primProc, fDataManager, i, processor.coordTransforms()); append_texture_bindings(processor, &textureBindings); } fXferProcessor->setData(fDataManager, pipeline.getXferProcessor()); append_texture_bindings(pipeline.getXferProcessor(), &textureBindings); // Get new descriptor sets if (fNumSamplers) { fSamplerPoolManager.getNewDescriptorSet(gpu, &fDescriptorSets[GrVkUniformHandler::kSamplerDescSet]); this->writeSamplers(gpu, textureBindings, pipeline.getAllowSRGBInputs()); } if (fVertexUniformBuffer.get() || fFragmentUniformBuffer.get()) { if (fDataManager.uploadUniformBuffers(gpu, fVertexUniformBuffer, fFragmentUniformBuffer) || VK_NULL_HANDLE == fDescriptorSets[GrVkUniformHandler::kUniformBufferDescSet]) { const GrVkDescriptorPool* pool; int uniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet; gpu->resourceProvider().getUniformDescriptorSet(&fDescriptorSets[uniformDSIdx], &pool); if (pool != fCurrentUniformDescPool) { if (fCurrentUniformDescPool) { fCurrentUniformDescPool->unref(gpu); } fCurrentUniformDescPool = pool; fCurrentUniformDescPool->ref(); } this->writeUniformBuffers(gpu); } } }
void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { this->setRenderTargetState(primProc, pipeline.proxy()); // we set the textures, and uniforms for installed processors in a generic way, but subclasses // of GLProgram determine how to set coord transforms // We must bind to texture units in the same order in which we set the uniforms in // GrGLProgramDataManager. That is first all texture samplers and then texel buffers. // Within each group we will bind them in primProc, fragProcs, XP order. int nextTexSamplerIdx = 0; int nextTexelBufferIdx = fNumTextureSamplers; fGeometryProcessor->setData(fProgramDataManager, primProc, GrFragmentProcessor::CoordTransformIter(pipeline)); this->bindTextures(primProc, pipeline.getAllowSRGBInputs(), &nextTexSamplerIdx, &nextTexelBufferIdx); this->setFragmentData(primProc, pipeline, &nextTexSamplerIdx, &nextTexelBufferIdx); const GrXferProcessor& xp = pipeline.getXferProcessor(); SkIPoint offset; GrTexture* dstTexture = pipeline.peekDstTexture(&offset); fXferProcessor->setData(fProgramDataManager, xp, dstTexture, offset); if (dstTexture) { fGpu->bindTexture(nextTexSamplerIdx++, GrSamplerState::ClampNearest(), true, static_cast<GrGLTexture*>(dstTexture), pipeline.dstTextureProxy()->origin()); } SkASSERT(nextTexSamplerIdx == fNumTextureSamplers); SkASSERT(nextTexelBufferIdx == fNumTextureSamplers + fNumTexelBuffers); }
bool GrPipeline::isEqual(const GrPipeline& that) const { if (this->getRenderTarget() != that.getRenderTarget() || this->fFragmentStages.count() != that.fFragmentStages.count() || this->fNumColorStages != that.fNumColorStages || this->fScissorState != that.fScissorState || this->fFlags != that.fFlags || this->fStencilSettings != that.fStencilSettings || this->fDrawFace != that.fDrawFace) { return false; } if (!this->getXferProcessor()->isEqual(*that.getXferProcessor())) { return false; } // The program desc comparison should have already assured that the stage counts match. SkASSERT(this->numFragmentStages() == that.numFragmentStages()); for (int i = 0; i < this->numFragmentStages(); i++) { if (this->getFragmentStage(i) != that.getFragmentStage(i)) { return false; } } return true; }
void GrVkPipelineState::setAndBindUniforms(GrVkGpu* gpu, const GrRenderTarget* renderTarget, GrSurfaceOrigin origin, const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, GrVkCommandBuffer* commandBuffer) { this->setRenderTargetState(renderTarget, origin); fGeometryProcessor->setData(fDataManager, primProc, GrFragmentProcessor::CoordTransformIter(pipeline)); GrFragmentProcessor::Iter iter(pipeline); GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt); const GrFragmentProcessor* fp = iter.next(); GrGLSLFragmentProcessor* glslFP = glslIter.next(); while (fp && glslFP) { glslFP->setData(fDataManager, *fp); fp = iter.next(); glslFP = glslIter.next(); } SkASSERT(!fp && !glslFP); { SkIPoint offset; GrTexture* dstTexture = pipeline.peekDstTexture(&offset); fXferProcessor->setData(fDataManager, pipeline.getXferProcessor(), dstTexture, offset); } // Get new descriptor set if (fGeometryUniformBuffer || fFragmentUniformBuffer) { int uniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet; if (fDataManager.uploadUniformBuffers( gpu, fGeometryUniformBuffer.get(), fFragmentUniformBuffer.get()) || !fUniformDescriptorSet) { if (fUniformDescriptorSet) { fUniformDescriptorSet->recycle(gpu); } fUniformDescriptorSet = gpu->resourceProvider().getUniformDescriptorSet(); fDescriptorSets[uniformDSIdx] = fUniformDescriptorSet->descriptorSet(); this->writeUniformBuffers(gpu); } commandBuffer->bindDescriptorSets(gpu, this, fPipelineLayout, uniformDSIdx, 1, &fDescriptorSets[uniformDSIdx], 0, nullptr); if (fUniformDescriptorSet) { commandBuffer->addRecycledResource(fUniformDescriptorSet); } if (fGeometryUniformBuffer) { commandBuffer->addRecycledResource(fGeometryUniformBuffer->resource()); } if (fFragmentUniformBuffer) { commandBuffer->addRecycledResource(fFragmentUniformBuffer->resource()); } } }
void set_dynamic_blend_constant_state(GrVkGpu* gpu, GrVkCommandBuffer* cmdBuffer, const GrPipeline& pipeline) { GrXferProcessor::BlendInfo blendInfo; pipeline.getXferProcessor().getBlendInfo(&blendInfo); GrBlendCoeff srcCoeff = blendInfo.fSrcBlend; GrBlendCoeff dstCoeff = blendInfo.fDstBlend; float floatColors[4]; if (blend_coeff_refs_constant(srcCoeff) || blend_coeff_refs_constant(dstCoeff)) { GrColorToRGBAFloat(blendInfo.fBlendConstant, floatColors); } else { memset(floatColors, 0, 4 * sizeof(float)); } cmdBuffer->setBlendConstants(gpu, floatColors); }
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()); } }
uint32_t get_blend_info_key(const GrPipeline& pipeline) { GrXferProcessor::BlendInfo blendInfo; pipeline.getXferProcessor().getBlendInfo(&blendInfo); static const uint32_t kBlendWriteShift = 1; static const uint32_t kBlendCoeffShift = 5; GR_STATIC_ASSERT(kLast_GrBlendCoeff < (1 << kBlendCoeffShift)); GR_STATIC_ASSERT(kFirstAdvancedGrBlendEquation - 1 < 4); uint32_t key = blendInfo.fWriteColor; key |= (blendInfo.fSrcBlend << kBlendWriteShift); key |= (blendInfo.fDstBlend << (kBlendWriteShift + kBlendCoeffShift)); key |= (blendInfo.fEquation << (kBlendWriteShift + 2 * kBlendCoeffShift)); return key; }
void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, const GrBatchTracker& batchTracker) { 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->fGLProc->setData(fProgramDataManager, primProc, batchTracker); this->bindTextures(fGeometryProcessor.get(), primProc); const GrXferProcessor& xp = *pipeline.getXferProcessor(); fXferProcessor->fGLProc->setData(fProgramDataManager, xp); this->bindTextures(fXferProcessor.get(), xp); this->setFragmentData(primProc, pipeline); // Some of GrGLProgram subclasses need to update state here this->didSetData(); }
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 GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { this->setRenderTargetState(primProc, pipeline.getRenderTarget()); // 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, GrFragmentProcessor::CoordTransformIter(pipeline)); this->bindTextures(primProc, pipeline.getAllowSRGBInputs(), &nextSamplerIdx); this->setFragmentData(primProc, pipeline, &nextSamplerIdx); const GrXferProcessor& xp = pipeline.getXferProcessor(); SkIPoint offset; GrTexture* dstTexture = pipeline.dstTexture(&offset); fXferProcessor->setData(fProgramDataManager, xp, dstTexture, offset); if (dstTexture) { fGpu->bindTexture(nextSamplerIdx++, GrSamplerParams::ClampNoFilter(), true, static_cast<GrGLTexture*>(dstTexture)); } }
void setup_color_blend_state(const GrVkGpu* gpu, const GrPipeline& pipeline, VkPipelineColorBlendStateCreateInfo* colorBlendInfo, VkPipelineColorBlendAttachmentState* attachmentState) { GrXferProcessor::BlendInfo blendInfo; pipeline.getXferProcessor().getBlendInfo(&blendInfo); GrBlendEquation equation = blendInfo.fEquation; GrBlendCoeff srcCoeff = blendInfo.fSrcBlend; GrBlendCoeff dstCoeff = blendInfo.fDstBlend; bool blendOff = (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) && kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff; memset(attachmentState, 0, sizeof(VkPipelineColorBlendAttachmentState)); attachmentState->blendEnable = !blendOff; if (!blendOff) { attachmentState->srcColorBlendFactor = blend_coeff_to_vk_blend(srcCoeff); attachmentState->dstColorBlendFactor = blend_coeff_to_vk_blend(dstCoeff); attachmentState->colorBlendOp = blend_equation_to_vk_blend_op(equation); attachmentState->srcAlphaBlendFactor = blend_coeff_to_vk_blend(srcCoeff); attachmentState->dstAlphaBlendFactor = blend_coeff_to_vk_blend(dstCoeff); attachmentState->alphaBlendOp = blend_equation_to_vk_blend_op(equation); } if (!blendInfo.fWriteColor) { attachmentState->colorWriteMask = 0; } else { attachmentState->colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; } memset(colorBlendInfo, 0, sizeof(VkPipelineColorBlendStateCreateInfo)); colorBlendInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; colorBlendInfo->pNext = nullptr; colorBlendInfo->flags = 0; colorBlendInfo->logicOpEnable = VK_FALSE; colorBlendInfo->attachmentCount = 1; colorBlendInfo->pAttachments = attachmentState; // colorBlendInfo->blendConstants is set dynamically }
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; }
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 GrVkGpuCommandBuffer::onDraw(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc, const GrMesh* meshes, int meshCount) { if (!meshCount) { return; } GrRenderTarget* rt = pipeline.getRenderTarget(); GrVkRenderTarget* vkRT = static_cast<GrVkRenderTarget*>(rt); const GrVkRenderPass* renderPass = vkRT->simpleRenderPass(); SkASSERT(renderPass); prepare_sampled_images(primProc, fGpu); GrFragmentProcessor::Iter iter(pipeline); while (const GrFragmentProcessor* fp = iter.next()) { prepare_sampled_images(*fp, fGpu); } prepare_sampled_images(pipeline.getXferProcessor(), fGpu); GrPrimitiveType primitiveType = meshes[0].primitiveType(); sk_sp<GrVkPipelineState> pipelineState = this->prepareDrawState(pipeline, primProc, primitiveType, *renderPass); if (!pipelineState) { return; } for (int i = 0; i < meshCount; ++i) { const GrMesh& mesh = meshes[i]; GrMesh::Iterator iter; const GrNonInstancedMesh* nonIdxMesh = iter.init(mesh); do { if (nonIdxMesh->primitiveType() != primitiveType) { // Technically we don't have to call this here (since there is a safety check in // pipelineState:setData but this will allow for quicker freeing of resources if the // pipelineState sits in a cache for a while. pipelineState->freeTempResources(fGpu); SkDEBUGCODE(pipelineState = nullptr); primitiveType = nonIdxMesh->primitiveType(); pipelineState = this->prepareDrawState(pipeline, primProc, primitiveType, *renderPass); if (!pipelineState) { return; } } SkASSERT(pipelineState); this->bindGeometry(primProc, *nonIdxMesh); if (nonIdxMesh->isIndexed()) { fCommandBuffer->drawIndexed(fGpu, nonIdxMesh->indexCount(), 1, nonIdxMesh->startIndex(), nonIdxMesh->startVertex(), 0); } else { fCommandBuffer->draw(fGpu, nonIdxMesh->vertexCount(), 1, nonIdxMesh->startVertex(), 0); } fIsEmpty = false; fGpu->stats()->incNumDraws(); } while ((nonIdxMesh = iter.next())); } // Technically we don't have to call this here (since there is a safety check in // pipelineState:setData but this will allow for quicker freeing of resources if the // pipelineState sits in a cache for a while. pipelineState->freeTempResources(fGpu); }