/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrVkRenderTarget_DEFINED
#define GrVkRenderTarget_DEFINED
#include "GrVkImage.h"
#include "GrRenderTarget.h"
#include "GrVkRenderPass.h"
#include "GrVkResourceProvider.h"
#include "vk/GrVkTypes.h"
class GrVkCommandBuffer;
class GrVkFramebuffer;
class GrVkGpu;
class GrVkImageView;
class GrVkSecondaryCommandBuffer;
class GrVkStencilAttachment;
struct GrVkImageInfo;
#ifdef SK_BUILD_FOR_WIN
// Windows gives bogus warnings about inheriting asTexture/asRenderTarget via dominance.
#pragma warning(push)
#pragma warning(disable: 4250)
#endif
class GrVkRenderTarget: public GrRenderTarget, public virtual GrVkImage {
public:
static sk_sp<GrVkRenderTarget> MakeWrappedRenderTarget(GrVkGpu*, const GrSurfaceDesc&,
const GrVkImageInfo&,
sk_sp<GrVkImageLayout>);
static sk_sp<GrVkRenderTarget> MakeSecondaryCBRenderTarget(GrVkGpu*, const GrSurfaceDesc&,
const GrVkDrawableInfo& vkInfo);
~GrVkRenderTarget() override;
GrBackendFormat backendFormat() const override { return this->getBackendFormat(); }
const GrVkFramebuffer* framebuffer() const { return fFramebuffer; }
const GrVkImageView* colorAttachmentView() const { return fColorAttachmentView; }
const GrVkResource* msaaImageResource() const {
if (fMSAAImage) {
return fMSAAImage->fResource;
}
return nullptr;
}
GrVkImage* msaaImage() { return fMSAAImage.get(); }
const GrVkImageView* resolveAttachmentView() const { return fResolveAttachmentView; }
const GrVkResource* stencilImageResource() const;
const GrVkImageView* stencilAttachmentView() const;
const GrVkRenderPass* simpleRenderPass() const { return fCachedSimpleRenderPass; }
GrVkResourceProvider::CompatibleRPHandle compatibleRenderPassHandle() const {
SkASSERT(!this->wrapsSecondaryCommandBuffer());
return fCompatibleRPHandle;
}
const GrVkRenderPass* externalRenderPass() const {
SkASSERT(this->wrapsSecondaryCommandBuffer());
// We use the cached simple render pass to hold the external render pass.
return fCachedSimpleRenderPass;
}
bool wrapsSecondaryCommandBuffer() const { return fSecondaryCommandBuffer != nullptr; }
GrVkSecondaryCommandBuffer* getExternalSecondaryCommandBuffer() const {
return fSecondaryCommandBuffer;
}
// override of GrRenderTarget
ResolveType getResolveType() const override {
if (this->numColorSamples() > 1) {
return kCanResolve_ResolveType;
}
return kAutoResolves_ResolveType;
}
bool canAttemptStencilAttachment() const override {
// We don't know the status of the stencil attachment for wrapped external secondary command
// buffers so we just assume we don't have one.
return !this->wrapsSecondaryCommandBuffer();
}
GrBackendRenderTarget getBackendRenderTarget() const override;
void getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc,
GrVkRenderPass::AttachmentFlags* flags) const;
void addResources(GrVkCommandBuffer& commandBuffer) const;
protected:
GrVkRenderTarget(GrVkGpu* gpu,
const GrSurfaceDesc& desc,
const GrVkImageInfo& info,
sk_sp<GrVkImageLayout> layout,
const GrVkImageInfo& msaaInfo,
sk_sp<GrVkImageLayout> msaaLayout,
const GrVkImageView* colorAttachmentView,
const GrVkImageView* resolveAttachmentView,
GrBackendObjectOwnership);
GrVkRenderTarget(GrVkGpu* gpu,
const GrSurfaceDesc& desc,
const GrVkImageInfo& info,
sk_sp<GrVkImageLayout> layout,
const GrVkImageView* colorAttachmentView,
GrBackendObjectOwnership);
GrVkGpu* getVkGpu() const;
void onAbandon() override;
void onRelease() override;
// This accounts for the texture's memory and any MSAA renderbuffer's memory.
size_t onGpuMemorySize() const override {
int numColorSamples = this->numColorSamples();
if (numColorSamples > 1) {
// Add one to account for the resolved VkImage.
numColorSamples += 1;
}
return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
numColorSamples, GrMipMapped::kNo);
}
void createFramebuffer(GrVkGpu* gpu);
const GrVkImageView* fColorAttachmentView;
std::unique_ptr<GrVkImage> fMSAAImage;
const GrVkImageView* fResolveAttachmentView;
private:
GrVkRenderTarget(GrVkGpu* gpu,
const GrSurfaceDesc& desc,
const GrVkImageInfo& info,
sk_sp<GrVkImageLayout> layout,
const GrVkImageInfo& msaaInfo,
sk_sp<GrVkImageLayout> msaaLayout,
const GrVkImageView* colorAttachmentView,
const GrVkImageView* resolveAttachmentView);
GrVkRenderTarget(GrVkGpu* gpu,
const GrSurfaceDesc& desc,
const GrVkImageInfo& info,
sk_sp<GrVkImageLayout> layout,
const GrVkImageView* colorAttachmentView);
GrVkRenderTarget(GrVkGpu* gpu,
const GrSurfaceDesc& desc,
const GrVkImageInfo& info,
sk_sp<GrVkImageLayout> layout,
const GrVkRenderPass* renderPass,
GrVkSecondaryCommandBuffer* secondaryCommandBuffer);
bool completeStencilAttachment() override;
// In Vulkan we call the release proc after we are finished with the underlying
// GrVkImage::Resource object (which occurs after the GPU has finished all work on it).
void onSetRelease(sk_sp<GrRefCntedCallback> releaseHelper) override {
// Forward the release proc on to GrVkImage
this->setResourceRelease(std::move(releaseHelper));
}
void releaseInternalObjects();
void abandonInternalObjects();
const GrVkFramebuffer* fFramebuffer;
// This is a cached pointer to a simple render pass. The render target should unref it
// once it is done with it.
const GrVkRenderPass* fCachedSimpleRenderPass;
// This is a handle to be used to quickly get compatible GrVkRenderPasses for this render target
GrVkResourceProvider::CompatibleRPHandle fCompatibleRPHandle;
// If this render target wraps an external VkCommandBuffer, then this pointer will be non-null
// and will point to the GrVk object that, in turn, wraps the external VkCommandBuffer. In this
// case the render target will not be backed by an actual VkImage and will thus be limited in
// terms of what it can be used for.
GrVkSecondaryCommandBuffer* fSecondaryCommandBuffer = nullptr;
};
#endif