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 GrVkPipelineState::writeSamplers(GrVkGpu* gpu, const SkTArray<const GrTextureAccess*>& textureBindings, bool allowSRGBInputs) { SkASSERT(fNumSamplers == textureBindings.count()); for (int i = 0; i < textureBindings.count(); ++i) { const GrTextureParams& params = textureBindings[i]->getParams(); GrVkTexture* texture = static_cast<GrVkTexture*>(textureBindings[i]->getTexture()); if (GrTextureParams::kMipMap_FilterMode == params.filterMode()) { if (texture->texturePriv().mipMapsAreDirty()) { gpu->generateMipmap(texture); texture->texturePriv().dirtyMipMaps(false); } } fSamplers.push(gpu->resourceProvider().findOrCreateCompatibleSampler(params, texture->texturePriv().maxMipMapLevel())); const GrVkResource* textureResource = texture->resource(); textureResource->ref(); fTextures.push(textureResource); const GrVkImageView* textureView = texture->textureView(allowSRGBInputs); textureView->ref(); fTextureViews.push(textureView); // Change texture layout so it can be read in shader texture->setImageLayout(gpu, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, false); VkDescriptorImageInfo imageInfo; memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo)); imageInfo.sampler = fSamplers[i]->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)); } }
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; }