1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC 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/GrVkMSAALoadManager.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 11cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h" 12cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h" 14cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkBuffer.h" 15cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCommandBuffer.h" 16cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkDescriptorSet.h" 17cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkGpu.h" 18cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkImageView.h" 19cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkPipeline.h" 20cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkRenderTarget.h" 21cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkResourceProvider.h" 22cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkUtil.h" 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ciGrVkMSAALoadManager::GrVkMSAALoadManager() 25cb93a386Sopenharmony_ci : fVertShaderModule(VK_NULL_HANDLE) 26cb93a386Sopenharmony_ci , fFragShaderModule(VK_NULL_HANDLE) 27cb93a386Sopenharmony_ci , fPipelineLayout(VK_NULL_HANDLE) {} 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ciGrVkMSAALoadManager::~GrVkMSAALoadManager() {} 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_cibool GrVkMSAALoadManager::createMSAALoadProgram(GrVkGpu* gpu) { 32cb93a386Sopenharmony_ci TRACE_EVENT0("skia", TRACE_FUNC); 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci SkSL::String vertShaderText; 35cb93a386Sopenharmony_ci vertShaderText.append( 36cb93a386Sopenharmony_ci "layout(set = 0, binding = 0) uniform vertexUniformBuffer {" 37cb93a386Sopenharmony_ci "half4 uPosXform;" 38cb93a386Sopenharmony_ci "};" 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci "// MSAA Load Program VS\n" 41cb93a386Sopenharmony_ci "void main() {" 42cb93a386Sopenharmony_ci "float2 position = float2(sk_VertexID >> 1, sk_VertexID & 1);" 43cb93a386Sopenharmony_ci "sk_Position.xy = position * uPosXform.xy + uPosXform.zw;" 44cb93a386Sopenharmony_ci "sk_Position.zw = half2(0, 1);" 45cb93a386Sopenharmony_ci "}"); 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci SkSL::String fragShaderText; 48cb93a386Sopenharmony_ci fragShaderText.append( 49cb93a386Sopenharmony_ci "layout(input_attachment_index = 0, set = 2, binding = 0) uniform subpassInput uInput;" 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci "// MSAA Load Program FS\n" 52cb93a386Sopenharmony_ci "void main() {" 53cb93a386Sopenharmony_ci "sk_FragColor = subpassLoad(uInput);" 54cb93a386Sopenharmony_ci "}"); 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci SkSL::Program::Settings settings; 57cb93a386Sopenharmony_ci SkSL::String spirv; 58cb93a386Sopenharmony_ci SkSL::Program::Inputs inputs; 59cb93a386Sopenharmony_ci if (!GrCompileVkShaderModule(gpu, vertShaderText, VK_SHADER_STAGE_VERTEX_BIT, 60cb93a386Sopenharmony_ci &fVertShaderModule, &fShaderStageInfo[0], settings, &spirv, 61cb93a386Sopenharmony_ci &inputs)) { 62cb93a386Sopenharmony_ci this->destroyResources(gpu); 63cb93a386Sopenharmony_ci return false; 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ci SkASSERT(inputs == SkSL::Program::Inputs()); 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci if (!GrCompileVkShaderModule(gpu, fragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, 68cb93a386Sopenharmony_ci &fFragShaderModule, &fShaderStageInfo[1], settings, &spirv, 69cb93a386Sopenharmony_ci &inputs)) { 70cb93a386Sopenharmony_ci this->destroyResources(gpu); 71cb93a386Sopenharmony_ci return false; 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci SkASSERT(inputs == SkSL::Program::Inputs()); 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci VkDescriptorSetLayout dsLayout[GrVkUniformHandler::kDescSetCount]; 76cb93a386Sopenharmony_ci 77cb93a386Sopenharmony_ci GrVkResourceProvider& resourceProvider = gpu->resourceProvider(); 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci dsLayout[GrVkUniformHandler::kUniformBufferDescSet] = resourceProvider.getUniformDSLayout(); 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci // Even though we don't have a sampler we need to put a valid handle here (of zero samplers) 82cb93a386Sopenharmony_ci // since we set up our descriptor layout to be uniform, sampler, input. 83cb93a386Sopenharmony_ci // 84cb93a386Sopenharmony_ci // TODO: We should have a more general way for different pipelines to describe their descriptor 85cb93a386Sopenharmony_ci // layouts so that we don't have to use the compile time constants for the sets. 86cb93a386Sopenharmony_ci GrVkDescriptorSetManager::Handle samplerHandle; 87cb93a386Sopenharmony_ci resourceProvider.getZeroSamplerDescriptorSetHandle(&samplerHandle); 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ci dsLayout[GrVkUniformHandler::kSamplerDescSet] = 90cb93a386Sopenharmony_ci resourceProvider.getSamplerDSLayout(samplerHandle); 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_ci dsLayout[GrVkUniformHandler::kInputDescSet] = resourceProvider.getInputDSLayout(); 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci // Create the VkPipelineLayout 95cb93a386Sopenharmony_ci VkPipelineLayoutCreateInfo layoutCreateInfo; 96cb93a386Sopenharmony_ci memset(&layoutCreateInfo, 0, sizeof(VkPipelineLayoutCreateFlags)); 97cb93a386Sopenharmony_ci layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; 98cb93a386Sopenharmony_ci layoutCreateInfo.pNext = nullptr; 99cb93a386Sopenharmony_ci layoutCreateInfo.flags = 0; 100cb93a386Sopenharmony_ci layoutCreateInfo.setLayoutCount = GrVkUniformHandler::kDescSetCount; 101cb93a386Sopenharmony_ci layoutCreateInfo.pSetLayouts = dsLayout; 102cb93a386Sopenharmony_ci layoutCreateInfo.pushConstantRangeCount = 0; 103cb93a386Sopenharmony_ci layoutCreateInfo.pPushConstantRanges = nullptr; 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci VkResult err = GR_VK_CALL( 106cb93a386Sopenharmony_ci gpu->vkInterface(), 107cb93a386Sopenharmony_ci CreatePipelineLayout(gpu->device(), &layoutCreateInfo, nullptr, &fPipelineLayout)); 108cb93a386Sopenharmony_ci if (err) { 109cb93a386Sopenharmony_ci this->destroyResources(gpu); 110cb93a386Sopenharmony_ci return false; 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci return true; 114cb93a386Sopenharmony_ci} 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_cibool GrVkMSAALoadManager::loadMSAAFromResolve(GrVkGpu* gpu, 117cb93a386Sopenharmony_ci GrVkCommandBuffer* commandBuffer, 118cb93a386Sopenharmony_ci const GrVkRenderPass& renderPass, 119cb93a386Sopenharmony_ci GrAttachment* dst, 120cb93a386Sopenharmony_ci GrVkImage* src, 121cb93a386Sopenharmony_ci const SkIRect& rect) { 122cb93a386Sopenharmony_ci if (!dst) { 123cb93a386Sopenharmony_ci return false; 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci if (!src || !src->supportsInputAttachmentUsage()) { 126cb93a386Sopenharmony_ci return false; 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci if (VK_NULL_HANDLE == fVertShaderModule) { 130cb93a386Sopenharmony_ci SkASSERT(fFragShaderModule == VK_NULL_HANDLE && fPipelineLayout == VK_NULL_HANDLE); 131cb93a386Sopenharmony_ci if (!this->createMSAALoadProgram(gpu)) { 132cb93a386Sopenharmony_ci SkDebugf("Failed to create copy program.\n"); 133cb93a386Sopenharmony_ci return false; 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci } 136cb93a386Sopenharmony_ci SkASSERT(fPipelineLayout != VK_NULL_HANDLE); 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci GrVkResourceProvider& resourceProv = gpu->resourceProvider(); 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci sk_sp<const GrVkPipeline> pipeline = 141cb93a386Sopenharmony_ci resourceProv.findOrCreateMSAALoadPipeline(renderPass, dst->numSamples(), 142cb93a386Sopenharmony_ci fShaderStageInfo, fPipelineLayout); 143cb93a386Sopenharmony_ci if (!pipeline) { 144cb93a386Sopenharmony_ci return false; 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci commandBuffer->bindPipeline(gpu, std::move(pipeline)); 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_ci // Set Dynamic viewport and stencil 149cb93a386Sopenharmony_ci // We always use one viewport the size of the RT 150cb93a386Sopenharmony_ci VkViewport viewport; 151cb93a386Sopenharmony_ci viewport.x = 0.0f; 152cb93a386Sopenharmony_ci viewport.y = 0.0f; 153cb93a386Sopenharmony_ci viewport.width = SkIntToScalar(dst->width()); 154cb93a386Sopenharmony_ci viewport.height = SkIntToScalar(dst->height()); 155cb93a386Sopenharmony_ci viewport.minDepth = 0.0f; 156cb93a386Sopenharmony_ci viewport.maxDepth = 1.0f; 157cb93a386Sopenharmony_ci commandBuffer->setViewport(gpu, 0, 1, &viewport); 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_ci // We assume the scissor is not enabled so just set it to the whole RT 160cb93a386Sopenharmony_ci VkRect2D scissor; 161cb93a386Sopenharmony_ci scissor.extent.width = dst->width(); 162cb93a386Sopenharmony_ci scissor.extent.height = dst->height(); 163cb93a386Sopenharmony_ci scissor.offset.x = 0; 164cb93a386Sopenharmony_ci scissor.offset.y = 0; 165cb93a386Sopenharmony_ci commandBuffer->setScissor(gpu, 0, 1, &scissor); 166cb93a386Sopenharmony_ci 167cb93a386Sopenharmony_ci // Update and bind uniform descriptor set 168cb93a386Sopenharmony_ci int w = rect.width(); 169cb93a386Sopenharmony_ci int h = rect.height(); 170cb93a386Sopenharmony_ci 171cb93a386Sopenharmony_ci // dst rect edges in NDC (-1 to 1) 172cb93a386Sopenharmony_ci int dw = dst->width(); 173cb93a386Sopenharmony_ci int dh = dst->height(); 174cb93a386Sopenharmony_ci float dx0 = 2.f * rect.fLeft / dw - 1.f; 175cb93a386Sopenharmony_ci float dx1 = 2.f * (rect.fLeft + w) / dw - 1.f; 176cb93a386Sopenharmony_ci float dy0 = 2.f * rect.fTop / dh - 1.f; 177cb93a386Sopenharmony_ci float dy1 = 2.f * (rect.fTop + h) / dh - 1.f; 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci float uniData[] = {dx1 - dx0, dy1 - dy0, dx0, dy0}; // posXform 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ci GrResourceProvider* resourceProvider = gpu->getContext()->priv().resourceProvider(); 182cb93a386Sopenharmony_ci // TODO: Is it worth holding onto the last used uniform buffer and tracking the width, height, 183cb93a386Sopenharmony_ci // dst width, and dst height so that we can use the buffer again without having to update the 184cb93a386Sopenharmony_ci // data? 185cb93a386Sopenharmony_ci sk_sp<GrGpuBuffer> uniformBuffer = resourceProvider->createBuffer( 186cb93a386Sopenharmony_ci 4 * sizeof(float), GrGpuBufferType::kUniform, kDynamic_GrAccessPattern, uniData); 187cb93a386Sopenharmony_ci if (!uniformBuffer) { 188cb93a386Sopenharmony_ci return false; 189cb93a386Sopenharmony_ci } 190cb93a386Sopenharmony_ci GrVkBuffer* vkUniformBuffer = static_cast<GrVkBuffer*>(uniformBuffer.get()); 191cb93a386Sopenharmony_ci static_assert(GrVkUniformHandler::kUniformBufferDescSet < GrVkUniformHandler::kInputDescSet); 192cb93a386Sopenharmony_ci commandBuffer->bindDescriptorSets(gpu, fPipelineLayout, 193cb93a386Sopenharmony_ci GrVkUniformHandler::kUniformBufferDescSet, 194cb93a386Sopenharmony_ci /*setCount=*/1, vkUniformBuffer->uniformDescriptorSet(), 195cb93a386Sopenharmony_ci /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr); 196cb93a386Sopenharmony_ci commandBuffer->addGrBuffer(std::move(uniformBuffer)); 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_ci // Update the input descriptor set 199cb93a386Sopenharmony_ci gr_rp<const GrVkDescriptorSet> inputDS = src->inputDescSetForMSAALoad(gpu); 200cb93a386Sopenharmony_ci if (!inputDS) { 201cb93a386Sopenharmony_ci return false; 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci commandBuffer->bindDescriptorSets(gpu, fPipelineLayout, 204cb93a386Sopenharmony_ci GrVkUniformHandler::kInputDescSet, /*setCount=*/1, 205cb93a386Sopenharmony_ci inputDS->descriptorSet(), 206cb93a386Sopenharmony_ci /*dynamicOffsetCount=*/0, /*dynamicOffsets=*/nullptr); 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci // We don't need to add the src and dst resources here since those are all tracked by the main 209cb93a386Sopenharmony_ci // render pass code out in GrVkOpsRenderPass and GrVkRenderTarget::adResources. 210cb93a386Sopenharmony_ci commandBuffer->addRecycledResource(std::move(inputDS)); 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_ci commandBuffer->draw(gpu, 4, 1, 0, 0); 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ci return true; 215cb93a386Sopenharmony_ci} 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_civoid GrVkMSAALoadManager::destroyResources(GrVkGpu* gpu) { 218cb93a386Sopenharmony_ci if (fVertShaderModule != VK_NULL_HANDLE) { 219cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), 220cb93a386Sopenharmony_ci DestroyShaderModule(gpu->device(), fVertShaderModule, nullptr)); 221cb93a386Sopenharmony_ci fVertShaderModule = VK_NULL_HANDLE; 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_ci if (fFragShaderModule != VK_NULL_HANDLE) { 225cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), 226cb93a386Sopenharmony_ci DestroyShaderModule(gpu->device(), fFragShaderModule, nullptr)); 227cb93a386Sopenharmony_ci fFragShaderModule = VK_NULL_HANDLE; 228cb93a386Sopenharmony_ci } 229cb93a386Sopenharmony_ci 230cb93a386Sopenharmony_ci if (fPipelineLayout != VK_NULL_HANDLE) { 231cb93a386Sopenharmony_ci GR_VK_CALL(gpu->vkInterface(), 232cb93a386Sopenharmony_ci DestroyPipelineLayout(gpu->device(), fPipelineLayout, nullptr)); 233cb93a386Sopenharmony_ci fPipelineLayout = VK_NULL_HANDLE; 234cb93a386Sopenharmony_ci } 235cb93a386Sopenharmony_ci} 236cb93a386Sopenharmony_ci 237