Add support for vk image sharing mode and handle queues xfers correctly.

Change-Id: I9dbe6020d67cc452c9cbbdeace68f1d01275b419
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/293559
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Greg Daniel 2020-06-02 11:10:41 -04:00 committed by Skia Commit-Bot
parent 674a5ccd3c
commit aa9d99ff6b
8 changed files with 100 additions and 34 deletions

View File

@ -9,6 +9,9 @@ Milestone 85
* <insert new release notes here>
* Add VkSharingMode field to GrVkImageInfo.
https://review.skia.org/293559
* Move SkBitmapRegionDecoder into client_utils/android.
* Remove SkSurface::MakeFromBackendTextureAsRenderTarget.

View File

@ -149,6 +149,12 @@ struct GrVkYcbcrConversionInfo {
VkFormatFeatureFlags fFormatFeatures;
};
/*
* When wrapping a GrBackendTexture or GrBackendRendenderTarget, the fCurrentQueueFamily should
* either be VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_EXTERNAL, or VK_QUEUE_FAMILY_FOREIGN_EXT. If
* fSharingMode is VK_SHARING_MODE_EXCLUSIVE then fCurrentQueueFamily can also be the graphics
* queue index passed into Skia.
*/
struct GrVkImageInfo {
VkImage fImage;
GrVkAlloc fAlloc;
@ -159,6 +165,7 @@ struct GrVkImageInfo {
uint32_t fCurrentQueueFamily;
GrProtected fProtected;
GrVkYcbcrConversionInfo fYcbcrConversionInfo;
VkSharingMode fSharingMode;
GrVkImageInfo()
: fImage(VK_NULL_HANDLE)
@ -169,7 +176,8 @@ struct GrVkImageInfo {
, fLevelCount(0)
, fCurrentQueueFamily(VK_QUEUE_FAMILY_IGNORED)
, fProtected(GrProtected::kNo)
, fYcbcrConversionInfo() {}
, fYcbcrConversionInfo()
, fSharingMode(VK_SHARING_MODE_EXCLUSIVE) {}
GrVkImageInfo(VkImage image,
GrVkAlloc alloc,
@ -179,7 +187,8 @@ struct GrVkImageInfo {
uint32_t levelCount,
uint32_t currentQueueFamily = VK_QUEUE_FAMILY_IGNORED,
GrProtected isProtected = GrProtected::kNo,
GrVkYcbcrConversionInfo ycbcrConversionInfo = GrVkYcbcrConversionInfo())
GrVkYcbcrConversionInfo ycbcrConversionInfo = GrVkYcbcrConversionInfo(),
VkSharingMode sharingMode = VK_SHARING_MODE_EXCLUSIVE)
: fImage(image)
, fAlloc(alloc)
, fImageTiling(imageTiling)
@ -188,7 +197,8 @@ struct GrVkImageInfo {
, fLevelCount(levelCount)
, fCurrentQueueFamily(currentQueueFamily)
, fProtected(isProtected)
, fYcbcrConversionInfo(ycbcrConversionInfo) {}
, fYcbcrConversionInfo(ycbcrConversionInfo)
, fSharingMode(sharingMode) {}
GrVkImageInfo(const GrVkImageInfo& info, VkImageLayout layout, uint32_t familyQueueIndex)
: fImage(info.fImage)
@ -199,7 +209,8 @@ struct GrVkImageInfo {
, fLevelCount(info.fLevelCount)
, fCurrentQueueFamily(familyQueueIndex)
, fProtected(info.fProtected)
, fYcbcrConversionInfo(info.fYcbcrConversionInfo) {}
, fYcbcrConversionInfo(info.fYcbcrConversionInfo)
, fSharingMode(info.fSharingMode) {}
#if GR_TEST_UTILS
bool operator==(const GrVkImageInfo& that) const {
@ -207,7 +218,8 @@ struct GrVkImageInfo {
fImageTiling == that.fImageTiling && fImageLayout == that.fImageLayout &&
fFormat == that.fFormat && fLevelCount == that.fLevelCount &&
fCurrentQueueFamily == that.fCurrentQueueFamily && fProtected == that.fProtected &&
fYcbcrConversionInfo == that.fYcbcrConversionInfo;
fYcbcrConversionInfo == that.fYcbcrConversionInfo &&
fSharingMode == that.fSharingMode;
}
#endif
};

View File

@ -486,6 +486,7 @@ static GrBackendTexture make_vk_backend_texture(
// "foreign" device we can leave them as external.
imageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
imageInfo.fYcbcrConversionInfo = *ycbcrConversion;
imageInfo.fSharingMode = imageCreateInfo.sharingMode;
*deleteProc = delete_vk_image;
*updateProc = update_vk_image;

View File

@ -1198,7 +1198,8 @@ bool GrVkGpu::updateBuffer(GrVkBuffer* buffer, const void* src,
static bool check_image_info(const GrVkCaps& caps,
const GrVkImageInfo& info,
bool needsAllocation) {
bool needsAllocation,
uint32_t graphicsQueueIndex) {
if (VK_NULL_HANDLE == info.fImage) {
return false;
}
@ -1211,6 +1212,18 @@ static bool check_image_info(const GrVkCaps& caps,
return false;
}
if (info.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED &&
info.fCurrentQueueFamily != VK_QUEUE_FAMILY_EXTERNAL &&
info.fCurrentQueueFamily != VK_QUEUE_FAMILY_FOREIGN_EXT) {
if (info.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) {
if (info.fCurrentQueueFamily != graphicsQueueIndex) {
return false;
}
} else {
return false;
}
}
if (info.fYcbcrConversionInfo.isValid()) {
if (!caps.supportsYcbcrConversion()) {
return false;
@ -1256,7 +1269,8 @@ sk_sp<GrTexture> GrVkGpu::onWrapBackendTexture(const GrBackendTexture& backendTe
return nullptr;
}
if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership)) {
if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership,
this->queueIndex())) {
return nullptr;
}
@ -1282,7 +1296,8 @@ sk_sp<GrTexture> GrVkGpu::onWrapCompressedBackendTexture(const GrBackendTexture&
return nullptr;
}
if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership)) {
if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership,
this->queueIndex())) {
return nullptr;
}
@ -1309,7 +1324,8 @@ sk_sp<GrTexture> GrVkGpu::onWrapRenderableBackendTexture(const GrBackendTexture&
return nullptr;
}
if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership)) {
if (!check_image_info(this->vkCaps(), imageInfo, kAdopt_GrWrapOwnership == ownership,
this->queueIndex())) {
return nullptr;
}
@ -1349,7 +1365,7 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTa
return nullptr;
}
if (!check_image_info(this->vkCaps(), info, false)) {
if (!check_image_info(this->vkCaps(), info, false, this->queueIndex())) {
return nullptr;
}
@ -1382,7 +1398,7 @@ sk_sp<GrRenderTarget> GrVkGpu::onWrapBackendTextureAsRenderTarget(const GrBacken
if (!tex.getVkImageInfo(&imageInfo)) {
return nullptr;
}
if (!check_image_info(this->vkCaps(), imageInfo, false)) {
if (!check_image_info(this->vkCaps(), imageInfo, false, this->queueIndex())) {
return nullptr;
}

View File

@ -13,6 +13,43 @@
#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
GrVkImage::GrVkImage(const GrVkGpu* gpu,
const GrVkImageInfo& info,
sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
GrBackendObjectOwnership ownership,
bool forSecondaryCB)
: fInfo(info)
, fInitialQueueFamily(info.fCurrentQueueFamily)
, fMutableState(std::move(mutableState))
, fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) {
SkASSERT(fMutableState->getImageLayout() == fInfo.fImageLayout);
SkASSERT(fMutableState->getQueueFamilyIndex() == fInfo.fCurrentQueueFamily);
#ifdef SK_DEBUG
// We can't transfer from the non graphics queue to the graphics queue since we can't
// release the image from the original queue without having that queue. This limits us in terms
// of the types of queue indices we can handle.
if (info.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED &&
info.fCurrentQueueFamily != VK_QUEUE_FAMILY_EXTERNAL &&
info.fCurrentQueueFamily != VK_QUEUE_FAMILY_FOREIGN_EXT) {
if (info.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) {
if (info.fCurrentQueueFamily != gpu->queueIndex()) {
SkASSERT(false);
}
} else {
SkASSERT(false);
}
}
#endif
if (forSecondaryCB) {
fResource = nullptr;
} else if (fIsBorrowed) {
fResource = new BorrowedResource(gpu, info.fImage, info.fAlloc, info.fImageTiling);
} else {
SkASSERT(VK_NULL_HANDLE != info.fAlloc.fMemory);
fResource = new Resource(gpu, info.fImage, info.fAlloc, info.fImageTiling);
}
}
VkPipelineStageFlags GrVkImage::LayoutToPipelineSrcStageFlags(const VkImageLayout layout) {
if (VK_IMAGE_LAYOUT_GENERAL == layout) {
return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
@ -116,15 +153,22 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
uint32_t srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
uint32_t dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
if (this->currentQueueFamilyIndex() != VK_QUEUE_FAMILY_IGNORED &&
gpu->queueIndex() != this->currentQueueFamilyIndex()) {
this->currentQueueFamilyIndex() != gpu->queueIndex()) {
// The image still is owned by its original queue family and we need to transfer it into
// ours.
SkASSERT(!releaseFamilyQueue);
SkASSERT(this->currentQueueFamilyIndex() == fInitialQueueFamily);
// We only support transferring from external or foreign queues here and not arbitrary
// ones.
SkASSERT(this->currentQueueFamilyIndex() == VK_QUEUE_FAMILY_EXTERNAL ||
this->currentQueueFamilyIndex() == VK_QUEUE_FAMILY_FOREIGN_EXT);
srcQueueFamilyIndex = this->currentQueueFamilyIndex();
dstQueueFamilyIndex = gpu->queueIndex();
this->setQueueFamilyIndex(gpu->queueIndex());
if (fInfo.fSharingMode == VK_SHARING_MODE_EXCLUSIVE) {
dstQueueFamilyIndex = gpu->queueIndex();
} else {
dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
}
this->setQueueFamilyIndex(dstQueueFamilyIndex);
} else if (releaseFamilyQueue) {
// We are releasing the image so we must transfer the image back to its original queue
// family.
@ -217,6 +261,7 @@ bool GrVkImage::InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImag
info->fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED;
info->fProtected =
(createflags & VK_IMAGE_CREATE_PROTECTED_BIT) ? GrProtected::kYes : GrProtected::kNo;
info->fSharingMode = VK_SHARING_MODE_EXCLUSIVE;
return true;
}

View File

@ -29,22 +29,8 @@ public:
const GrVkImageInfo& info,
sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
GrBackendObjectOwnership ownership,
bool forSecondaryCB = false)
: fInfo(info)
, fInitialQueueFamily(info.fCurrentQueueFamily)
, fMutableState(std::move(mutableState))
, fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) {
SkASSERT(fMutableState->getImageLayout() == fInfo.fImageLayout);
SkASSERT(fMutableState->getQueueFamilyIndex() == fInfo.fCurrentQueueFamily);
if (forSecondaryCB) {
fResource = nullptr;
} else if (fIsBorrowed) {
fResource = new BorrowedResource(gpu, info.fImage, info.fAlloc, info.fImageTiling);
} else {
SkASSERT(VK_NULL_HANDLE != info.fAlloc.fMemory);
fResource = new Resource(gpu, info.fImage, info.fAlloc, info.fImageTiling);
}
}
bool forSecondaryCB = false);
virtual ~GrVkImage();
VkImage image() const {

View File

@ -317,12 +317,14 @@ bool VulkanWindowContext::createSwapchain(int width, int height,
fDestroySwapchainKHR(fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
}
this->createBuffers(swapchainCreateInfo.imageFormat, colorType);
this->createBuffers(swapchainCreateInfo.imageFormat, colorType,
swapchainCreateInfo.imageSharingMode);
return true;
}
void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType) {
void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType,
VkSharingMode sharingMode) {
fGetSwapchainImagesKHR(fDevice, fSwapchain, &fImageCount, nullptr);
SkASSERT(fImageCount);
fImages = new VkImage[fImageCount];
@ -342,6 +344,7 @@ void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType)
info.fFormat = format;
info.fLevelCount = 1;
info.fCurrentQueueFamily = fPresentQueueIndex;
info.fSharingMode = sharingMode;
if (fSampleCount == 1) {
GrBackendRenderTarget backendRT(fWidth, fHeight, fSampleCount, info);

View File

@ -61,7 +61,7 @@ private:
BackbufferInfo* getAvailableBackbuffer();
bool createSwapchain(int width, int height, const DisplayParams& params);
void createBuffers(VkFormat format, SkColorType colorType);
void createBuffers(VkFormat format, SkColorType colorType, VkSharingMode);
void destroyBuffers();
VkInstance fInstance = VK_NULL_HANDLE;