blob: 2d6a2203c55fc8c33c8b4ceb594fe35b38a902f4 [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.
*/
#ifndef GrVkImage_DEFINED
#define GrVkImage_DEFINED
#include "include/core/SkTypes.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/vk/GrVkTypes.h"
#include "include/private/GrTypesPriv.h"
#include "include/private/GrVkTypesPriv.h"
#include "src/gpu/GrBackendSurfaceMutableStateImpl.h"
#include "src/gpu/GrManagedResource.h"
#include "src/gpu/GrTexture.h"
class GrVkGpu;
class GrVkTexture;
class GrVkImage : SkNoncopyable {
private:
class Resource;
public:
GrVkImage(const GrVkGpu* gpu,
const GrVkImageInfo& info,
sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
GrBackendObjectOwnership ownership,
bool forSecondaryCB = false);
virtual ~GrVkImage();
VkImage image() const {
// Should only be called when we have a real fResource object, i.e. never when being used as
// a RT in an external secondary command buffer.
SkASSERT(fResource);
return fInfo.fImage;
}
const GrVkAlloc& alloc() const {
// Should only be called when we have a real fResource object, i.e. never when being used as
// a RT in an external secondary command buffer.
SkASSERT(fResource);
return fInfo.fAlloc;
}
VkFormat imageFormat() const { return fInfo.fFormat; }
GrBackendFormat getBackendFormat() const {
if (fResource && this->ycbcrConversionInfo().isValid()) {
SkASSERT(this->imageFormat() == this->ycbcrConversionInfo().fFormat);
return GrBackendFormat::MakeVk(this->ycbcrConversionInfo());
}
SkASSERT(this->imageFormat() != VK_FORMAT_UNDEFINED);
return GrBackendFormat::MakeVk(this->imageFormat());
}
uint32_t mipLevels() const { return fInfo.fLevelCount; }
const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const {
// Should only be called when we have a real fResource object, i.e. never when being used as
// a RT in an external secondary command buffer.
SkASSERT(fResource);
return fInfo.fYcbcrConversionInfo;
}
bool supportsInputAttachmentUsage() const {
return fInfo.fImageUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
}
const Resource* resource() const {
SkASSERT(fResource);
return fResource;
}
bool isLinearTiled() const {
// Should only be called when we have a real fResource object, i.e. never when being used as
// a RT in an external secondary command buffer.
SkASSERT(fResource);
return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling);
}
bool isBorrowed() const { return fIsBorrowed; }
sk_sp<GrBackendSurfaceMutableStateImpl> getMutableState() const { return fMutableState; }
VkImageLayout currentLayout() const { return fMutableState->getImageLayout(); }
void setImageLayoutAndQueueIndex(const GrVkGpu* gpu,
VkImageLayout newLayout,
VkAccessFlags dstAccessMask,
VkPipelineStageFlags dstStageMask,
bool byRegion,
uint32_t newQueueFamilyIndex);
void setImageLayout(const GrVkGpu* gpu,
VkImageLayout newLayout,
VkAccessFlags dstAccessMask,
VkPipelineStageFlags dstStageMask,
bool byRegion) {
this->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccessMask, dstStageMask, byRegion,
VK_QUEUE_FAMILY_IGNORED);
}
uint32_t currentQueueFamilyIndex() const { return fMutableState->getQueueFamilyIndex(); }
void setQueueFamilyIndex(uint32_t queueFamilyIndex) {
fMutableState->setQueueFamilyIndex(queueFamilyIndex);
}
// Returns the image to its original queue family and changes the layout to present if the queue
// family is not external or foreign.
void prepareForPresent(GrVkGpu* gpu);
// Returns the image to its original queue family
void prepareForExternal(GrVkGpu* gpu);
// This simply updates our tracking of the image layout and does not actually do any gpu work.
// This is only used for mip map generation where we are manually changing the layouts as we
// blit each layer, and then at the end need to update our tracking.
void updateImageLayout(VkImageLayout newLayout) {
// Should only be called when we have a real fResource object, i.e. never when being used as
// a RT in an external secondary command buffer.
SkASSERT(fResource);
fMutableState->setImageLayout(newLayout);
}
struct ImageDesc {
VkImageType fImageType;
VkFormat fFormat;
uint32_t fWidth;
uint32_t fHeight;
uint32_t fLevels;
uint32_t fSamples;
VkImageTiling fImageTiling;
VkImageUsageFlags fUsageFlags;
VkFlags fMemProps;
GrProtected fIsProtected;
ImageDesc()
: fImageType(VK_IMAGE_TYPE_2D)
, fFormat(VK_FORMAT_UNDEFINED)
, fWidth(0)
, fHeight(0)
, fLevels(1)
, fSamples(1)
, fImageTiling(VK_IMAGE_TILING_OPTIMAL)
, fUsageFlags(0)
, fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
, fIsProtected(GrProtected::kNo) {}
};
static bool InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*);
// Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo
static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*);
// These match the definitions in SkImage, for whence they came
typedef void* ReleaseCtx;
typedef void (*ReleaseProc)(ReleaseCtx);
void setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper);
// Helpers to use for setting the layout of the VkImage
static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout);
static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);
#if GR_TEST_UTILS
void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu);
#endif
protected:
void releaseImage();
bool hasResource() const { return fResource; }
GrVkImageInfo fInfo;
uint32_t fInitialQueueFamily;
sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState;
bool fIsBorrowed;
private:
class Resource : public GrTextureResource {
public:
explicit Resource(const GrVkGpu* gpu)
: fGpu(gpu)
, fImage(VK_NULL_HANDLE) {
fAlloc.fMemory = VK_NULL_HANDLE;
fAlloc.fOffset = 0;
}
Resource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
: fGpu(gpu)
, fImage(image)
, fAlloc(alloc)
, fImageTiling(tiling) {}
~Resource() override {}
#ifdef SK_TRACE_MANAGED_RESOURCES
void dumpInfo() const override {
SkDebugf("GrVkImage: %d (%d refs)\n", fImage, this->getRefCnt());
}
#endif
#ifdef SK_DEBUG
const GrManagedResource* asVkImageResource() const override { return this; }
#endif
private:
void freeGPUData() const override;
const GrVkGpu* fGpu;
VkImage fImage;
GrVkAlloc fAlloc;
VkImageTiling fImageTiling;
using INHERITED = GrTextureResource;
};
// for wrapped textures
class BorrowedResource : public Resource {
public:
BorrowedResource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc,
VkImageTiling tiling)
: Resource(gpu, image, alloc, tiling) {
}
private:
void freeGPUData() const override;
};
Resource* fResource;
friend class GrVkRenderTarget;
};
#endif