1/* 2* Copyright 2015 Google Inc. 3* 4* Use of this source code is governed by a BSD-style license that can be 5* found in the LICENSE file. 6*/ 7 8#include "GrVkRenderPass.h" 9 10#include "GrProcessor.h" 11#include "GrVkFramebuffer.h" 12#include "GrVkGpu.h" 13#include "GrVkRenderTarget.h" 14#include "GrVkUtil.h" 15 16typedef GrVkRenderPass::AttachmentsDescriptor::AttachmentDesc AttachmentDesc; 17 18void setup_vk_attachment_description(VkAttachmentDescription* attachment, 19 const AttachmentDesc& desc, 20 VkImageLayout layout) { 21 attachment->flags = 0; 22 attachment->format = desc.fFormat; 23 SkAssertResult(GrSampleCountToVkSampleCount(desc.fSamples, &attachment->samples)); 24 switch (layout) { 25 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: 26 attachment->loadOp = desc.fLoadStoreOps.fLoadOp; 27 attachment->storeOp = desc.fLoadStoreOps.fStoreOp; 28 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 29 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 30 break; 31 case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: 32 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 33 attachment->storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 34 attachment->stencilLoadOp = desc.fLoadStoreOps.fLoadOp; 35 attachment->stencilStoreOp = desc.fLoadStoreOps.fStoreOp; 36 break; 37 default: 38 SkFAIL("Unexpected attachment layout"); 39 } 40 41 attachment->initialLayout = layout; 42 attachment->finalLayout = layout; 43} 44 45void GrVkRenderPass::initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& target) { 46 static const GrVkRenderPass::LoadStoreOps kBasicLoadStoreOps(VK_ATTACHMENT_LOAD_OP_LOAD, 47 VK_ATTACHMENT_STORE_OP_STORE); 48 49 this->init(gpu, target, kBasicLoadStoreOps, kBasicLoadStoreOps); 50} 51 52void GrVkRenderPass::init(const GrVkGpu* gpu, 53 const LoadStoreOps& colorOp, 54 const LoadStoreOps& stencilOp) { 55 uint32_t numAttachments = fAttachmentsDescriptor.fAttachmentCount; 56 // Attachment descriptions to be set on the render pass 57 SkTArray<VkAttachmentDescription> attachments(numAttachments); 58 attachments.reset(numAttachments); 59 memset(attachments.begin(), 0, numAttachments * sizeof(VkAttachmentDescription)); 60 61 // Refs to attachments on the render pass (as described by teh VkAttachmentDescription above), 62 // that are used by the subpass. 63 VkAttachmentReference colorRef; 64 VkAttachmentReference stencilRef; 65 uint32_t currentAttachment = 0; 66 67 // Go through each of the attachment types (color, stencil) and set the necessary 68 // on the various Vk structs. 69 VkSubpassDescription subpassDesc; 70 memset(&subpassDesc, 0, sizeof(VkSubpassDescription)); 71 subpassDesc.flags = 0; 72 subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 73 subpassDesc.inputAttachmentCount = 0; 74 subpassDesc.pInputAttachments = nullptr; 75 subpassDesc.pResolveAttachments = nullptr; 76 77 if (fAttachmentFlags & kColor_AttachmentFlag) { 78 // set up color attachment 79 fAttachmentsDescriptor.fColor.fLoadStoreOps = colorOp; 80 setup_vk_attachment_description(&attachments[currentAttachment], 81 fAttachmentsDescriptor.fColor, 82 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); 83 // setup subpass use of attachment 84 colorRef.attachment = currentAttachment++; 85 colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 86 subpassDesc.colorAttachmentCount = 1; 87 88 if (VK_ATTACHMENT_LOAD_OP_CLEAR == colorOp.fLoadOp) { 89 fClearValueCount++; 90 } 91 } else { 92 // I don't think there should ever be a time where we don't have a color attachment 93 SkASSERT(false); 94 colorRef.attachment = VK_ATTACHMENT_UNUSED; 95 colorRef.layout = VK_IMAGE_LAYOUT_UNDEFINED; 96 subpassDesc.colorAttachmentCount = 0; 97 } 98 subpassDesc.pColorAttachments = &colorRef; 99 100 if (fAttachmentFlags & kStencil_AttachmentFlag) { 101 // set up stencil attachment 102 fAttachmentsDescriptor.fStencil.fLoadStoreOps = stencilOp; 103 setup_vk_attachment_description(&attachments[currentAttachment], 104 fAttachmentsDescriptor.fStencil, 105 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); 106 // setup subpass use of attachment 107 stencilRef.attachment = currentAttachment++; 108 stencilRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 109 if (VK_ATTACHMENT_LOAD_OP_CLEAR == stencilOp.fLoadOp) { 110 fClearValueCount++; 111 } 112 } else { 113 stencilRef.attachment = VK_ATTACHMENT_UNUSED; 114 stencilRef.layout = VK_IMAGE_LAYOUT_UNDEFINED; 115 } 116 subpassDesc.pDepthStencilAttachment = &stencilRef; 117 118 subpassDesc.preserveAttachmentCount = 0; 119 subpassDesc.pPreserveAttachments = nullptr; 120 121 SkASSERT(numAttachments == currentAttachment); 122 123 // Create the VkRenderPass compatible with the attachment descriptions above 124 VkRenderPassCreateInfo createInfo; 125 memset(&createInfo, 0, sizeof(VkRenderPassCreateInfo)); 126 createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 127 createInfo.pNext = nullptr; 128 createInfo.flags = 0; 129 createInfo.attachmentCount = numAttachments; 130 createInfo.pAttachments = attachments.begin(); 131 createInfo.subpassCount = 1; 132 createInfo.pSubpasses = &subpassDesc; 133 createInfo.dependencyCount = 0; 134 createInfo.pDependencies = nullptr; 135 136 GR_VK_CALL_ERRCHECK(gpu->vkInterface(), CreateRenderPass(gpu->device(), 137 &createInfo, 138 nullptr, 139 &fRenderPass)); 140 141 // Get granularity for this render pass 142 GR_VK_CALL(gpu->vkInterface(), GetRenderAreaGranularity(gpu->device(), 143 fRenderPass, 144 &fGranularity)); 145} 146 147void GrVkRenderPass::init(const GrVkGpu* gpu, 148 const GrVkRenderPass& compatibleRenderPass, 149 const LoadStoreOps& colorOp, 150 const LoadStoreOps& stencilOp) { 151 fAttachmentFlags = compatibleRenderPass.fAttachmentFlags; 152 fAttachmentsDescriptor = compatibleRenderPass.fAttachmentsDescriptor; 153 this->init(gpu, colorOp, stencilOp); 154} 155 156void GrVkRenderPass::init(const GrVkGpu* gpu, 157 const GrVkRenderTarget& target, 158 const LoadStoreOps& colorOp, 159 const LoadStoreOps& stencilOp) { 160 // Get attachment information from render target. This includes which attachments the render 161 // target has (color, stencil) and the attachments format and sample count. 162 target.getAttachmentsDescriptor(&fAttachmentsDescriptor, &fAttachmentFlags); 163 this->init(gpu, colorOp, stencilOp); 164} 165 166void GrVkRenderPass::freeGPUData(const GrVkGpu* gpu) const { 167 GR_VK_CALL(gpu->vkInterface(), DestroyRenderPass(gpu->device(), fRenderPass, nullptr)); 168} 169 170// Works under the assumption that color attachment will always be the first attachment in our 171// attachment array if it exists. 172bool GrVkRenderPass::colorAttachmentIndex(uint32_t* index) const { 173 *index = 0; 174 if (fAttachmentFlags & kColor_AttachmentFlag) { 175 return true; 176 } 177 return false; 178} 179 180// Works under the assumption that stencil attachment will always be after the color and resolve 181// attachment. 182bool GrVkRenderPass::stencilAttachmentIndex(uint32_t* index) const { 183 *index = 0; 184 if (fAttachmentFlags & kColor_AttachmentFlag) { 185 ++(*index); 186 } 187 if (fAttachmentFlags & kStencil_AttachmentFlag) { 188 return true; 189 } 190 return false; 191} 192 193bool GrVkRenderPass::isCompatible(const AttachmentsDescriptor& desc, 194 const AttachmentFlags& flags) const { 195 if (flags != fAttachmentFlags) { 196 return false; 197 } 198 199 if (fAttachmentFlags & kColor_AttachmentFlag) { 200 if (!fAttachmentsDescriptor.fColor.isCompatible(desc.fColor)) { 201 return false; 202 } 203 } 204 if (fAttachmentFlags & kStencil_AttachmentFlag) { 205 if (!fAttachmentsDescriptor.fStencil.isCompatible(desc.fStencil)) { 206 return false; 207 } 208 } 209 210 return true; 211} 212 213bool GrVkRenderPass::isCompatible(const GrVkRenderTarget& target) const { 214 AttachmentsDescriptor desc; 215 AttachmentFlags flags; 216 target.getAttachmentsDescriptor(&desc, &flags); 217 218 return this->isCompatible(desc, flags); 219} 220 221bool GrVkRenderPass::isCompatible(const GrVkRenderPass& renderPass) const { 222 return this->isCompatible(renderPass.fAttachmentsDescriptor, renderPass.fAttachmentFlags); 223} 224 225bool GrVkRenderPass::equalLoadStoreOps(const LoadStoreOps& colorOps, 226 const LoadStoreOps& stencilOps) const { 227 if (fAttachmentFlags & kColor_AttachmentFlag) { 228 if (fAttachmentsDescriptor.fColor.fLoadStoreOps != colorOps) { 229 return false; 230 } 231 } 232 if (fAttachmentFlags & kStencil_AttachmentFlag) { 233 if (fAttachmentsDescriptor.fStencil.fLoadStoreOps != stencilOps) { 234 return false; 235 } 236 } 237 return true; 238} 239 240void GrVkRenderPass::genKey(GrProcessorKeyBuilder* b) const { 241 b->add32(fAttachmentFlags); 242 if (fAttachmentFlags & kColor_AttachmentFlag) { 243 b->add32(fAttachmentsDescriptor.fColor.fFormat); 244 b->add32(fAttachmentsDescriptor.fColor.fSamples); 245 } 246 if (fAttachmentFlags & kStencil_AttachmentFlag) { 247 b->add32(fAttachmentsDescriptor.fStencil.fFormat); 248 b->add32(fAttachmentsDescriptor.fStencil.fSamples); 249 } 250} 251