Add support for switching family queues in vulkan.
Bug: skia: Change-Id: Ie4f620a96d1a6f7662819590d97073a694159f96 Reviewed-on: https://skia-review.googlesource.com/150483 Commit-Queue: Greg Daniel <egdaniel@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
03a47063de
commit
ecddbc0126
@ -63,6 +63,7 @@ struct GrVkImageInfo {
|
||||
VkImageLayout fImageLayout;
|
||||
VkFormat fFormat;
|
||||
uint32_t fLevelCount;
|
||||
uint32_t fCurrentQueueFamily;
|
||||
|
||||
GrVkImageInfo()
|
||||
: fImage(VK_NULL_HANDLE)
|
||||
@ -70,16 +71,19 @@ struct GrVkImageInfo {
|
||||
, fImageTiling(VK_IMAGE_TILING_OPTIMAL)
|
||||
, fImageLayout(VK_IMAGE_LAYOUT_UNDEFINED)
|
||||
, fFormat(VK_FORMAT_UNDEFINED)
|
||||
, fLevelCount(0) {}
|
||||
, fLevelCount(0)
|
||||
, fCurrentQueueFamily(VK_QUEUE_FAMILY_IGNORED) {}
|
||||
|
||||
GrVkImageInfo(VkImage image, GrVkAlloc alloc, VkImageTiling imageTiling, VkImageLayout layout,
|
||||
VkFormat format, uint32_t levelCount)
|
||||
VkFormat format, uint32_t levelCount,
|
||||
uint32_t currentQueueFamily = VK_QUEUE_FAMILY_IGNORED)
|
||||
: fImage(image)
|
||||
, fAlloc(alloc)
|
||||
, fImageTiling(imageTiling)
|
||||
, fImageLayout(layout)
|
||||
, fFormat(format)
|
||||
, fLevelCount(levelCount) {}
|
||||
, fLevelCount(levelCount)
|
||||
, fCurrentQueueFamily(currentQueueFamily) {}
|
||||
|
||||
GrVkImageInfo(const GrVkImageInfo& info, VkImageLayout layout)
|
||||
: fImage(info.fImage)
|
||||
@ -87,7 +91,8 @@ struct GrVkImageInfo {
|
||||
, fImageTiling(info.fImageTiling)
|
||||
, fImageLayout(layout)
|
||||
, fFormat(info.fFormat)
|
||||
, fLevelCount(info.fLevelCount) {}
|
||||
, fLevelCount(info.fLevelCount)
|
||||
, fCurrentQueueFamily(info.fCurrentQueueFamily) {}
|
||||
|
||||
// This gives a way for a client to update the layout of the Image if they change the layout
|
||||
// while we're still holding onto the wrapped texture. They will first need to get a handle
|
||||
|
@ -120,6 +120,7 @@ GrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
|
||||
, fInstance(backendContext.fInstance)
|
||||
, fDevice(backendContext.fDevice)
|
||||
, fQueue(backendContext.fQueue)
|
||||
, fQueueIndex(backendContext.fGraphicsQueueIndex)
|
||||
, fResourceProvider(this)
|
||||
, fDisconnected(false) {
|
||||
SkASSERT(!backendContext.fOwnsInstanceAndDevice);
|
||||
|
@ -53,6 +53,7 @@ public:
|
||||
|
||||
VkDevice device() const { return fDevice; }
|
||||
VkQueue queue() const { return fQueue; }
|
||||
uint32_t queueIndex() const { return fQueueIndex; }
|
||||
VkCommandPool cmdPool() const { return fCmdPool; }
|
||||
VkPhysicalDeviceProperties physicalDeviceProperties() const {
|
||||
return fPhysDevProps;
|
||||
@ -234,6 +235,7 @@ private:
|
||||
VkInstance fInstance;
|
||||
VkDevice fDevice;
|
||||
VkQueue fQueue; // Must be Graphics queue
|
||||
uint32_t fQueueIndex;
|
||||
|
||||
// Created by GrVkGpu
|
||||
GrVkResourceProvider fResourceProvider;
|
||||
|
@ -80,11 +80,16 @@ VkImageAspectFlags vk_format_to_aspect_flags(VkFormat format) {
|
||||
void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
|
||||
VkAccessFlags dstAccessMask,
|
||||
VkPipelineStageFlags dstStageMask,
|
||||
bool byRegion) {
|
||||
bool byRegion, bool releaseFamilyQueue) {
|
||||
SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED != newLayout &&
|
||||
VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout);
|
||||
VkImageLayout currentLayout = this->currentLayout();
|
||||
|
||||
if (releaseFamilyQueue && fInfo.fCurrentQueueFamily == fInitialQueueFamily) {
|
||||
// We never transfered the image to this queue and we are releasing it so don't do anything.
|
||||
return;
|
||||
}
|
||||
|
||||
// If the old and new layout are the same and the layout is a read only layout, there is no need
|
||||
// to put in a barrier.
|
||||
if (newLayout == currentLayout &&
|
||||
@ -98,6 +103,28 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
|
||||
VkPipelineStageFlags srcStageMask = GrVkImage::LayoutToPipelineStageFlags(currentLayout);
|
||||
|
||||
VkImageAspectFlags aspectFlags = vk_format_to_aspect_flags(fInfo.fFormat);
|
||||
|
||||
uint32_t srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
uint32_t dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
if (fInfo.fCurrentQueueFamily != VK_QUEUE_FAMILY_IGNORED &&
|
||||
gpu->queueIndex() != fInfo.fCurrentQueueFamily) {
|
||||
// The image still is owned by its original queue family and we need to transfer it into
|
||||
// ours.
|
||||
SkASSERT(!releaseFamilyQueue);
|
||||
SkASSERT(fInfo.fCurrentQueueFamily == fInitialQueueFamily);
|
||||
|
||||
srcQueueFamilyIndex = fInfo.fCurrentQueueFamily;
|
||||
dstQueueFamilyIndex = gpu->queueIndex();
|
||||
fInfo.fCurrentQueueFamily = gpu->queueIndex();
|
||||
} else if (releaseFamilyQueue) {
|
||||
// We are releasing the image so we must transfer the image back to its original queue
|
||||
// family.
|
||||
SkASSERT(fInfo.fCurrentQueueFamily == gpu->queueIndex());
|
||||
srcQueueFamilyIndex = fInfo.fCurrentQueueFamily;
|
||||
dstQueueFamilyIndex = fInitialQueueFamily;
|
||||
fInfo.fCurrentQueueFamily = fInitialQueueFamily;
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier imageMemoryBarrier = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
|
||||
nullptr, // pNext
|
||||
@ -105,8 +132,8 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
|
||||
dstAccessMask, // inputMask
|
||||
currentLayout, // oldLayout
|
||||
newLayout, // newLayout
|
||||
VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
|
||||
VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex
|
||||
srcQueueFamilyIndex, // srcQueueFamilyIndex
|
||||
dstQueueFamilyIndex, // dstQueueFamilyIndex
|
||||
fInfo.fImage, // image
|
||||
{ aspectFlags, 0, fInfo.fLevelCount, 0, 1 } // subresourceRange
|
||||
};
|
||||
@ -168,6 +195,7 @@ bool GrVkImage::InitImageInfo(const GrVkGpu* gpu, const ImageDesc& imageDesc, Gr
|
||||
info->fImageLayout = initialLayout;
|
||||
info->fFormat = imageDesc.fFormat;
|
||||
info->fLevelCount = imageDesc.fLevels;
|
||||
info->fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -187,6 +215,9 @@ GrVkImage::~GrVkImage() {
|
||||
}
|
||||
|
||||
void GrVkImage::releaseImage(const GrVkGpu* gpu) {
|
||||
if (fInfo.fCurrentQueueFamily != fInitialQueueFamily) {
|
||||
this->setImageLayout(gpu, fInfo.fImageLayout, 0, 0, false, true);
|
||||
}
|
||||
if (fResource) {
|
||||
fResource->unref(gpu);
|
||||
fResource = nullptr;
|
||||
|
@ -27,6 +27,7 @@ public:
|
||||
GrVkImage(const GrVkImageInfo& info, sk_sp<GrVkImageLayout> layout,
|
||||
GrBackendObjectOwnership ownership)
|
||||
: fInfo(info)
|
||||
, fInitialQueueFamily(info.fCurrentQueueFamily)
|
||||
, fLayout(std::move(layout))
|
||||
, fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) {
|
||||
SkASSERT(fLayout->getImageLayout() == fInfo.fImageLayout);
|
||||
@ -58,7 +59,8 @@ public:
|
||||
VkImageLayout newLayout,
|
||||
VkAccessFlags dstAccessMask,
|
||||
VkPipelineStageFlags dstStageMask,
|
||||
bool byRegion);
|
||||
bool byRegion,
|
||||
bool releaseFamilyQueue = false);
|
||||
|
||||
// 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
|
||||
@ -111,6 +113,7 @@ protected:
|
||||
void setNewResource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling);
|
||||
|
||||
GrVkImageInfo fInfo;
|
||||
uint32_t fInitialQueueFamily;
|
||||
sk_sp<GrVkImageLayout> fLayout;
|
||||
bool fIsBorrowed;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user