blob: 9c4787b865cb3bce8ef6e271e37bfd5d9931357d [file] [log] [blame]
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "GrVkRenderPass.h"
#include "GrVkFramebuffer.h"
#include "GrVkGpu.h"
#include "GrVkRenderTarget.h"
#include "GrVkUtil.h"
void setup_simple_vk_attachment_description(VkAttachmentDescription* attachment,
VkFormat format,
uint32_t samples,
VkImageLayout layout) {
attachment->flags = 0;
attachment->format = format;
SkAssertResult(GrSampleCountToVkSampleCount(samples, &attachment->samples));
attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment->initialLayout = layout;
attachment->finalLayout = layout;
}
void GrVkRenderPass::initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& target) {
// Get attachment information from render target. This includes which attachments the render
// target has (color, resolve, stencil) and the attachments format and sample count.
target.getAttachmentsDescriptor(&fAttachmentsDescriptor, &fAttachmentFlags);
uint32_t numAttachments = fAttachmentsDescriptor.fAttachmentCount;
// Attachment descriptions to be set on the render pass
SkTArray<VkAttachmentDescription> attachments(numAttachments);
attachments.reset(numAttachments);
memset(attachments.begin(), 0, numAttachments*sizeof(VkAttachmentDescription));
// Refs to attachments on the render pass (as described by teh VkAttachmentDescription above),
// that are used by the subpass.
VkAttachmentReference colorRef;
VkAttachmentReference resolveRef;
VkAttachmentReference stencilRef;
uint32_t currentAttachment = 0;
// Go through each of the attachment types (color, resolve, stencil) and set the necessary
// on the various Vk structs.
VkSubpassDescription subpassDesc;
memset(&subpassDesc, 0, sizeof(VkSubpassDescription));
subpassDesc.flags = 0;
subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpassDesc.inputAttachmentCount = 0;
subpassDesc.pInputAttachments = nullptr;
if (fAttachmentFlags & kColor_AttachmentFlag) {
// set up color attachment
setup_simple_vk_attachment_description(&attachments[currentAttachment],
fAttachmentsDescriptor.fColor.fFormat,
fAttachmentsDescriptor.fColor.fSamples,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// setup subpass use of attachment
colorRef.attachment = currentAttachment++;
colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
subpassDesc.colorAttachmentCount = 1;
} else {
// I don't think there should ever be a time where we don't have a color attachment
SkASSERT(false);
colorRef.attachment = VK_ATTACHMENT_UNUSED;
colorRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
subpassDesc.colorAttachmentCount = 0;
}
subpassDesc.pColorAttachments = &colorRef;
if (fAttachmentFlags & kResolve_AttachmentFlag) {
// set up resolve attachment
setup_simple_vk_attachment_description(&attachments[currentAttachment],
fAttachmentsDescriptor.fResolve.fFormat,
fAttachmentsDescriptor.fResolve.fSamples,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// setup subpass use of attachment
resolveRef.attachment = currentAttachment++;
// I'm really not sure what the layout should be for the resolve textures.
resolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
subpassDesc.pResolveAttachments = &resolveRef;
} else {
subpassDesc.pResolveAttachments = nullptr;
}
if (fAttachmentFlags & kStencil_AttachmentFlag) {
// set up stencil attachment
setup_simple_vk_attachment_description(&attachments[currentAttachment],
fAttachmentsDescriptor.fStencil.fFormat,
fAttachmentsDescriptor.fStencil.fSamples,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
// setup subpass use of attachment
stencilRef.attachment = currentAttachment++;
stencilRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
} else {
stencilRef.attachment = VK_ATTACHMENT_UNUSED;
stencilRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
}
subpassDesc.pDepthStencilAttachment = &stencilRef;
subpassDesc.preserveAttachmentCount = 0;
subpassDesc.pPreserveAttachments = nullptr;
SkASSERT(numAttachments == currentAttachment);
// Create the VkRenderPass compatible with the attachment descriptions above
VkRenderPassCreateInfo createInfo;
memset(&createInfo, 0, sizeof(VkRenderPassCreateInfo));
createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.attachmentCount = numAttachments;
createInfo.pAttachments = attachments.begin();
createInfo.subpassCount = 1;
createInfo.pSubpasses = &subpassDesc;
createInfo.dependencyCount = 0;
createInfo.pDependencies = nullptr;
GR_VK_CALL_ERRCHECK(gpu->vkInterface(), CreateRenderPass(gpu->device(),
&createInfo,
nullptr,
&fRenderPass));
}
void GrVkRenderPass::freeGPUData(const GrVkGpu* gpu) const {
GR_VK_CALL(gpu->vkInterface(), DestroyRenderPass(gpu->device(), fRenderPass, nullptr));
}
// Works under the assumption that color attachment will always be the first attachment in our
// attachment array if it exists.
bool GrVkRenderPass::colorAttachmentIndex(uint32_t* index) const {
*index = 0;
if (fAttachmentFlags & kColor_AttachmentFlag) {
return true;
}
return false;
}
// Works under the assumption that resolve attachment will always be after the color attachment.
bool GrVkRenderPass::resolveAttachmentIndex(uint32_t* index) const {
*index = 0;
if (fAttachmentFlags & kColor_AttachmentFlag) {
++(*index);
}
if (fAttachmentFlags & kResolve_AttachmentFlag) {
return true;
}
return false;
}
// Works under the assumption that stencil attachment will always be after the color and resolve
// attachment.
bool GrVkRenderPass::stencilAttachmentIndex(uint32_t* index) const {
*index = 0;
if (fAttachmentFlags & kColor_AttachmentFlag) {
++(*index);
}
if (fAttachmentFlags & kResolve_AttachmentFlag) {
++(*index);
}
if (fAttachmentFlags & kStencil_AttachmentFlag) {
return true;
}
return false;
}
void GrVkRenderPass::getBeginInfo(const GrVkRenderTarget& target,
VkRenderPassBeginInfo* beginInfo,
VkSubpassContents* contents) const {
SkASSERT(this->isCompatible(target));
VkRect2D renderArea;
renderArea.offset = { 0, 0 };
renderArea.extent = { (uint32_t)target.width(), (uint32_t)target.height() };
memset(beginInfo, 0, sizeof(VkRenderPassBeginInfo));
beginInfo->sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
beginInfo->pNext = nullptr;
beginInfo->renderPass = fRenderPass;
beginInfo->framebuffer = target.framebuffer()->framebuffer();
beginInfo->renderArea = renderArea;
beginInfo->clearValueCount = 0;
beginInfo->pClearValues = nullptr;
// Currently just assuming no secondary cmd buffers. This value will need to be update if we
// have them.
*contents = VK_SUBPASS_CONTENTS_INLINE;
}
bool GrVkRenderPass::isCompatible(const GrVkRenderTarget& target) const {
AttachmentsDescriptor desc;
AttachmentFlags flags;
target.getAttachmentsDescriptor(&desc, &flags);
if (flags != fAttachmentFlags) {
return false;
}
if (fAttachmentFlags & kColor_AttachmentFlag) {
if (fAttachmentsDescriptor.fColor != desc.fColor) {
return false;
}
}
if (fAttachmentFlags & kResolve_AttachmentFlag) {
if (fAttachmentsDescriptor.fResolve != desc.fResolve) {
return false;
}
}
if (fAttachmentFlags & kStencil_AttachmentFlag) {
if (fAttachmentsDescriptor.fStencil != desc.fStencil) {
return false;
}
}
return true;
}