1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkPipelineState.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/core/SkMipmap.h" 11cb93a386Sopenharmony_ci#include "src/gpu/GrFragmentProcessor.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrGeometryProcessor.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrPipeline.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrXferProcessor.h" 17cb93a386Sopenharmony_ci#include "src/gpu/effects/GrTextureEffect.h" 18cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkBuffer.h" 19cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCommandBuffer.h" 20cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkDescriptorPool.h" 21cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkDescriptorSet.h" 22cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkGpu.h" 23cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkImageView.h" 24cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkMemory.h" 25cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkPipeline.h" 26cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkRenderTarget.h" 27cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkSampler.h" 28cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkTexture.h" 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ciGrVkPipelineState::GrVkPipelineState( 31cb93a386Sopenharmony_ci GrVkGpu* gpu, 32cb93a386Sopenharmony_ci sk_sp<const GrVkPipeline> pipeline, 33cb93a386Sopenharmony_ci const GrVkDescriptorSetManager::Handle& samplerDSHandle, 34cb93a386Sopenharmony_ci const GrGLSLBuiltinUniformHandles& builtinUniformHandles, 35cb93a386Sopenharmony_ci const UniformInfoArray& uniforms, 36cb93a386Sopenharmony_ci uint32_t uniformSize, 37cb93a386Sopenharmony_ci bool usePushConstants, 38cb93a386Sopenharmony_ci const UniformInfoArray& samplers, 39cb93a386Sopenharmony_ci std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl, 40cb93a386Sopenharmony_ci std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl, 41cb93a386Sopenharmony_ci std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls) 42cb93a386Sopenharmony_ci : fPipeline(std::move(pipeline)) 43cb93a386Sopenharmony_ci , fSamplerDSHandle(samplerDSHandle) 44cb93a386Sopenharmony_ci , fBuiltinUniformHandles(builtinUniformHandles) 45cb93a386Sopenharmony_ci , fGPImpl(std::move(gpImpl)) 46cb93a386Sopenharmony_ci , fXPImpl(std::move(xpImpl)) 47cb93a386Sopenharmony_ci , fFPImpls(std::move(fpImpls)) 48cb93a386Sopenharmony_ci , fDataManager(uniforms, uniformSize, usePushConstants) { 49cb93a386Sopenharmony_ci fNumSamplers = samplers.count(); 50cb93a386Sopenharmony_ci for (const auto& sampler : samplers.items()) { 51cb93a386Sopenharmony_ci // We store the immutable samplers here and take a ref on the sampler. Once we switch to 52cb93a386Sopenharmony_ci // using sk_sps here we should just move the immutable samplers to save the extra ref/unref. 53cb93a386Sopenharmony_ci if (sampler.fImmutableSampler) { 54cb93a386Sopenharmony_ci sampler.fImmutableSampler->ref(); 55cb93a386Sopenharmony_ci } 56cb93a386Sopenharmony_ci fImmutableSamplers.push_back(sampler.fImmutableSampler); 57cb93a386Sopenharmony_ci } 58cb93a386Sopenharmony_ci} 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ciGrVkPipelineState::~GrVkPipelineState() { 61cb93a386Sopenharmony_ci // Must have freed all GPU resources before this is destroyed 62cb93a386Sopenharmony_ci SkASSERT(!fPipeline); 63cb93a386Sopenharmony_ci} 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_civoid GrVkPipelineState::freeGPUResources(GrVkGpu* gpu) { 66cb93a386Sopenharmony_ci fPipeline.reset(); 67cb93a386Sopenharmony_ci fDataManager.releaseData(); 68cb93a386Sopenharmony_ci for (int i = 0; i < fImmutableSamplers.count(); ++i) { 69cb93a386Sopenharmony_ci if (fImmutableSamplers[i]) { 70cb93a386Sopenharmony_ci fImmutableSamplers[i]->unref(); 71cb93a386Sopenharmony_ci fImmutableSamplers[i] = nullptr; 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_cibool GrVkPipelineState::setAndBindUniforms(GrVkGpu* gpu, 77cb93a386Sopenharmony_ci SkISize colorAttachmentDimensions, 78cb93a386Sopenharmony_ci const GrProgramInfo& programInfo, 79cb93a386Sopenharmony_ci GrVkCommandBuffer* commandBuffer) { 80cb93a386Sopenharmony_ci this->setRenderTargetState(colorAttachmentDimensions, programInfo.origin()); 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_ci fGPImpl->setData(fDataManager, *gpu->caps()->shaderCaps(), programInfo.geomProc()); 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) { 85cb93a386Sopenharmony_ci const auto& fp = programInfo.pipeline().getFragmentProcessor(i); 86cb93a386Sopenharmony_ci fp.visitWithImpls([&](const GrFragmentProcessor& fp, 87cb93a386Sopenharmony_ci GrFragmentProcessor::ProgramImpl& impl) { 88cb93a386Sopenharmony_ci impl.setData(fDataManager, fp); 89cb93a386Sopenharmony_ci }, *fFPImpls[i]); 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_ci programInfo.pipeline().setDstTextureUniforms(fDataManager, &fBuiltinUniformHandles); 93cb93a386Sopenharmony_ci fXPImpl->setData(fDataManager, programInfo.pipeline().getXferProcessor()); 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci // Upload uniform data and bind descriptor set. 96cb93a386Sopenharmony_ci auto [uniformBuffer, success] = fDataManager.uploadUniforms(gpu, fPipeline->layout(), 97cb93a386Sopenharmony_ci commandBuffer); 98cb93a386Sopenharmony_ci if (!success) { 99cb93a386Sopenharmony_ci return false; 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci if (uniformBuffer) { 102cb93a386Sopenharmony_ci const GrVkBuffer* vkBuffer = static_cast<GrVkBuffer*>(uniformBuffer.get()); 103cb93a386Sopenharmony_ci static const int kUniformDSIdx = GrVkUniformHandler::kUniformBufferDescSet; 104cb93a386Sopenharmony_ci commandBuffer->bindDescriptorSets(gpu, fPipeline->layout(), kUniformDSIdx, /*setCount=*/1, 105cb93a386Sopenharmony_ci vkBuffer->uniformDescriptorSet(), 106cb93a386Sopenharmony_ci /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr); 107cb93a386Sopenharmony_ci commandBuffer->addGrBuffer(std::move(uniformBuffer)); 108cb93a386Sopenharmony_ci } 109cb93a386Sopenharmony_ci return true; 110cb93a386Sopenharmony_ci} 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_cibool GrVkPipelineState::setAndBindTextures(GrVkGpu* gpu, 113cb93a386Sopenharmony_ci const GrGeometryProcessor& geomProc, 114cb93a386Sopenharmony_ci const GrPipeline& pipeline, 115cb93a386Sopenharmony_ci const GrSurfaceProxy* const geomProcTextures[], 116cb93a386Sopenharmony_ci GrVkCommandBuffer* commandBuffer) { 117cb93a386Sopenharmony_ci SkASSERT(geomProcTextures || !geomProc.numTextureSamplers()); 118cb93a386Sopenharmony_ci if (!fNumSamplers) { 119cb93a386Sopenharmony_ci return true; 120cb93a386Sopenharmony_ci } 121cb93a386Sopenharmony_ci struct SamplerBindings { 122cb93a386Sopenharmony_ci GrSamplerState fState; 123cb93a386Sopenharmony_ci GrVkTexture* fTexture; 124cb93a386Sopenharmony_ci }; 125cb93a386Sopenharmony_ci SkAutoSTArray<8, SamplerBindings> samplerBindings(fNumSamplers); 126cb93a386Sopenharmony_ci int currTextureBinding = 0; 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ci for (int i = 0; i < geomProc.numTextureSamplers(); ++i) { 129cb93a386Sopenharmony_ci SkASSERT(geomProcTextures[i]->asTextureProxy()); 130cb93a386Sopenharmony_ci const auto& sampler = geomProc.textureSampler(i); 131cb93a386Sopenharmony_ci auto texture = static_cast<GrVkTexture*>(geomProcTextures[i]->peekTexture()); 132cb93a386Sopenharmony_ci samplerBindings[currTextureBinding++] = {sampler.samplerState(), texture}; 133cb93a386Sopenharmony_ci } 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci if (GrTexture* dstTexture = pipeline.peekDstTexture()) { 137cb93a386Sopenharmony_ci samplerBindings[currTextureBinding++] = {GrSamplerState::Filter::kNearest, 138cb93a386Sopenharmony_ci static_cast<GrVkTexture*>(dstTexture)}; 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci pipeline.visitTextureEffects([&](const GrTextureEffect& te) { 142cb93a386Sopenharmony_ci GrSamplerState samplerState = te.samplerState(); 143cb93a386Sopenharmony_ci auto* texture = static_cast<GrVkTexture*>(te.texture()); 144cb93a386Sopenharmony_ci samplerBindings[currTextureBinding++] = {samplerState, texture}; 145cb93a386Sopenharmony_ci }); 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci // Get new descriptor set 148cb93a386Sopenharmony_ci SkASSERT(fNumSamplers == currTextureBinding); 149cb93a386Sopenharmony_ci static const int kSamplerDSIdx = GrVkUniformHandler::kSamplerDescSet; 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci if (fNumSamplers == 1) { 152cb93a386Sopenharmony_ci auto texture = samplerBindings[0].fTexture; 153cb93a386Sopenharmony_ci auto texAttachment = texture->textureImage(); 154cb93a386Sopenharmony_ci const auto& samplerState = samplerBindings[0].fState; 155cb93a386Sopenharmony_ci const GrVkDescriptorSet* descriptorSet = texture->cachedSingleDescSet(samplerState); 156cb93a386Sopenharmony_ci if (descriptorSet) { 157cb93a386Sopenharmony_ci commandBuffer->addGrSurface(sk_ref_sp<const GrSurface>(texture)); 158cb93a386Sopenharmony_ci commandBuffer->addResource(texAttachment->textureView()); 159cb93a386Sopenharmony_ci commandBuffer->addResource(texAttachment->resource()); 160cb93a386Sopenharmony_ci commandBuffer->addRecycledResource(descriptorSet); 161cb93a386Sopenharmony_ci commandBuffer->bindDescriptorSets(gpu, fPipeline->layout(), kSamplerDSIdx, 162cb93a386Sopenharmony_ci /*setCount=*/1, descriptorSet->descriptorSet(), 163cb93a386Sopenharmony_ci /*dynamicOffsetCount=*/0, 164cb93a386Sopenharmony_ci /*dynamicOffsets=*/nullptr); 165cb93a386Sopenharmony_ci return true; 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci } 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_ci const GrVkDescriptorSet* descriptorSet = 170cb93a386Sopenharmony_ci gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle); 171cb93a386Sopenharmony_ci if (!descriptorSet) { 172cb93a386Sopenharmony_ci return false; 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_ci for (int i = 0; i < fNumSamplers; ++i) { 176cb93a386Sopenharmony_ci GrSamplerState state = samplerBindings[i].fState; 177cb93a386Sopenharmony_ci GrVkTexture* texture = samplerBindings[i].fTexture; 178cb93a386Sopenharmony_ci auto texAttachment = texture->textureImage(); 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci const GrVkImageView* textureView = texAttachment->textureView(); 181cb93a386Sopenharmony_ci const GrVkSampler* sampler = nullptr; 182cb93a386Sopenharmony_ci if (fImmutableSamplers[i]) { 183cb93a386Sopenharmony_ci sampler = fImmutableSamplers[i]; 184cb93a386Sopenharmony_ci } else { 185cb93a386Sopenharmony_ci sampler = gpu->resourceProvider().findOrCreateCompatibleSampler( 186cb93a386Sopenharmony_ci state, texAttachment->ycbcrConversionInfo()); 187cb93a386Sopenharmony_ci if (!sampler) { 188cb93a386Sopenharmony_ci descriptorSet->recycle(); 189cb93a386Sopenharmony_ci return false; 190cb93a386Sopenharmony_ci } 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci SkASSERT(sampler); 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci VkDescriptorImageInfo imageInfo; 195cb93a386Sopenharmony_ci memset(&imageInfo, 0, sizeof(VkDescriptorImageInfo)); 196cb93a386Sopenharmony_ci imageInfo.sampler = fImmutableSamplers[i] ? VK_NULL_HANDLE : sampler->sampler(); 197cb93a386Sopenharmony_ci imageInfo.imageView = textureView->imageView(); 198cb93a386Sopenharmony_ci imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_ci VkWriteDescriptorSet writeInfo; 201cb93a386Sopenharmony_ci memset(&writeInfo, 0, sizeof(VkWriteDescriptorSet)); 202cb93a386Sopenharmony_ci writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 203cb93a386Sopenharmony_ci writeInfo.pNext = nullptr; 204cb93a386Sopenharmony_ci writeInfo.dstSet = *descriptorSet->descriptorSet(); 205cb93a386Sopenharmony_ci writeInfo.dstBinding = i; 206cb93a386Sopenharmony_ci writeInfo.dstArrayElement = 0; 207cb93a386Sopenharmony_ci writeInfo.descriptorCount = 1; 208cb93a386Sopenharmony_ci writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 209cb93a386Sopenharmony_ci writeInfo.pImageInfo = &imageInfo; 210cb93a386Sopenharmony_ci writeInfo.pBufferInfo = nullptr; 211cb93a386Sopenharmony_ci writeInfo.pTexelBufferView = nullptr; 212cb93a386Sopenharmony_ci 213cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), 214cb93a386Sopenharmony_ci UpdateDescriptorSets(gpu->device(), 1, &writeInfo, 0, nullptr)); 215cb93a386Sopenharmony_ci commandBuffer->addResource(sampler); 216cb93a386Sopenharmony_ci if (!fImmutableSamplers[i]) { 217cb93a386Sopenharmony_ci sampler->unref(); 218cb93a386Sopenharmony_ci } 219cb93a386Sopenharmony_ci commandBuffer->addResource(textureView); 220cb93a386Sopenharmony_ci commandBuffer->addResource(texAttachment->resource()); 221cb93a386Sopenharmony_ci } 222cb93a386Sopenharmony_ci if (fNumSamplers == 1) { 223cb93a386Sopenharmony_ci GrSamplerState state = samplerBindings[0].fState; 224cb93a386Sopenharmony_ci GrVkTexture* texture = samplerBindings[0].fTexture; 225cb93a386Sopenharmony_ci texture->addDescriptorSetToCache(descriptorSet, state); 226cb93a386Sopenharmony_ci } 227cb93a386Sopenharmony_ci 228cb93a386Sopenharmony_ci commandBuffer->bindDescriptorSets(gpu, fPipeline->layout(), kSamplerDSIdx, /*setCount=*/1, 229cb93a386Sopenharmony_ci descriptorSet->descriptorSet(), 230cb93a386Sopenharmony_ci /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr); 231cb93a386Sopenharmony_ci commandBuffer->addRecycledResource(descriptorSet); 232cb93a386Sopenharmony_ci descriptorSet->recycle(); 233cb93a386Sopenharmony_ci return true; 234cb93a386Sopenharmony_ci} 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_cibool GrVkPipelineState::setAndBindInputAttachment(GrVkGpu* gpu, 237cb93a386Sopenharmony_ci gr_rp<const GrVkDescriptorSet> inputDescSet, 238cb93a386Sopenharmony_ci GrVkCommandBuffer* commandBuffer) { 239cb93a386Sopenharmony_ci SkASSERT(inputDescSet); 240cb93a386Sopenharmony_ci commandBuffer->bindDescriptorSets(gpu, fPipeline->layout(), GrVkUniformHandler::kInputDescSet, 241cb93a386Sopenharmony_ci /*setCount=*/1, inputDescSet->descriptorSet(), 242cb93a386Sopenharmony_ci /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr); 243cb93a386Sopenharmony_ci // We don't add the input resource to the command buffer to track since the input will be 244cb93a386Sopenharmony_ci // the same as the color attachment which is already tracked on the command buffer. 245cb93a386Sopenharmony_ci commandBuffer->addRecycledResource(std::move(inputDescSet)); 246cb93a386Sopenharmony_ci return true; 247cb93a386Sopenharmony_ci} 248cb93a386Sopenharmony_ci 249cb93a386Sopenharmony_civoid GrVkPipelineState::setRenderTargetState(SkISize colorAttachmentDimensions, 250cb93a386Sopenharmony_ci GrSurfaceOrigin origin) { 251cb93a386Sopenharmony_ci // Set RT adjustment and RT flip 252cb93a386Sopenharmony_ci SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid()); 253cb93a386Sopenharmony_ci if (fRenderTargetState.fRenderTargetOrigin != origin || 254cb93a386Sopenharmony_ci fRenderTargetState.fRenderTargetSize != colorAttachmentDimensions) { 255cb93a386Sopenharmony_ci fRenderTargetState.fRenderTargetSize = colorAttachmentDimensions; 256cb93a386Sopenharmony_ci fRenderTargetState.fRenderTargetOrigin = origin; 257cb93a386Sopenharmony_ci 258cb93a386Sopenharmony_ci // The client will mark a swap buffer as kTopLeft when making a SkSurface because 259cb93a386Sopenharmony_ci // Vulkan's framebuffer space has (0, 0) at the top left. This agrees with Skia's device 260cb93a386Sopenharmony_ci // coords and with Vulkan's NDC that has (-1, -1) in the top left. So a flip is needed when 261cb93a386Sopenharmony_ci // surface origin is kBottomLeft rather than kTopLeft. 262cb93a386Sopenharmony_ci bool flip = (origin == kBottomLeft_GrSurfaceOrigin); 263cb93a386Sopenharmony_ci std::array<float, 4> v = SkSL::Compiler::GetRTAdjustVector(colorAttachmentDimensions, flip); 264cb93a386Sopenharmony_ci fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data()); 265cb93a386Sopenharmony_ci if (fBuiltinUniformHandles.fRTFlipUni.isValid()) { 266cb93a386Sopenharmony_ci std::array<float, 2> d = 267cb93a386Sopenharmony_ci SkSL::Compiler::GetRTFlipVector(colorAttachmentDimensions.height(), flip); 268cb93a386Sopenharmony_ci fDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data()); 269cb93a386Sopenharmony_ci } 270cb93a386Sopenharmony_ci } 271cb93a386Sopenharmony_ci} 272cb93a386Sopenharmony_ci 273cb93a386Sopenharmony_civoid GrVkPipelineState::bindPipeline(const GrVkGpu* gpu, GrVkCommandBuffer* commandBuffer) { 274cb93a386Sopenharmony_ci commandBuffer->bindPipeline(gpu, fPipeline); 275cb93a386Sopenharmony_ci} 276