Index: src/gpu/vk/GrVkRenderTarget.cpp |
diff --git a/src/gpu/vk/GrVkRenderTarget.cpp b/src/gpu/vk/GrVkRenderTarget.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..87f1f77e392fb3832cc30556349e8e1fa8e8dd1c |
--- /dev/null |
+++ b/src/gpu/vk/GrVkRenderTarget.cpp |
@@ -0,0 +1,391 @@ |
+/* |
+ * 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 "GrVkRenderTarget.h" |
+ |
+#include "GrRenderTargetPriv.h" |
+#include "GrVkCommandBuffer.h" |
+#include "GrVkFramebuffer.h" |
+#include "GrVkGpu.h" |
+#include "GrVkImageView.h" |
+#include "GrVkResourceProvider.h" |
+#include "GrVkUtil.h" |
+ |
+#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X) |
+ |
+// We're virtually derived from GrSurface (via GrRenderTarget) so its |
+// constructor must be explicitly called. |
+GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, |
+ const GrSurfaceDesc& desc, |
+ GrGpuResource::LifeCycle lifeCycle, |
+ const GrVkImage::Resource* imageResource, |
+ const GrVkImage::Resource* msaaResource, |
+ const GrVkImageView* colorAttachmentView, |
+ const GrVkImageView* resolveAttachmentView) |
+ : GrSurface(gpu, lifeCycle, desc) |
+ , GrVkImage(imageResource) |
+ // for the moment we only support 1:1 color to stencil |
+ , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig) |
+ , fFramebuffer(nullptr) |
+ , fColorAttachmentView(colorAttachmentView) |
+ , fMSAAImageResource(msaaResource) |
+ , fResolveAttachmentView(resolveAttachmentView) |
+ , fCachedSimpleRenderPass(nullptr) { |
+ SkASSERT(desc.fSampleCnt); |
+ // The plus 1 is to account for the resolve texture. |
+ fColorValuesPerPixel = desc.fSampleCnt + 1; // TODO: this still correct? |
+ this->createFramebuffer(gpu); |
+ this->registerWithCache(); |
+ msaaResource->ref(); |
+} |
+ |
+// We're virtually derived from GrSurface (via GrRenderTarget) so its |
+// constructor must be explicitly called. |
+GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, |
+ const GrSurfaceDesc& desc, |
+ GrGpuResource::LifeCycle lifeCycle, |
+ const GrVkImage::Resource* imageResource, |
+ const GrVkImage::Resource* msaaResource, |
+ const GrVkImageView* colorAttachmentView, |
+ const GrVkImageView* resolveAttachmentView, |
+ Derived) |
+ : GrSurface(gpu, lifeCycle, desc) |
+ , GrVkImage(imageResource) |
+ // for the moment we only support 1:1 color to stencil |
+ , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig) |
+ , fFramebuffer(nullptr) |
+ , fColorAttachmentView(colorAttachmentView) |
+ , fMSAAImageResource(msaaResource) |
+ , fResolveAttachmentView(resolveAttachmentView) |
+ , fCachedSimpleRenderPass(nullptr) { |
+ SkASSERT(desc.fSampleCnt); |
+ // The plus 1 is to account for the resolve texture. |
+ fColorValuesPerPixel = desc.fSampleCnt + 1; // TODO: this still correct? |
+ this->createFramebuffer(gpu); |
+ msaaResource->ref(); |
+} |
+ |
+// We're virtually derived from GrSurface (via GrRenderTarget) so its |
+// constructor must be explicitly called. |
+GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, |
+ const GrSurfaceDesc& desc, |
+ GrGpuResource::LifeCycle lifeCycle, |
+ const GrVkImage::Resource* imageResource, |
+ const GrVkImageView* colorAttachmentView) |
+ : GrSurface(gpu, lifeCycle, desc) |
+ , GrVkImage(imageResource) |
+ , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig) |
+ , fFramebuffer(nullptr) |
+ , fColorAttachmentView(colorAttachmentView) |
+ , fMSAAImageResource(nullptr) |
+ , fResolveAttachmentView(nullptr) |
+ , fCachedSimpleRenderPass(nullptr) { |
+ SkASSERT(!desc.fSampleCnt); |
+ fColorValuesPerPixel = 1; |
+ this->createFramebuffer(gpu); |
+ this->registerWithCache(); |
+} |
+ |
+// We're virtually derived from GrSurface (via GrRenderTarget) so its |
+// constructor must be explicitly called. |
+GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu, |
+ const GrSurfaceDesc& desc, |
+ GrGpuResource::LifeCycle lifeCycle, |
+ const GrVkImage::Resource* imageResource, |
+ const GrVkImageView* colorAttachmentView, |
+ Derived) |
+ : GrSurface(gpu, lifeCycle, desc) |
+ , GrVkImage(imageResource) |
+ , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig) |
+ , fFramebuffer(nullptr) |
+ , fColorAttachmentView(colorAttachmentView) |
+ , fMSAAImageResource(nullptr) |
+ , fResolveAttachmentView(nullptr) |
+ , fCachedSimpleRenderPass(nullptr) { |
+ SkASSERT(!desc.fSampleCnt); |
+ fColorValuesPerPixel = 1; |
+ this->createFramebuffer(gpu); |
+} |
+ |
+GrVkRenderTarget* |
+GrVkRenderTarget::Create(GrVkGpu* gpu, |
+ const GrSurfaceDesc& desc, |
+ GrGpuResource::LifeCycle lifeCycle, |
+ const GrVkImage::Resource* imageResource) { |
+ VkFormat pixelFormat; |
+ GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat); |
+ |
+ VkImage colorImage; |
+ |
+ // create msaa surface if necessary |
+ const GrVkImage::Resource* msaaResource = nullptr; |
+ const GrVkImageView* resolveAttachmentView = nullptr; |
+ if (desc.fSampleCnt) { |
+ GrVkImage::ImageDesc msImageDesc; |
+ msImageDesc.fImageType = VK_IMAGE_TYPE_2D; |
+ msImageDesc.fFormat = pixelFormat; |
+ msImageDesc.fWidth = desc.fWidth; |
+ msImageDesc.fHeight = desc.fHeight; |
+ msImageDesc.fLevels = 1; |
+ msImageDesc.fSamples = desc.fSampleCnt; |
+ msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL; |
+ msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; |
+ msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; |
+ |
+ msaaResource = GrVkImage::CreateResource(gpu, msImageDesc); |
+ |
+ if (!msaaResource) { |
+ return nullptr; |
+ } |
+ |
+ // Set color attachment image |
+ colorImage = msaaResource->fImage; |
+ |
+ // Create Resolve attachment view |
+ resolveAttachmentView = GrVkImageView::Create(gpu, imageResource->fImage, pixelFormat, |
+ GrVkImageView::kColor_Type); |
+ if (!resolveAttachmentView) { |
+ msaaResource->unref(gpu); |
+ return nullptr; |
+ } |
+ } else { |
+ // Set color attachment image |
+ colorImage = imageResource->fImage; |
+ } |
+ |
+ // Get color attachment view |
+ const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat, |
+ GrVkImageView::kColor_Type); |
+ if (!colorAttachmentView) { |
+ if (msaaResource) { |
+ resolveAttachmentView->unref(gpu); |
+ msaaResource->unref(gpu); |
+ } |
+ return NULL; |
+ } |
+ |
+ GrVkRenderTarget* texRT; |
+ if (msaaResource) { |
+ texRT = new GrVkRenderTarget(gpu, desc, lifeCycle, imageResource, msaaResource, |
+ colorAttachmentView, resolveAttachmentView); |
+ msaaResource->unref(gpu); |
+ } else { |
+ texRT = new GrVkRenderTarget(gpu, desc, lifeCycle, imageResource, |
+ colorAttachmentView); |
+ } |
+ |
+ return texRT; |
+} |
+ |
+GrVkRenderTarget* |
+GrVkRenderTarget::CreateNewRenderTarget(GrVkGpu* gpu, |
+ const GrSurfaceDesc& desc, |
+ GrGpuResource::LifeCycle lifeCycle, |
+ const GrVkImage::ImageDesc& imageDesc) { |
+ SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); |
+ |
+ const GrVkImage::Resource* imageResource = GrVkImage::CreateResource(gpu, imageDesc); |
+ if (!imageResource) { |
+ return nullptr; |
+ } |
+ |
+ GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource); |
+ // Create() will increment the refCount of the image resource if it succeeds |
+ imageResource->unref(gpu); |
+ |
+ return rt; |
+} |
+ |
+GrVkRenderTarget* |
+GrVkRenderTarget::CreateWrappedRenderTarget(GrVkGpu* gpu, |
+ const GrSurfaceDesc& desc, |
+ GrGpuResource::LifeCycle lifeCycle, |
+ const GrVkImage::Resource* imageResource) { |
+ SkASSERT(imageResource); |
+ |
+ // Note: we assume the caller will unref the imageResource |
+ // Create() will increment the refCount, and we'll unref when we're done with it |
+ return GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource); |
+} |
+ |
+bool GrVkRenderTarget::completeStencilAttachment() { |
+ this->createFramebuffer(this->getVkGpu()); |
+ return true; |
+} |
+ |
+void GrVkRenderTarget::createFramebuffer(GrVkGpu* gpu) { |
+ if (fFramebuffer) { |
+ fFramebuffer->unref(gpu); |
+ } |
+ if (fCachedSimpleRenderPass) { |
+ fCachedSimpleRenderPass->unref(gpu); |
+ } |
+ |
+ // Vulkan requires us to create a compatible renderpass before we can create our framebuffer, |
+ // so we use this to get a (cached) basic renderpass, only for creation. |
+ fCachedSimpleRenderPass = gpu->resourceProvider().findOrCreateCompatibleRenderPass(*this); |
+ |
+ // Stencil attachment view is stored in the base RT stencil attachment |
+ const GrVkImageView* stencilView = this->stencilAttachmentView(); |
+ fFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(), |
+ fCachedSimpleRenderPass, fColorAttachmentView, |
+ fResolveAttachmentView, stencilView); |
+ SkASSERT(fFramebuffer); |
+} |
+ |
+void GrVkRenderTarget::getAttachmentsDescriptor( |
+ GrVkRenderPass::AttachmentsDescriptor* desc, |
+ GrVkRenderPass::AttachmentFlags* attachmentFlags) const { |
+ int colorSamples = this->numColorSamples(); |
+ VkFormat colorFormat; |
+ GrPixelConfigToVkFormat(this->config(), &colorFormat); |
+ desc->fColor.fFormat = colorFormat; |
+ desc->fColor.fSamples = colorSamples ? colorSamples : 1; |
+ *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag; |
+ uint32_t attachmentCount = 1; |
+ if (colorSamples > 0) { |
+ desc->fResolve.fFormat = colorFormat; |
+ desc->fResolve.fSamples = 1; |
+ *attachmentFlags |= GrVkRenderPass::kResolve_AttachmentFlag; |
+ ++attachmentCount; |
+ } |
+ |
+ const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment(); |
+ if (stencil) { |
+ const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil); |
+ desc->fStencil.fFormat = vkStencil->vkFormat(); |
+ desc->fStencil.fSamples = vkStencil->numSamples() ? vkStencil->numSamples() : 1; |
+ // Currently in vulkan stencil and color attachments must all have same number of samples |
+ SkASSERT(desc->fColor.fSamples == desc->fStencil.fSamples); |
+ *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag; |
+ ++attachmentCount; |
+ } |
+ desc->fAttachmentCount = attachmentCount; |
+} |
+ |
+GrVkRenderTarget::~GrVkRenderTarget() { |
+ // either release or abandon should have been called by the owner of this object. |
+ SkASSERT(!fMSAAImageResource); |
+ SkASSERT(!fResolveAttachmentView); |
+ SkASSERT(!fColorAttachmentView); |
+ SkASSERT(!fFramebuffer); |
+ SkASSERT(!fCachedSimpleRenderPass); |
+} |
+ |
+void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) const { |
+ commandBuffer.addResource(this->framebuffer()); |
+ commandBuffer.addResource(this->resource()); |
+ commandBuffer.addResource(this->colorAttachmentView()); |
+ if (this->msaaImageResource()) { |
+ commandBuffer.addResource(this->msaaImageResource()); |
+ commandBuffer.addResource(this->resolveAttachmentView()); |
+ } |
+ if (this->stencilImageResource()) { |
+ commandBuffer.addResource(this->stencilImageResource()); |
+ commandBuffer.addResource(this->stencilAttachmentView()); |
+ } |
+} |
+ |
+void GrVkRenderTarget::releaseInternalObjects() { |
+ GrVkGpu* gpu = this->getVkGpu(); |
+ |
+ if (fMSAAImageResource) { |
+ fMSAAImageResource->unref(gpu); |
+ fMSAAImageResource = nullptr; |
+ } |
+ |
+ if (fResolveAttachmentView) { |
+ fResolveAttachmentView->unref(gpu); |
+ fResolveAttachmentView = nullptr; |
+ } |
+ if (fColorAttachmentView) { |
+ fColorAttachmentView->unref(gpu); |
+ fColorAttachmentView = nullptr; |
+ } |
+ if (fFramebuffer) { |
+ fFramebuffer->unref(gpu); |
+ fFramebuffer = nullptr; |
+ } |
+ if (fCachedSimpleRenderPass) { |
+ fCachedSimpleRenderPass->unref(gpu); |
+ fCachedSimpleRenderPass = nullptr; |
+ } |
+} |
+ |
+void GrVkRenderTarget::abandonInternalObjects() { |
+ if (fMSAAImageResource) { |
+ fMSAAImageResource->unrefAndAbandon(); |
+ fMSAAImageResource = nullptr; |
+ } |
+ |
+ if (fResolveAttachmentView) { |
+ fResolveAttachmentView->unrefAndAbandon(); |
+ fResolveAttachmentView = nullptr; |
+ } |
+ if (fColorAttachmentView) { |
+ fColorAttachmentView->unrefAndAbandon(); |
+ fColorAttachmentView = nullptr; |
+ } |
+ if (fFramebuffer) { |
+ fFramebuffer->unrefAndAbandon(); |
+ fFramebuffer = nullptr; |
+ } |
+ if (fCachedSimpleRenderPass) { |
+ fCachedSimpleRenderPass->unrefAndAbandon(); |
+ fCachedSimpleRenderPass = nullptr; |
+ } |
+} |
+ |
+void GrVkRenderTarget::onRelease() { |
+ this->releaseInternalObjects(); |
+ if (this->shouldFreeResources()) { |
+ this->releaseImage(this->getVkGpu()); |
+ } else { |
+ this->abandonImage(); |
+ } |
+ |
+ GrRenderTarget::onRelease(); |
+} |
+ |
+void GrVkRenderTarget::onAbandon() { |
+ this->abandonInternalObjects(); |
+ this->abandonImage(); |
+ GrRenderTarget::onAbandon(); |
+} |
+ |
+ |
+GrBackendObject GrVkRenderTarget::getRenderTargetHandle() const { |
+ // Currently just passing back the pointer to the main Image::Resource as the handle |
+ return (GrBackendObject)&fResource; |
+} |
+ |
+const GrVkImage::Resource* GrVkRenderTarget::stencilImageResource() const { |
+ const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment(); |
+ if (stencil) { |
+ const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil); |
+ return vkStencil->imageResource(); |
+ } |
+ |
+ return nullptr; |
+} |
+ |
+const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const { |
+ const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment(); |
+ if (stencil) { |
+ const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil); |
+ return vkStencil->stencilView(); |
+ } |
+ |
+ return nullptr; |
+} |
+ |
+ |
+GrVkGpu* GrVkRenderTarget::getVkGpu() const { |
+ SkASSERT(!this->wasDestroyed()); |
+ return static_cast<GrVkGpu*>(this->getGpu()); |
+} |
+ |