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:
Greg Daniel 2018-08-30 16:39:34 -04:00 committed by Skia Commit-Bot
parent 03a47063de
commit ecddbc0126
5 changed files with 50 additions and 8 deletions

View File

@ -63,6 +63,7 @@ struct GrVkImageInfo {
VkImageLayout fImageLayout; VkImageLayout fImageLayout;
VkFormat fFormat; VkFormat fFormat;
uint32_t fLevelCount; uint32_t fLevelCount;
uint32_t fCurrentQueueFamily;
GrVkImageInfo() GrVkImageInfo()
: fImage(VK_NULL_HANDLE) : fImage(VK_NULL_HANDLE)
@ -70,16 +71,19 @@ struct GrVkImageInfo {
, fImageTiling(VK_IMAGE_TILING_OPTIMAL) , fImageTiling(VK_IMAGE_TILING_OPTIMAL)
, fImageLayout(VK_IMAGE_LAYOUT_UNDEFINED) , fImageLayout(VK_IMAGE_LAYOUT_UNDEFINED)
, fFormat(VK_FORMAT_UNDEFINED) , fFormat(VK_FORMAT_UNDEFINED)
, fLevelCount(0) {} , fLevelCount(0)
, fCurrentQueueFamily(VK_QUEUE_FAMILY_IGNORED) {}
GrVkImageInfo(VkImage image, GrVkAlloc alloc, VkImageTiling imageTiling, VkImageLayout layout, 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) : fImage(image)
, fAlloc(alloc) , fAlloc(alloc)
, fImageTiling(imageTiling) , fImageTiling(imageTiling)
, fImageLayout(layout) , fImageLayout(layout)
, fFormat(format) , fFormat(format)
, fLevelCount(levelCount) {} , fLevelCount(levelCount)
, fCurrentQueueFamily(currentQueueFamily) {}
GrVkImageInfo(const GrVkImageInfo& info, VkImageLayout layout) GrVkImageInfo(const GrVkImageInfo& info, VkImageLayout layout)
: fImage(info.fImage) : fImage(info.fImage)
@ -87,7 +91,8 @@ struct GrVkImageInfo {
, fImageTiling(info.fImageTiling) , fImageTiling(info.fImageTiling)
, fImageLayout(layout) , fImageLayout(layout)
, fFormat(info.fFormat) , 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 // 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 // while we're still holding onto the wrapped texture. They will first need to get a handle

View File

@ -120,6 +120,7 @@ GrVkGpu::GrVkGpu(GrContext* context, const GrContextOptions& options,
, fInstance(backendContext.fInstance) , fInstance(backendContext.fInstance)
, fDevice(backendContext.fDevice) , fDevice(backendContext.fDevice)
, fQueue(backendContext.fQueue) , fQueue(backendContext.fQueue)
, fQueueIndex(backendContext.fGraphicsQueueIndex)
, fResourceProvider(this) , fResourceProvider(this)
, fDisconnected(false) { , fDisconnected(false) {
SkASSERT(!backendContext.fOwnsInstanceAndDevice); SkASSERT(!backendContext.fOwnsInstanceAndDevice);

View File

@ -53,6 +53,7 @@ public:
VkDevice device() const { return fDevice; } VkDevice device() const { return fDevice; }
VkQueue queue() const { return fQueue; } VkQueue queue() const { return fQueue; }
uint32_t queueIndex() const { return fQueueIndex; }
VkCommandPool cmdPool() const { return fCmdPool; } VkCommandPool cmdPool() const { return fCmdPool; }
VkPhysicalDeviceProperties physicalDeviceProperties() const { VkPhysicalDeviceProperties physicalDeviceProperties() const {
return fPhysDevProps; return fPhysDevProps;
@ -234,6 +235,7 @@ private:
VkInstance fInstance; VkInstance fInstance;
VkDevice fDevice; VkDevice fDevice;
VkQueue fQueue; // Must be Graphics queue VkQueue fQueue; // Must be Graphics queue
uint32_t fQueueIndex;
// Created by GrVkGpu // Created by GrVkGpu
GrVkResourceProvider fResourceProvider; GrVkResourceProvider fResourceProvider;

View File

@ -80,11 +80,16 @@ VkImageAspectFlags vk_format_to_aspect_flags(VkFormat format) {
void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout, void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
VkAccessFlags dstAccessMask, VkAccessFlags dstAccessMask,
VkPipelineStageFlags dstStageMask, VkPipelineStageFlags dstStageMask,
bool byRegion) { bool byRegion, bool releaseFamilyQueue) {
SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED != newLayout && SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED != newLayout &&
VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout); VK_IMAGE_LAYOUT_PREINITIALIZED != newLayout);
VkImageLayout currentLayout = this->currentLayout(); 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 // 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. // to put in a barrier.
if (newLayout == currentLayout && if (newLayout == currentLayout &&
@ -98,6 +103,28 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
VkPipelineStageFlags srcStageMask = GrVkImage::LayoutToPipelineStageFlags(currentLayout); VkPipelineStageFlags srcStageMask = GrVkImage::LayoutToPipelineStageFlags(currentLayout);
VkImageAspectFlags aspectFlags = vk_format_to_aspect_flags(fInfo.fFormat); 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 = { VkImageMemoryBarrier imageMemoryBarrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
nullptr, // pNext nullptr, // pNext
@ -105,8 +132,8 @@ void GrVkImage::setImageLayout(const GrVkGpu* gpu, VkImageLayout newLayout,
dstAccessMask, // inputMask dstAccessMask, // inputMask
currentLayout, // oldLayout currentLayout, // oldLayout
newLayout, // newLayout newLayout, // newLayout
VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex srcQueueFamilyIndex, // srcQueueFamilyIndex
VK_QUEUE_FAMILY_IGNORED, // dstQueueFamilyIndex dstQueueFamilyIndex, // dstQueueFamilyIndex
fInfo.fImage, // image fInfo.fImage, // image
{ aspectFlags, 0, fInfo.fLevelCount, 0, 1 } // subresourceRange { 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->fImageLayout = initialLayout;
info->fFormat = imageDesc.fFormat; info->fFormat = imageDesc.fFormat;
info->fLevelCount = imageDesc.fLevels; info->fLevelCount = imageDesc.fLevels;
info->fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED;
return true; return true;
} }
@ -187,6 +215,9 @@ GrVkImage::~GrVkImage() {
} }
void GrVkImage::releaseImage(const GrVkGpu* gpu) { void GrVkImage::releaseImage(const GrVkGpu* gpu) {
if (fInfo.fCurrentQueueFamily != fInitialQueueFamily) {
this->setImageLayout(gpu, fInfo.fImageLayout, 0, 0, false, true);
}
if (fResource) { if (fResource) {
fResource->unref(gpu); fResource->unref(gpu);
fResource = nullptr; fResource = nullptr;

View File

@ -27,6 +27,7 @@ public:
GrVkImage(const GrVkImageInfo& info, sk_sp<GrVkImageLayout> layout, GrVkImage(const GrVkImageInfo& info, sk_sp<GrVkImageLayout> layout,
GrBackendObjectOwnership ownership) GrBackendObjectOwnership ownership)
: fInfo(info) : fInfo(info)
, fInitialQueueFamily(info.fCurrentQueueFamily)
, fLayout(std::move(layout)) , fLayout(std::move(layout))
, fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) { , fIsBorrowed(GrBackendObjectOwnership::kBorrowed == ownership) {
SkASSERT(fLayout->getImageLayout() == fInfo.fImageLayout); SkASSERT(fLayout->getImageLayout() == fInfo.fImageLayout);
@ -58,7 +59,8 @@ public:
VkImageLayout newLayout, VkImageLayout newLayout,
VkAccessFlags dstAccessMask, VkAccessFlags dstAccessMask,
VkPipelineStageFlags dstStageMask, 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 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 // 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); void setNewResource(VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling);
GrVkImageInfo fInfo; GrVkImageInfo fInfo;
uint32_t fInitialQueueFamily;
sk_sp<GrVkImageLayout> fLayout; sk_sp<GrVkImageLayout> fLayout;
bool fIsBorrowed; bool fIsBorrowed;